Merge tag 'v2.7.0'
This commit is contained in:
commit
c2fcf51421
621 changed files with 18714 additions and 8684 deletions
|
@ -3,7 +3,7 @@ version: 2
|
|||
aliases:
|
||||
- &defaults
|
||||
docker:
|
||||
- image: circleci/ruby:2.5.1-stretch-node
|
||||
- image: circleci/ruby:2.6.0-stretch-node
|
||||
environment: &ruby_environment
|
||||
BUNDLE_APP_CONFIG: ./.bundle/
|
||||
DB_HOST: localhost
|
||||
|
@ -98,21 +98,21 @@ jobs:
|
|||
<<: *defaults
|
||||
<<: *install_steps
|
||||
|
||||
install-ruby2.6:
|
||||
<<: *defaults
|
||||
<<: *install_ruby_dependencies
|
||||
|
||||
install-ruby2.5:
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/ruby:2.5.3-stretch-node
|
||||
environment: *ruby_environment
|
||||
<<: *install_ruby_dependencies
|
||||
|
||||
install-ruby2.4:
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/ruby:2.4.4-stretch-node
|
||||
environment: *ruby_environment
|
||||
<<: *install_ruby_dependencies
|
||||
|
||||
install-ruby2.3:
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/ruby:2.3.7-stretch-node
|
||||
- image: circleci/ruby:2.4.5-stretch-node
|
||||
environment: *ruby_environment
|
||||
<<: *install_ruby_dependencies
|
||||
|
||||
|
@ -128,43 +128,43 @@ jobs:
|
|||
- ./mastodon/public/assets
|
||||
- ./mastodon/public/packs-test/
|
||||
|
||||
test-ruby2.6:
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/ruby:2.6.0-stretch-node
|
||||
environment: *ruby_environment
|
||||
- image: circleci/postgres:10.6-alpine
|
||||
environment:
|
||||
POSTGRES_USER: root
|
||||
- image: circleci/redis:5.0.3-alpine3.8
|
||||
<<: *test_steps
|
||||
|
||||
test-ruby2.5:
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/ruby:2.5.1-stretch-node
|
||||
- image: circleci/ruby:2.5.3-stretch-node
|
||||
environment: *ruby_environment
|
||||
- image: circleci/postgres:10.3-alpine
|
||||
- image: circleci/postgres:10.6-alpine
|
||||
environment:
|
||||
POSTGRES_USER: root
|
||||
- image: circleci/redis:4.0.9-alpine
|
||||
- image: circleci/redis:4.0.12-alpine
|
||||
<<: *test_steps
|
||||
|
||||
test-ruby2.4:
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/ruby:2.4.4-stretch-node
|
||||
- image: circleci/ruby:2.4.5-stretch-node
|
||||
environment: *ruby_environment
|
||||
- image: circleci/postgres:10.3-alpine
|
||||
- image: circleci/postgres:10.6-alpine
|
||||
environment:
|
||||
POSTGRES_USER: root
|
||||
- image: circleci/redis:4.0.9-alpine
|
||||
<<: *test_steps
|
||||
|
||||
test-ruby2.3:
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/ruby:2.3.7-stretch-node
|
||||
environment: *ruby_environment
|
||||
- image: circleci/postgres:10.3-alpine
|
||||
environment:
|
||||
POSTGRES_USER: root
|
||||
- image: circleci/redis:4.0.9-alpine
|
||||
- image: circleci/redis:4.0.12-alpine
|
||||
<<: *test_steps
|
||||
|
||||
test-webui:
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/node:8.11.1-stretch
|
||||
- image: circleci/node:8.15.0-stretch
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- run: ./bin/retry yarn test:jest
|
||||
|
@ -183,20 +183,24 @@ workflows:
|
|||
build-and-test:
|
||||
jobs:
|
||||
- install
|
||||
- install-ruby2.6:
|
||||
requires:
|
||||
- install
|
||||
- install-ruby2.5:
|
||||
requires:
|
||||
- install
|
||||
- install-ruby2.6
|
||||
- install-ruby2.4:
|
||||
requires:
|
||||
- install
|
||||
- install-ruby2.5
|
||||
- install-ruby2.3:
|
||||
requires:
|
||||
- install
|
||||
- install-ruby2.5
|
||||
- install-ruby2.6
|
||||
- build:
|
||||
requires:
|
||||
- install-ruby2.5
|
||||
- install-ruby2.6
|
||||
- test-ruby2.6:
|
||||
requires:
|
||||
- install-ruby2.6
|
||||
- build
|
||||
- test-ruby2.5:
|
||||
requires:
|
||||
- install-ruby2.5
|
||||
|
@ -205,13 +209,9 @@ workflows:
|
|||
requires:
|
||||
- install-ruby2.4
|
||||
- build
|
||||
- test-ruby2.3:
|
||||
requires:
|
||||
- install-ruby2.3
|
||||
- build
|
||||
- test-webui:
|
||||
requires:
|
||||
- install
|
||||
- check-i18n:
|
||||
requires:
|
||||
- install-ruby2.5
|
||||
- install-ruby2.6
|
||||
|
|
|
@ -27,7 +27,7 @@ plugins:
|
|||
enabled: true
|
||||
eslint:
|
||||
enabled: true
|
||||
channel: eslint-4
|
||||
channel: eslint-5
|
||||
rubocop:
|
||||
enabled: true
|
||||
channel: rubocop-0-54
|
||||
|
|
|
@ -1,30 +1,13 @@
|
|||
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
|
||||
#
|
||||
# If you find yourself ignoring temporary files generated by your text editor
|
||||
# or operating system, you probably want to add a global ignore instead:
|
||||
# git config --global core.excludesfile '~/.gitignore_global'
|
||||
|
||||
# Ignore bundler config.
|
||||
/.bundle
|
||||
|
||||
# Ignore the default SQLite database.
|
||||
/db/*.sqlite3
|
||||
/db/*.sqlite3-journal
|
||||
|
||||
# Ignore all logfiles and tempfiles.
|
||||
/log/*
|
||||
!/log/.keep
|
||||
/tmp
|
||||
coverage
|
||||
public/system
|
||||
public/assets
|
||||
.env
|
||||
.env.production
|
||||
node_modules/
|
||||
neo4j/
|
||||
|
||||
# Ignore Vagrant files
|
||||
.vagrant/
|
||||
|
||||
# Ignore Capistrano customizations
|
||||
config/deploy/*
|
||||
/build/**
|
||||
/coverage/**
|
||||
/db/**
|
||||
/lib/**
|
||||
/log/**
|
||||
/node_modules/**
|
||||
/nonobox/**
|
||||
/public/**
|
||||
!/public/embed.js
|
||||
/spec/**
|
||||
/tmp/**
|
||||
/vendor/**
|
||||
!.eslintrc.js
|
||||
|
|
199
.eslintrc.js
Normal file
199
.eslintrc.js
Normal file
|
@ -0,0 +1,199 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
es6: true,
|
||||
jest: true,
|
||||
},
|
||||
|
||||
globals: {
|
||||
ATTACHMENT_HOST: false,
|
||||
},
|
||||
|
||||
parser: 'babel-eslint',
|
||||
|
||||
plugins: [
|
||||
'react',
|
||||
'jsx-a11y',
|
||||
'import',
|
||||
'promise',
|
||||
],
|
||||
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
ecmaFeatures: {
|
||||
experimentalObjectRestSpread: true,
|
||||
jsx: true,
|
||||
},
|
||||
ecmaVersion: 2018,
|
||||
},
|
||||
|
||||
settings: {
|
||||
react: {
|
||||
version: 'detect',
|
||||
},
|
||||
'import/extensions': [
|
||||
'.js',
|
||||
],
|
||||
'import/ignore': [
|
||||
'node_modules',
|
||||
'\\.(css|scss|json)$',
|
||||
],
|
||||
},
|
||||
|
||||
rules: {
|
||||
'brace-style': 'warn',
|
||||
'comma-dangle': ['error', 'always-multiline'],
|
||||
'comma-spacing': [
|
||||
'warn',
|
||||
{
|
||||
before: false,
|
||||
after: true,
|
||||
},
|
||||
],
|
||||
'comma-style': ['warn', 'last'],
|
||||
'consistent-return': 'error',
|
||||
'dot-notation': 'error',
|
||||
eqeqeq: 'error',
|
||||
indent: ['warn', 2],
|
||||
'jsx-quotes': ['error', 'prefer-single'],
|
||||
'no-catch-shadow': 'error',
|
||||
'no-cond-assign': 'error',
|
||||
'no-console': [
|
||||
'warn',
|
||||
{
|
||||
allow: [
|
||||
'error',
|
||||
'warn',
|
||||
],
|
||||
},
|
||||
],
|
||||
'no-fallthrough': 'error',
|
||||
'no-irregular-whitespace': 'error',
|
||||
'no-mixed-spaces-and-tabs': 'warn',
|
||||
'no-nested-ternary': 'warn',
|
||||
'no-trailing-spaces': 'warn',
|
||||
'no-undef': 'error',
|
||||
'no-unreachable': 'error',
|
||||
'no-unused-expressions': 'error',
|
||||
'no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
vars: 'all',
|
||||
args: 'after-used',
|
||||
ignoreRestSiblings: true,
|
||||
},
|
||||
],
|
||||
'object-curly-spacing': ['error', 'always'],
|
||||
'padded-blocks': [
|
||||
'error',
|
||||
{
|
||||
classes: 'always',
|
||||
},
|
||||
],
|
||||
quotes: ['error', 'single'],
|
||||
semi: 'error',
|
||||
strict: 'off',
|
||||
'valid-typeof': 'error',
|
||||
|
||||
'react/jsx-boolean-value': 'error',
|
||||
'react/jsx-closing-bracket-location': ['error', 'line-aligned'],
|
||||
'react/jsx-curly-spacing': 'error',
|
||||
'react/jsx-equals-spacing': 'error',
|
||||
'react/jsx-first-prop-new-line': ['error', 'multiline-multiprop'],
|
||||
'react/jsx-indent': ['error', 2],
|
||||
'react/jsx-no-bind': 'error',
|
||||
'react/jsx-no-duplicate-props': 'error',
|
||||
'react/jsx-no-undef': 'error',
|
||||
'react/jsx-tag-spacing': 'error',
|
||||
'react/jsx-uses-react': 'error',
|
||||
'react/jsx-uses-vars': 'error',
|
||||
'react/jsx-wrap-multilines': 'error',
|
||||
'react/no-multi-comp': 'off',
|
||||
'react/no-string-refs': 'error',
|
||||
'react/prop-types': 'error',
|
||||
'react/self-closing-comp': 'error',
|
||||
|
||||
'jsx-a11y/accessible-emoji': 'warn',
|
||||
'jsx-a11y/alt-text': 'warn',
|
||||
'jsx-a11y/anchor-has-content': 'warn',
|
||||
'jsx-a11y/anchor-is-valid': [
|
||||
'warn',
|
||||
{
|
||||
components: [
|
||||
'Link',
|
||||
'NavLink',
|
||||
],
|
||||
specialLink: [
|
||||
'to',
|
||||
],
|
||||
aspect: [
|
||||
'noHref',
|
||||
'invalidHref',
|
||||
'preferButton',
|
||||
],
|
||||
},
|
||||
],
|
||||
'jsx-a11y/aria-activedescendant-has-tabindex': 'warn',
|
||||
'jsx-a11y/aria-props': 'warn',
|
||||
'jsx-a11y/aria-proptypes': 'warn',
|
||||
'jsx-a11y/aria-role': 'warn',
|
||||
'jsx-a11y/aria-unsupported-elements': 'warn',
|
||||
'jsx-a11y/heading-has-content': 'warn',
|
||||
'jsx-a11y/html-has-lang': 'warn',
|
||||
'jsx-a11y/iframe-has-title': 'warn',
|
||||
'jsx-a11y/img-redundant-alt': 'warn',
|
||||
'jsx-a11y/interactive-supports-focus': 'warn',
|
||||
'jsx-a11y/label-has-for': 'off',
|
||||
'jsx-a11y/mouse-events-have-key-events': 'warn',
|
||||
'jsx-a11y/no-access-key': 'warn',
|
||||
'jsx-a11y/no-distracting-elements': 'warn',
|
||||
'jsx-a11y/no-noninteractive-element-interactions': [
|
||||
'warn',
|
||||
{
|
||||
handlers: [
|
||||
'onClick',
|
||||
],
|
||||
},
|
||||
],
|
||||
'jsx-a11y/no-onchange': 'warn',
|
||||
'jsx-a11y/no-redundant-roles': 'warn',
|
||||
'jsx-a11y/no-static-element-interactions': [
|
||||
'warn',
|
||||
{
|
||||
handlers: [
|
||||
'onClick',
|
||||
],
|
||||
},
|
||||
],
|
||||
'jsx-a11y/role-has-required-aria-props': 'warn',
|
||||
'jsx-a11y/role-supports-aria-props': 'off',
|
||||
'jsx-a11y/scope': 'warn',
|
||||
'jsx-a11y/tabindex-no-positive': 'warn',
|
||||
|
||||
'import/extensions': [
|
||||
'error',
|
||||
'always',
|
||||
{
|
||||
js: 'never',
|
||||
},
|
||||
],
|
||||
'import/newline-after-import': 'error',
|
||||
'import/no-extraneous-dependencies': [
|
||||
'error',
|
||||
{
|
||||
devDependencies: [
|
||||
'config/webpack/**',
|
||||
'app/javascript/mastodon/test_setup.js',
|
||||
'app/javascript/**/__tests__/**',
|
||||
],
|
||||
},
|
||||
],
|
||||
'import/no-unresolved': 'error',
|
||||
'import/no-webpack-loader-syntax': 'error',
|
||||
|
||||
'promise/catch-or-return': 'error',
|
||||
},
|
||||
};
|
170
.eslintrc.yml
170
.eslintrc.yml
|
@ -1,170 +0,0 @@
|
|||
---
|
||||
root: true
|
||||
|
||||
env:
|
||||
browser: true
|
||||
node: true
|
||||
es6: true
|
||||
jest: true
|
||||
|
||||
globals:
|
||||
ATTACHMENT_HOST: false
|
||||
|
||||
parser: babel-eslint
|
||||
|
||||
plugins:
|
||||
- react
|
||||
- jsx-a11y
|
||||
- import
|
||||
- promise
|
||||
|
||||
parserOptions:
|
||||
sourceType: module
|
||||
ecmaFeatures:
|
||||
experimentalObjectRestSpread: true
|
||||
jsx: true
|
||||
ecmaVersion: 2018
|
||||
|
||||
settings:
|
||||
import/extensions:
|
||||
- .js
|
||||
import/ignore:
|
||||
- node_modules
|
||||
- \\.(css|scss|json)$
|
||||
|
||||
rules:
|
||||
brace-style: warn
|
||||
comma-dangle:
|
||||
- error
|
||||
- always-multiline
|
||||
comma-spacing:
|
||||
- warn
|
||||
- before: false
|
||||
after: true
|
||||
comma-style:
|
||||
- warn
|
||||
- last
|
||||
consistent-return: error
|
||||
dot-notation: error
|
||||
eqeqeq: error
|
||||
indent:
|
||||
- warn
|
||||
- 2
|
||||
jsx-quotes:
|
||||
- error
|
||||
- prefer-single
|
||||
no-catch-shadow: error
|
||||
no-cond-assign: error
|
||||
no-console:
|
||||
- warn
|
||||
- allow:
|
||||
- error
|
||||
- warn
|
||||
no-fallthrough: error
|
||||
no-irregular-whitespace: error
|
||||
no-mixed-spaces-and-tabs: warn
|
||||
no-nested-ternary: warn
|
||||
no-trailing-spaces: warn
|
||||
no-undef: error
|
||||
no-unreachable: error
|
||||
no-unused-expressions: error
|
||||
no-unused-vars:
|
||||
- error
|
||||
- vars: all
|
||||
args: after-used
|
||||
ignoreRestSiblings: true
|
||||
object-curly-spacing:
|
||||
- error
|
||||
- always
|
||||
padded-blocks:
|
||||
- error
|
||||
- classes: always
|
||||
quotes:
|
||||
- error
|
||||
- single
|
||||
semi: error
|
||||
strict: off
|
||||
valid-typeof: error
|
||||
|
||||
react/jsx-boolean-value: error
|
||||
react/jsx-closing-bracket-location:
|
||||
- error
|
||||
- line-aligned
|
||||
react/jsx-curly-spacing: error
|
||||
react/jsx-equals-spacing: error
|
||||
react/jsx-first-prop-new-line:
|
||||
- error
|
||||
- multiline-multiprop
|
||||
react/jsx-indent:
|
||||
- error
|
||||
- 2
|
||||
react/jsx-no-bind: error
|
||||
react/jsx-no-duplicate-props: error
|
||||
react/jsx-no-undef: error
|
||||
react/jsx-tag-spacing: error
|
||||
react/jsx-uses-react: error
|
||||
react/jsx-uses-vars: error
|
||||
react/jsx-wrap-multilines: error
|
||||
react/no-multi-comp: off
|
||||
react/no-string-refs: error
|
||||
react/prop-types: error
|
||||
react/self-closing-comp: error
|
||||
|
||||
jsx-a11y/accessible-emoji: warn
|
||||
jsx-a11y/alt-text: warn
|
||||
jsx-a11y/anchor-has-content: warn
|
||||
jsx-a11y/anchor-is-valid:
|
||||
- warn
|
||||
- components:
|
||||
- Link
|
||||
- NavLink
|
||||
specialLink:
|
||||
- to
|
||||
aspect:
|
||||
- noHref
|
||||
- invalidHref
|
||||
- preferButton
|
||||
jsx-a11y/aria-activedescendant-has-tabindex: warn
|
||||
jsx-a11y/aria-props: warn
|
||||
jsx-a11y/aria-proptypes: warn
|
||||
jsx-a11y/aria-role: warn
|
||||
jsx-a11y/aria-unsupported-elements: warn
|
||||
jsx-a11y/heading-has-content: warn
|
||||
jsx-a11y/html-has-lang: warn
|
||||
jsx-a11y/iframe-has-title: warn
|
||||
jsx-a11y/img-redundant-alt: warn
|
||||
jsx-a11y/interactive-supports-focus: warn
|
||||
jsx-a11y/label-has-for: off
|
||||
jsx-a11y/mouse-events-have-key-events: warn
|
||||
jsx-a11y/no-access-key: warn
|
||||
jsx-a11y/no-distracting-elements: warn
|
||||
jsx-a11y/no-noninteractive-element-interactions:
|
||||
- warn
|
||||
- handlers:
|
||||
- onClick
|
||||
jsx-a11y/no-onchange: warn
|
||||
jsx-a11y/no-redundant-roles: warn
|
||||
jsx-a11y/no-static-element-interactions:
|
||||
- warn
|
||||
- handlers:
|
||||
- onClick
|
||||
jsx-a11y/role-has-required-aria-props: warn
|
||||
jsx-a11y/role-supports-aria-props: off
|
||||
jsx-a11y/scope: warn
|
||||
jsx-a11y/tabindex-no-positive: warn
|
||||
|
||||
import/extensions:
|
||||
- error
|
||||
- always
|
||||
- js: never
|
||||
import/newline-after-import: error
|
||||
import/no-extraneous-dependencies:
|
||||
- error
|
||||
- devDependencies:
|
||||
- "config/webpack/**"
|
||||
- "app/javascript/mastodon/test_setup.js"
|
||||
- "app/javascript/**/__tests__/**"
|
||||
import/no-unresolved: error
|
||||
import/no-webpack-loader-syntax: error
|
||||
|
||||
promise/catch-or-return: error
|
|
@ -1,9 +0,0 @@
|
|||
plugins:
|
||||
postcss-smart-import: {}
|
||||
precss: {}
|
||||
autoprefixer:
|
||||
browsers:
|
||||
- last 2 versions
|
||||
- IE >= 11
|
||||
- iOS >= 9
|
||||
postcss-object-fit-images: {}
|
|
@ -1 +1 @@
|
|||
2.5.3
|
||||
2.6.0
|
||||
|
|
337
AUTHORS.md
337
AUTHORS.md
|
@ -1,41 +1,44 @@
|
|||
Authors
|
||||
=======
|
||||
|
||||
Mastodon is available on [GitHub](https://github.com/tootsuite/mastodon)
|
||||
and provided thanks to the work of the following contributors:
|
||||
|
||||
* [Gargron](https://github.com/Gargron)
|
||||
* [ykzts](https://github.com/ykzts)
|
||||
* [akihikodaki](https://github.com/akihikodaki)
|
||||
* [mjankowski](https://github.com/mjankowski)
|
||||
* [ThibG](https://github.com/ThibG)
|
||||
* [mjankowski](https://github.com/mjankowski)
|
||||
* [unarist](https://github.com/unarist)
|
||||
* [m4sk1n](https://github.com/m4sk1n)
|
||||
* [dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* [yiskah](https://github.com/yiskah)
|
||||
* [nolanlawson](https://github.com/nolanlawson)
|
||||
* [sorin-davidoi](https://github.com/sorin-davidoi)
|
||||
* [ysksn](https://github.com/ysksn)
|
||||
* [abcang](https://github.com/abcang)
|
||||
* [lynlynlynx](https://github.com/lynlynlynx)
|
||||
* [dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* [alpaca-tc](https://github.com/alpaca-tc)
|
||||
* [mayaeh](https://github.com/mayaeh)
|
||||
* [renatolond](https://github.com/renatolond)
|
||||
* [nclm](https://github.com/nclm)
|
||||
* [ineffyble](https://github.com/ineffyble)
|
||||
* [renatolond](https://github.com/renatolond)
|
||||
* [jeroenpraat](https://github.com/jeroenpraat)
|
||||
* [mayaeh](https://github.com/mayaeh)
|
||||
* [blackle](https://github.com/blackle)
|
||||
* [Quent-in](https://github.com/Quent-in)
|
||||
* [JantsoP](https://github.com/JantsoP)
|
||||
* [mabkenar](https://github.com/mabkenar)
|
||||
* [nullkal](https://github.com/nullkal)
|
||||
* [yookoala](https://github.com/yookoala)
|
||||
* [mabkenar](https://github.com/mabkenar)
|
||||
* [ysksn](https://github.com/ysksn)
|
||||
* [Kjwon15](https://github.com/Kjwon15)
|
||||
* [shuheiktgw](https://github.com/shuheiktgw)
|
||||
* [ashfurrow](https://github.com/ashfurrow)
|
||||
* [Kjwon15](https://github.com/Kjwon15)
|
||||
* [Quenty31](https://github.com/Quenty31)
|
||||
* [zunda](https://github.com/zunda)
|
||||
* [eramdam](https://github.com/eramdam)
|
||||
* [masarakki](https://github.com/masarakki)
|
||||
* [takayamaki](https://github.com/takayamaki)
|
||||
* [masarakki](https://github.com/masarakki)
|
||||
* [ticky](https://github.com/ticky)
|
||||
* [Quenty31](https://github.com/Quenty31)
|
||||
* [danhunsaker](https://github.com/danhunsaker)
|
||||
* [ThisIsMissEm](https://github.com/ThisIsMissEm)
|
||||
* [hcmiya](https://github.com/hcmiya)
|
||||
|
@ -88,16 +91,19 @@ and provided thanks to the work of the following contributors:
|
|||
* [mistydemeo](https://github.com/mistydemeo)
|
||||
* [dunn](https://github.com/dunn)
|
||||
* [xqus](https://github.com/xqus)
|
||||
* [hugogameiro](https://github.com/hugogameiro)
|
||||
* [pfm-eyesightjp](https://github.com/pfm-eyesightjp)
|
||||
* [fakenine](https://github.com/fakenine)
|
||||
* [tsuwatch](https://github.com/tsuwatch)
|
||||
* [victorhck](https://github.com/victorhck)
|
||||
* [ashleyhull-versent](https://github.com/ashleyhull-versent)
|
||||
* [kedamaDQ](https://github.com/kedamaDQ)
|
||||
* [puckipedia](https://github.com/puckipedia)
|
||||
* [fvh-P](https://github.com/fvh-P)
|
||||
* [contraexemplo](https://github.com/contraexemplo)
|
||||
* [hugogameiro](https://github.com/hugogameiro)
|
||||
* [kazu9su](https://github.com/kazu9su)
|
||||
* [Komic](https://github.com/Komic)
|
||||
* [lmorchard](https://github.com/lmorchard)
|
||||
* [diomed](https://github.com/diomed)
|
||||
* [ariasuni](https://github.com/ariasuni)
|
||||
* [Neetshin](mailto:neetshin@neetsh.in)
|
||||
|
@ -105,7 +111,6 @@ and provided thanks to the work of the following contributors:
|
|||
* [ProgVal](https://github.com/ProgVal)
|
||||
* [valentin2105](https://github.com/valentin2105)
|
||||
* [yuntan](https://github.com/yuntan)
|
||||
* [ashleyhull-versent](https://github.com/ashleyhull-versent)
|
||||
* [goofy-bz](mailto:goofy@babelzilla.org)
|
||||
* [kadiix](https://github.com/kadiix)
|
||||
* [kodacs](https://github.com/kodacs)
|
||||
|
@ -119,35 +124,37 @@ and provided thanks to the work of the following contributors:
|
|||
* [northerner](https://github.com/northerner)
|
||||
* [fhemberger](https://github.com/fhemberger)
|
||||
* [greysteil](https://github.com/greysteil)
|
||||
* [hnrysmth](https://github.com/hnrysmth)
|
||||
* [hensmith](https://github.com/hensmith)
|
||||
* [hinaloe](https://github.com/hinaloe)
|
||||
* [d6rkaiz](https://github.com/d6rkaiz)
|
||||
* [Reverite](https://github.com/Reverite)
|
||||
* [JMendyk](https://github.com/JMendyk)
|
||||
* [JohnD28](https://github.com/JohnD28)
|
||||
* [znz](https://github.com/znz)
|
||||
* [Naouak](https://github.com/Naouak)
|
||||
* [pawelngei](https://github.com/pawelngei)
|
||||
* [reneklacan](https://github.com/reneklacan)
|
||||
* [ekiru](https://github.com/ekiru)
|
||||
* [tcitworld](https://github.com/tcitworld)
|
||||
* [geta6](https://github.com/geta6)
|
||||
* [happycoloredbanana](https://github.com/happycoloredbanana)
|
||||
* [kedamaDQ](https://github.com/kedamaDQ)
|
||||
* [leopku](https://github.com/leopku)
|
||||
* [SansPseudoFix](https://github.com/SansPseudoFix)
|
||||
* [tomfhowe](https://github.com/tomfhowe)
|
||||
* [noraworld](https://github.com/noraworld)
|
||||
* [theboss](https://github.com/theboss)
|
||||
* [178inaba](https://github.com/178inaba)
|
||||
* [Aditoo17](https://github.com/Aditoo17)
|
||||
* [alyssais](https://github.com/alyssais)
|
||||
* [kodnaplakal](https://github.com/kodnaplakal)
|
||||
* [stalker314314](https://github.com/stalker314314)
|
||||
* [huertanix](https://github.com/huertanix)
|
||||
* [genesixx](https://github.com/genesixx)
|
||||
* [halkeye](https://github.com/halkeye)
|
||||
* [hinaloe](https://github.com/hinaloe)
|
||||
* [treby](https://github.com/treby)
|
||||
* [Reverite](https://github.com/Reverite)
|
||||
* [jpdevries](https://github.com/jpdevries)
|
||||
* [H-C-F](https://github.com/H-C-F)
|
||||
* [gdpelican](https://github.com/gdpelican)
|
||||
* [kmichl](https://github.com/kmichl)
|
||||
* [Kurtis Rainbolt-Greene](mailto:me@kurtisrainboltgreene.name)
|
||||
* [saper](https://github.com/saper)
|
||||
* [nevillepark](https://github.com/nevillepark)
|
||||
|
@ -157,6 +164,7 @@ and provided thanks to the work of the following contributors:
|
|||
* [Ram Lmn](mailto:ramlmn@users.noreply.github.com)
|
||||
* [harukasan](https://github.com/harukasan)
|
||||
* [stamak](https://github.com/stamak)
|
||||
* [noellabo](https://github.com/noellabo)
|
||||
* [Technowix](mailto:technowix@users.noreply.github.com)
|
||||
* [Eychics](https://github.com/Eychics)
|
||||
* [Thor Harald Johansen](mailto:thj@thj.no)
|
||||
|
@ -165,22 +173,27 @@ and provided thanks to the work of the following contributors:
|
|||
* [Valentin_NC](mailto:valentin.ouvrard@nautile.sarl)
|
||||
* [R0ckweb](https://github.com/R0ckweb)
|
||||
* [caasi](https://github.com/caasi)
|
||||
* [chr-1x](https://github.com/chr-1x)
|
||||
* [esetomo](https://github.com/esetomo)
|
||||
* [foxiehkins](https://github.com/foxiehkins)
|
||||
* [hoodie](mailto:hoodiekitten@outlook.com)
|
||||
* [luzi82](https://github.com/luzi82)
|
||||
* [duxovni](https://github.com/duxovni)
|
||||
* [trwnh](https://github.com/trwnh)
|
||||
* [unsmell](https://github.com/unsmell)
|
||||
* [valerauko](https://github.com/valerauko)
|
||||
* [chriswmartin](https://github.com/chriswmartin)
|
||||
* [vahnj](https://github.com/vahnj)
|
||||
* [ikuradon](https://github.com/ikuradon)
|
||||
* [AndreLewin](https://github.com/AndreLewin)
|
||||
* [rinsuki](https://github.com/rinsuki)
|
||||
* [0xflotus](https://github.com/0xflotus)
|
||||
* [redtachyons](https://github.com/redtachyons)
|
||||
* [thurloat](https://github.com/thurloat)
|
||||
* [aaribaud](https://github.com/aaribaud)
|
||||
* [Andrew](mailto:andrewlchronister@gmail.com)
|
||||
* [estuans](https://github.com/estuans)
|
||||
* [BenLubar](https://github.com/BenLubar)
|
||||
* [dissolve](https://github.com/dissolve)
|
||||
* [PurpleBooth](https://github.com/PurpleBooth)
|
||||
* [bradurani](https://github.com/bradurani)
|
||||
|
@ -192,7 +205,7 @@ and provided thanks to the work of the following contributors:
|
|||
* [cdutson](https://github.com/cdutson)
|
||||
* [farlistener](https://github.com/farlistener)
|
||||
* [DavidLibeau](https://github.com/DavidLibeau)
|
||||
* [SirCmpwn](https://github.com/SirCmpwn)
|
||||
* [ddevault](https://github.com/ddevault)
|
||||
* [Fjoerfoks](https://github.com/Fjoerfoks)
|
||||
* [fmauNeko](https://github.com/fmauNeko)
|
||||
* [gloaec](https://github.com/gloaec)
|
||||
|
@ -207,6 +220,7 @@ and provided thanks to the work of the following contributors:
|
|||
* [jasonrhodes](https://github.com/jasonrhodes)
|
||||
* [Jason Snell](mailto:jason@newrelic.com)
|
||||
* [jviide](https://github.com/jviide)
|
||||
* [YuleZ](https://github.com/YuleZ)
|
||||
* [crakaC](https://github.com/crakaC)
|
||||
* [tkbky](https://github.com/tkbky)
|
||||
* [Kaylee](mailto:kaylee@codethat.sucks)
|
||||
|
@ -223,10 +237,12 @@ and provided thanks to the work of the following contributors:
|
|||
* [petzah](https://github.com/petzah)
|
||||
* [ignisf](https://github.com/ignisf)
|
||||
* [raymestalez](https://github.com/raymestalez)
|
||||
* [remram44](https://github.com/remram44)
|
||||
* [sascha-sl](https://github.com/sascha-sl)
|
||||
* [u1-liquid](https://github.com/u1-liquid)
|
||||
* [sim6](https://github.com/sim6)
|
||||
* [stemid](https://github.com/stemid)
|
||||
* [sumdog](https://github.com/sumdog)
|
||||
* [ThomasLeister](https://github.com/ThomasLeister)
|
||||
* [mcat-ee](https://github.com/mcat-ee)
|
||||
* [tototoshi](https://github.com/tototoshi)
|
||||
|
@ -243,7 +259,6 @@ and provided thanks to the work of the following contributors:
|
|||
* [aus-social](https://github.com/aus-social)
|
||||
* [imbsky](https://github.com/imbsky)
|
||||
* [bsky](mailto:me@imbsky.net)
|
||||
* [chr-1x](https://github.com/chr-1x)
|
||||
* [codl](https://github.com/codl)
|
||||
* [cpsdqs](https://github.com/cpsdqs)
|
||||
* [barzamin](https://github.com/barzamin)
|
||||
|
@ -252,6 +267,7 @@ and provided thanks to the work of the following contributors:
|
|||
* [ik11235](https://github.com/ik11235)
|
||||
* [kawax](https://github.com/kawax)
|
||||
* [007lva](https://github.com/007lva)
|
||||
* [mbajur](https://github.com/mbajur)
|
||||
* [matsurai25](https://github.com/matsurai25)
|
||||
* [mecab](https://github.com/mecab)
|
||||
* [nicobz25](https://github.com/nicobz25)
|
||||
|
@ -259,7 +275,6 @@ and provided thanks to the work of the following contributors:
|
|||
* [pinfort](https://github.com/pinfort)
|
||||
* [rbaumert](https://github.com/rbaumert)
|
||||
* [rhoio](https://github.com/rhoio)
|
||||
* [trwnh](https://github.com/trwnh)
|
||||
* [usagi-f](https://github.com/usagi-f)
|
||||
* [vidarlee](https://github.com/vidarlee)
|
||||
* [vjackson725](https://github.com/vjackson725)
|
||||
|
@ -269,11 +284,11 @@ and provided thanks to the work of the following contributors:
|
|||
* [Awea](https://github.com/Awea)
|
||||
* [halcy](https://github.com/halcy)
|
||||
* [naaaaaaaaaaaf](https://github.com/naaaaaaaaaaaf)
|
||||
* [NecroTechno](https://github.com/NecroTechno)
|
||||
* [8398a7](https://github.com/8398a7)
|
||||
* [857b](https://github.com/857b)
|
||||
* [insom](https://github.com/insom)
|
||||
* [Aditoo17](https://github.com/Aditoo17)
|
||||
* [tachyons](https://github.com/tachyons)
|
||||
* [Esteth](https://github.com/Esteth)
|
||||
* [unascribed](https://github.com/unascribed)
|
||||
* [Aguay-val](https://github.com/Aguay-val)
|
||||
* [Akihiko Odaki](mailto:nekomanma@pixiv.co.jp)
|
||||
|
@ -283,6 +298,7 @@ and provided thanks to the work of the following contributors:
|
|||
* [alxrcs](https://github.com/alxrcs)
|
||||
* [console-cowboy](https://github.com/console-cowboy)
|
||||
* [pointlessone](https://github.com/pointlessone)
|
||||
* [Alkarex](https://github.com/Alkarex)
|
||||
* [a2](https://github.com/a2)
|
||||
* [0xa](https://github.com/0xa)
|
||||
* [palindromordnilap](https://github.com/palindromordnilap)
|
||||
|
@ -299,7 +315,6 @@ and provided thanks to the work of the following contributors:
|
|||
* [ayumin](https://github.com/ayumin)
|
||||
* [BaptisteGelez](https://github.com/BaptisteGelez)
|
||||
* [bzg](https://github.com/bzg)
|
||||
* [BenLubar](https://github.com/BenLubar)
|
||||
* [benediktg](https://github.com/benediktg)
|
||||
* [blakebarnett](https://github.com/blakebarnett)
|
||||
* [bradj](https://github.com/bradj)
|
||||
|
@ -341,6 +356,7 @@ and provided thanks to the work of the following contributors:
|
|||
* [espenronnevik](https://github.com/espenronnevik)
|
||||
* [Finariel](https://github.com/Finariel)
|
||||
* [siuying](https://github.com/siuying)
|
||||
* [fwenzel](https://github.com/fwenzel)
|
||||
* [GenbuHase](https://github.com/GenbuHase)
|
||||
* [hattori6789](https://github.com/hattori6789)
|
||||
* [algernon](https://github.com/algernon)
|
||||
|
@ -375,10 +391,9 @@ and provided thanks to the work of the following contributors:
|
|||
* [jguerder](https://github.com/jguerder)
|
||||
* [Jehops](https://github.com/Jehops)
|
||||
* [joshuap](https://github.com/joshuap)
|
||||
* [YuleZ](https://github.com/YuleZ)
|
||||
* [Tiwy57](https://github.com/Tiwy57)
|
||||
* [xuv](https://github.com/xuv)
|
||||
* [Jnsll](https://github.com/Jnsll)
|
||||
* [June Sallou](mailto:jnsll@users.noreply.github.com)
|
||||
* [j0k3r](https://github.com/j0k3r)
|
||||
* [KEINOS](https://github.com/KEINOS)
|
||||
* [futoase](https://github.com/futoase)
|
||||
|
@ -389,7 +404,6 @@ and provided thanks to the work of the following contributors:
|
|||
* [k0ta0uchi](https://github.com/k0ta0uchi)
|
||||
* [KrzysiekJ](https://github.com/KrzysiekJ)
|
||||
* [leowzukw](https://github.com/leowzukw)
|
||||
* [lmorchard](https://github.com/lmorchard)
|
||||
* [Tak](https://github.com/Tak)
|
||||
* [cacheflow](https://github.com/cacheflow)
|
||||
* [ldidry](https://github.com/ldidry)
|
||||
|
@ -426,6 +440,7 @@ and provided thanks to the work of the following contributors:
|
|||
* [lae](https://github.com/lae)
|
||||
* [Nanamachi](https://github.com/Nanamachi)
|
||||
* [orinthe](https://github.com/orinthe)
|
||||
* [NecroTechno](https://github.com/NecroTechno)
|
||||
* [Dar13](https://github.com/Dar13)
|
||||
* [ngerakines](https://github.com/ngerakines)
|
||||
* [vonneudeck](https://github.com/vonneudeck)
|
||||
|
@ -443,7 +458,6 @@ and provided thanks to the work of the following contributors:
|
|||
* [Pangoraw](https://github.com/Pangoraw)
|
||||
* [peterkeen](https://github.com/peterkeen)
|
||||
* [pgate](https://github.com/pgate)
|
||||
* [remram44](https://github.com/remram44)
|
||||
* [retokromer](https://github.com/retokromer)
|
||||
* [rfwatson](https://github.com/rfwatson)
|
||||
* [rfreebern](https://github.com/rfreebern)
|
||||
|
@ -455,19 +469,22 @@ and provided thanks to the work of the following contributors:
|
|||
* [sts10](https://github.com/sts10)
|
||||
* [skoji](https://github.com/skoji)
|
||||
* [ScienJus](https://github.com/ScienJus)
|
||||
* [larkinscott](https://github.com/larkinscott)
|
||||
* [imolein](https://github.com/imolein)
|
||||
* [blinry](https://github.com/blinry)
|
||||
* [Noiwex](https://github.com/Noiwex)
|
||||
* [yuki764](https://github.com/yuki764)
|
||||
* [shnjp](https://github.com/shnjp)
|
||||
* [ernix](https://github.com/ernix)
|
||||
* [rosylilly](https://github.com/rosylilly)
|
||||
* [shouko](https://github.com/shouko)
|
||||
* [Scott Larkin](mailto:scott@codeclimate.com)
|
||||
* [Sebastian Hübner](mailto:imolein@users.noreply.github.com)
|
||||
* [Sebastian Morr](mailto:sebastian@morr.cc)
|
||||
* [Sergei Č](mailto:noiwex1911@gmail.com)
|
||||
* [Setuu](mailto:yuki764setuu@gmail.com)
|
||||
* [Shaun Gillies](mailto:me@shaungillies.net)
|
||||
* [Shin Adachi](mailto:shn@glucose.jp)
|
||||
* [Shin Kojima](mailto:shin@kojima.org)
|
||||
* [Sho Kusano](mailto:rosylilly@aduca.org)
|
||||
* [Shouko Yu](mailto:imshouko@gmail.com)
|
||||
* [Sina Mashek](mailto:sina@mashek.xyz)
|
||||
* [sossii](https://github.com/sossii)
|
||||
* [Sir-Boops](mailto:admin@boops.me)
|
||||
* [Soshi Kato](mailto:mail@sossii.com)
|
||||
* [Spanky](mailto:2788886+spankyworks@users.noreply.github.com)
|
||||
* [StefOfficiel](mailto:pichard.stephane@free.fr)
|
||||
* [Steven Tappert](mailto:admin@dark-it.net)
|
||||
* [Svetlozar Todorov](mailto:svetlik@users.noreply.github.com)
|
||||
* [Sébastien Santoro](mailto:dereckson@espace-win.org)
|
||||
* [Tad Thorley](mailto:phaedryx@users.noreply.github.com)
|
||||
|
@ -521,11 +538,13 @@ and provided thanks to the work of the following contributors:
|
|||
* [jacob](mailto:jacobherringtondeveloper@gmail.com)
|
||||
* [jenn kaplan](mailto:me@jkap.io)
|
||||
* [jirayudech](mailto:jirayudech@gmail.com)
|
||||
* [jomo](mailto:github@jomo.tv)
|
||||
* [jooops](mailto:joops@autistici.org)
|
||||
* [jukper](mailto:jukkaperanto@gmail.com)
|
||||
* [jumoru](mailto:jumoru@mailbox.org)
|
||||
* [karlyeurl](mailto:karl.yeurl@gmail.com)
|
||||
* [kedama](mailto:32974885+kedamadq@users.noreply.github.com)
|
||||
* [kodai](mailto:shirafuta.kodai@gmail.com)
|
||||
* [kuro5hin](mailto:rusty@kuro5hin.org)
|
||||
* [luzpaz](mailto:luzpaz@users.noreply.github.com)
|
||||
* [maxypy](mailto:maxime@mpigou.fr)
|
||||
|
@ -533,6 +552,7 @@ and provided thanks to the work of the following contributors:
|
|||
* [mimikun](mailto:dzdzble_effort_311@outlook.jp)
|
||||
* [mshrtkch](mailto:mshrtkch@users.noreply.github.com)
|
||||
* [muan](mailto:muan@github.com)
|
||||
* [namelessGonbai](mailto:43787036+namelessgonbai@users.noreply.github.com)
|
||||
* [neetshin](mailto:neetshin@neetsh.in)
|
||||
* [nightpool](mailto:nightpool@users.noreply.github.com)
|
||||
* [rch850](mailto:rich850@gmail.com)
|
||||
|
@ -564,3 +584,248 @@ and provided thanks to the work of the following contributors:
|
|||
* [雨宮美羽](mailto:k737566@gmail.com)
|
||||
|
||||
This document is provided for informational purposes only. Since it is only updated once per release, the version you are looking at may be currently out of date. To see the full list of contributors, consider looking at the [git history](https://github.com/tootsuite/mastodon/graphs/contributors) instead.
|
||||
|
||||
## Translators
|
||||
|
||||
Following people have contributed to translation of Mastodon:
|
||||
|
||||
- **Arabic**
|
||||
- ButterflyOfFire
|
||||
- **Asturian**
|
||||
- ButterflyOfFire
|
||||
- Enol P.
|
||||
- **Basque**
|
||||
- Aitzol
|
||||
- ButterflyOfFire
|
||||
- Gorka Azkarate
|
||||
- Osoitz
|
||||
- Peru Iparragirre
|
||||
- **Bulgarian**
|
||||
- ButterflyOfFire
|
||||
- **Catalan**
|
||||
- ButterflyOfFire
|
||||
- Joan Montané
|
||||
- Jose Luis
|
||||
- spla
|
||||
- **Chinese (Hong Kong)**
|
||||
- ButterflyOfFire
|
||||
- Luzi Leung
|
||||
- **Chinese (Simplified)**
|
||||
- Allen Zhong
|
||||
- ButterflyOfFire
|
||||
- SerCom_KC
|
||||
- **Chinese (Traditional)**
|
||||
- ButterflyOfFire
|
||||
- James58899
|
||||
- Jeff Huang
|
||||
- S1ttidoe477
|
||||
- SHA265
|
||||
- **Corsican**
|
||||
- Alix D. R.
|
||||
- ButterflyOfFire
|
||||
- **Croatian**
|
||||
- ButterflyOfFire
|
||||
- **Czech**
|
||||
- ButterflyOfFire
|
||||
- Lorem Ipsum
|
||||
- Marek Ľach
|
||||
- **Danish**
|
||||
- ButterflyOfFire
|
||||
- Rasmus Sæderup
|
||||
- **Dutch**
|
||||
- ButterflyOfFire
|
||||
- Jelv
|
||||
- jeroenpraat
|
||||
- rscmbbng
|
||||
- **English**
|
||||
- ButterflyOfFire
|
||||
- Renato "Lond" Cerqueira
|
||||
- **Esperanto**
|
||||
- ButterflyOfFire
|
||||
- Jeong Arm
|
||||
- Martin Bodin
|
||||
- Mélanie Chauvel
|
||||
- Vanege
|
||||
- tuxayo/Victor Grousset
|
||||
- **Finnish**
|
||||
- ButterflyOfFire
|
||||
- Jonne Arjoranta
|
||||
- S Heija
|
||||
- Taru Luojola
|
||||
- **French**
|
||||
- Alda Marteau-Hardi
|
||||
- Alix D. R.
|
||||
- Baptiste Jonglez
|
||||
- ButterflyOfFire
|
||||
- Franck Paul
|
||||
- Jean-Baptiste Holcroft
|
||||
- Jonathan Chan
|
||||
- Letiteuf55
|
||||
- Martin Bodin
|
||||
- Mélanie Chauvel
|
||||
- Olivier Humbert
|
||||
- Paul Marques Mota
|
||||
- Sylvhem
|
||||
- Technowix
|
||||
- Thibaut Girka
|
||||
- Théodore
|
||||
- azenet
|
||||
- codl
|
||||
- **Galician**
|
||||
- ButterflyOfFire
|
||||
- Xose M.
|
||||
- manequim
|
||||
- **Georgian**
|
||||
- ButterflyOfFire
|
||||
- **German**
|
||||
- Benedikt Geißler
|
||||
- ButterflyOfFire
|
||||
- Daniel
|
||||
- Eugen Rochko
|
||||
- Koyu Berteon
|
||||
- Patrick Figel
|
||||
- Weblate Admin
|
||||
- averageunicorn
|
||||
- ePirat
|
||||
- koyu
|
||||
- larsreineke
|
||||
- lilo
|
||||
- **Greek**
|
||||
- Antonis
|
||||
- ButterflyOfFire
|
||||
- Dimitris Maroulidis
|
||||
- Konstantinos Grevenitis
|
||||
- **Hebrew**
|
||||
- ButterflyOfFire
|
||||
- Ira
|
||||
- Yaron Shahrabani
|
||||
- **Hungarian**
|
||||
- Adam Paszternak
|
||||
- ButterflyOfFire
|
||||
- Tibike Miklós
|
||||
- **Ido**
|
||||
- ButterflyOfFire
|
||||
- **Indonesian**
|
||||
- Alfiana Sibuea
|
||||
- ButterflyOfFire
|
||||
- Dito Kurnia Pratama
|
||||
- Eirworks
|
||||
- afachri
|
||||
- se7entime
|
||||
- **Italian**
|
||||
- Alessandro Levati
|
||||
- ButterflyOfFire
|
||||
- Giuseppe Pignataro
|
||||
- Stefano
|
||||
- **Japanese**
|
||||
- ButterflyOfFire
|
||||
- Kumasun Morino
|
||||
- Yamagishi Kazutoshi
|
||||
- mayaeh
|
||||
- osapon
|
||||
- unarist
|
||||
- 小鳥遊まりあ
|
||||
- 森の子リスのミーコの大冒険
|
||||
- **Korean**
|
||||
- ButterflyOfFire
|
||||
- Jeong Arm
|
||||
- Minori Hiraoka
|
||||
- Yamagishi Kazutoshi
|
||||
- **Malay**
|
||||
- ButterflyOfFire
|
||||
- Muhammad Nur Hidayat (MNH48)
|
||||
- **Norwegian (old code)**
|
||||
- ButterflyOfFire
|
||||
- Espen Rønnevik
|
||||
- Tale
|
||||
- **Occitan**
|
||||
- ButterflyOfFire
|
||||
- Maxenç
|
||||
- Quenti2
|
||||
- Quentí
|
||||
- **Persian**
|
||||
- ButterflyOfFire
|
||||
- Masoud Abkenar
|
||||
- **Polish**
|
||||
- ButterflyOfFire
|
||||
- Jakub Mendyk
|
||||
- Marcin Mikołajczak
|
||||
- Marek Ľach
|
||||
- Stasiek Michalski
|
||||
- krkk
|
||||
- **Portuguese**
|
||||
- ButterflyOfFire
|
||||
- Hugo Gameiro
|
||||
- manequim
|
||||
- **Portuguese (Brazil)**
|
||||
- André Andrade
|
||||
- Anna e só
|
||||
- ButterflyOfFire
|
||||
- Renato "Lond" Cerqueira
|
||||
- **Romanian**
|
||||
- ButterflyOfFire
|
||||
- adrianbblk
|
||||
- **Russian**
|
||||
- Andrew Zyabin
|
||||
- ButterflyOfFire
|
||||
- Evgeny Petrov
|
||||
- Yaron Shahrabani
|
||||
- **Serbian**
|
||||
- Branko Kokanovic
|
||||
- Burekz Finezt
|
||||
- ButterflyOfFire
|
||||
- **Serbian (latin)**
|
||||
- ButterflyOfFire
|
||||
- **Slovak**
|
||||
- ButterflyOfFire
|
||||
- Ivan Pleva
|
||||
- Lorem Ipsum
|
||||
- Marek Ľach
|
||||
- Peter
|
||||
- **Slovenian**
|
||||
- ButterflyOfFire
|
||||
- Kristijan Tkalec
|
||||
- **Spanish**
|
||||
- Angeles Broullón
|
||||
- Antón López
|
||||
- ButterflyOfFire
|
||||
- Carlos Mondragon
|
||||
- David Charte
|
||||
- Emmanuel
|
||||
- Lothar Wolf
|
||||
- Pablo de la Concepción Sanz
|
||||
- **Swedish**
|
||||
- ButterflyOfFire
|
||||
- Elias Mårtenson
|
||||
- Isak Holmström
|
||||
- Shellkr
|
||||
- Stefan Midjich
|
||||
- Tim Stahel
|
||||
- **Telugu**
|
||||
- ButterflyOfFire
|
||||
- Joseph Nuthalapati
|
||||
- Ranjith Tellakula
|
||||
- avndp
|
||||
- **Thai**
|
||||
- ButterflyOfFire
|
||||
- **Turkish**
|
||||
- ButterflyOfFire
|
||||
- **Ukrainian**
|
||||
- ButterflyOfFire
|
||||
- Ivan Verchenko
|
||||
- alexcleac
|
||||
- **Welsh**
|
||||
- ButterflyOfFire
|
||||
- Jaz-Michael King
|
||||
- Kevin Beynon
|
||||
- Owain Rhys Lewis
|
||||
- Renato "Lond" Cerqueira
|
||||
- Rhoslyn Prys
|
||||
- carl morris
|
||||
- **Armenian**
|
||||
- ButterflyOfFire
|
||||
- **Latvian**
|
||||
- ButterflyOfFire
|
||||
- **Tamil**
|
||||
- ButterflyOfFire
|
||||
- Prasanna Venkadesh
|
||||
|
|
389
CHANGELOG.md
389
CHANGELOG.md
|
@ -3,199 +3,328 @@ Changelog
|
|||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [2.6.5] - 2018-12-01
|
||||
## [2.7.0] - 2019-01-20
|
||||
### Added
|
||||
|
||||
- Add link for adding a user to a list from their profile ([namelessGonbai](https://github.com/tootsuite/mastodon/pull/9062))
|
||||
- Add joining several hashtags in a single column ([gdpelican](https://github.com/tootsuite/mastodon/pull/8904))
|
||||
- Add volume sliders for videos ([sumdog](https://github.com/tootsuite/mastodon/pull/9366))
|
||||
- Add a tooltip explaining what a locked account is ([pawelngei](https://github.com/tootsuite/mastodon/pull/9403))
|
||||
- Add preloaded cache for common JSON-LD contexts ([ThibG](https://github.com/tootsuite/mastodon/pull/9412))
|
||||
- Add profile directory ([Gargron](https://github.com/tootsuite/mastodon/pull/9427))
|
||||
- Add setting to not group reblogs in home feed ([ThibG](https://github.com/tootsuite/mastodon/pull/9248))
|
||||
- Add admin ability to remove a user's header image ([ThibG](https://github.com/tootsuite/mastodon/pull/9495))
|
||||
- Add account hashtags to ActivityPub actor JSON ([Gargron](https://github.com/tootsuite/mastodon/pull/9450))
|
||||
- Add error message for avatar image that's too large ([sumdog](https://github.com/tootsuite/mastodon/pull/9518))
|
||||
- Add notification quick-filter bar ([pawelngei](https://github.com/tootsuite/mastodon/pull/9399))
|
||||
- Add new first-time tutorial ([Gargron](https://github.com/tootsuite/mastodon/pull/9531))
|
||||
- Add moderation warnings ([Gargron](https://github.com/tootsuite/mastodon/pull/9519))
|
||||
- Add emoji codepoint mappings for v11.0 ([Gargron](https://github.com/tootsuite/mastodon/pull/9618))
|
||||
- Add REST API for creating an account ([Gargron](https://github.com/tootsuite/mastodon/pull/9572))
|
||||
- Add support for Malayalam in language filter ([tachyons](https://github.com/tootsuite/mastodon/pull/9624))
|
||||
- Add exclude_reblogs option to account statuses API ([Gargron](https://github.com/tootsuite/mastodon/pull/9640))
|
||||
- Add local followers page to admin account UI ([chr-1x](https://github.com/tootsuite/mastodon/pull/9610))
|
||||
- Add healthcheck commands to docker-compose.yml ([BenLubar](https://github.com/tootsuite/mastodon/pull/9143))
|
||||
- Add handler for Move activity to migrate followers ([Gargron](https://github.com/tootsuite/mastodon/pull/9629))
|
||||
- Add CSV export for lists and domain blocks ([Gargron](https://github.com/tootsuite/mastodon/pull/9677))
|
||||
- Add `tootctl accounts follow ACCT` ([Gargron](https://github.com/tootsuite/mastodon/pull/9414))
|
||||
- Add scheduled statuses ([Gargron](https://github.com/tootsuite/mastodon/pull/9706))
|
||||
- Add immutable caching for S3 objects ([nolanlawson](https://github.com/tootsuite/mastodon/pull/9722))
|
||||
- Add cache to custom emojis API ([Gargron](https://github.com/tootsuite/mastodon/pull/9732))
|
||||
- Add preview cards to non-detailed statuses on public pages ([Gargron](https://github.com/tootsuite/mastodon/pull/9714))
|
||||
- Add `mod` and `moderator` to list of default reserved usernames ([Gargron](https://github.com/tootsuite/mastodon/pull/9713))
|
||||
- Add quick links to the admin interface in the web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/8545))
|
||||
- Add `tootctl domains crawl` ([Gargron](https://github.com/tootsuite/mastodon/pull/9809))
|
||||
- Add attachment list fallback to public pages ([ThibG](https://github.com/tootsuite/mastodon/pull/9780))
|
||||
- Add `tootctl --version` ([Gargron](https://github.com/tootsuite/mastodon/pull/9835))
|
||||
- Add information about how to opt-in to the directory on the directory ([Gargron](https://github.com/tootsuite/mastodon/pull/9834))
|
||||
- Add timeouts for S3 ([Gargron](https://github.com/tootsuite/mastodon/pull/9842))
|
||||
- Add support for non-public reblogs from ActivityPub ([Gargron](https://github.com/tootsuite/mastodon/pull/9841))
|
||||
- Add sending of `Reject` activity when sending a `Block` activity ([ThibG](https://github.com/tootsuite/mastodon/pull/9811))
|
||||
|
||||
### Changed
|
||||
|
||||
- Change lists to display replies to others on the list and list owner (#9324)
|
||||
- Temporarily pause timeline if mouse moved recently ([lmorchard](https://github.com/tootsuite/mastodon/pull/9200))
|
||||
- Change the password form order ([mayaeh](https://github.com/tootsuite/mastodon/pull/9267))
|
||||
- Redesign admin UI for accounts ([Gargron](https://github.com/tootsuite/mastodon/pull/9340), [Gargron](https://github.com/tootsuite/mastodon/pull/9643))
|
||||
- Redesign admin UI for instances/domain blocks ([Gargron](https://github.com/tootsuite/mastodon/pull/9645))
|
||||
- Swap avatar and header input fields in profile page ([ThibG](https://github.com/tootsuite/mastodon/pull/9271))
|
||||
- When posting in mobile mode, go back to previous history location ([ThibG](https://github.com/tootsuite/mastodon/pull/9502))
|
||||
- Split out is_changing_upload from is_submitting ([ThibG](https://github.com/tootsuite/mastodon/pull/9536))
|
||||
- Back to the getting-started when pins the timeline. ([kedamaDQ](https://github.com/tootsuite/mastodon/pull/9561))
|
||||
- Allow unauthenticated REST API access to GET /api/v1/accounts/:id/statuses ([Gargron](https://github.com/tootsuite/mastodon/pull/9573))
|
||||
- Limit maximum visibility of local silenced users to unlisted ([ThibG](https://github.com/tootsuite/mastodon/pull/9583))
|
||||
- Change API error message for unconfirmed accounts ([noellabo](https://github.com/tootsuite/mastodon/pull/9625))
|
||||
- Change the icon to "reply-all" when it's a reply to other accounts ([mayaeh](https://github.com/tootsuite/mastodon/pull/9378))
|
||||
- Do not ignore federated reports targetting already-reported accounts ([ThibG](https://github.com/tootsuite/mastodon/pull/9534))
|
||||
- Upgrade default Ruby version to 2.6.0 ([Gargron](https://github.com/tootsuite/mastodon/pull/9688))
|
||||
- Change e-mail digest frequency ([Gargron](https://github.com/tootsuite/mastodon/pull/9689))
|
||||
- Change Docker images for Tor support in docker-compose.yml ([Sir-Boops](https://github.com/tootsuite/mastodon/pull/9438))
|
||||
- Display fallback link card thumbnail when none is given ([Gargron](https://github.com/tootsuite/mastodon/pull/9715))
|
||||
- Change account bio length validation to ignore mention domains and URLs ([Gargron](https://github.com/tootsuite/mastodon/pull/9717))
|
||||
- Use configured contact user for "anonymous" federation activities ([yukimochi](https://github.com/tootsuite/mastodon/pull/9661))
|
||||
- Change remote interaction dialog to use specific actions instead of generic "interact" ([Gargron](https://github.com/tootsuite/mastodon/pull/9743))
|
||||
- Always re-fetch public key when signature verification fails to support blind key rotation ([ThibG](https://github.com/tootsuite/mastodon/pull/9667))
|
||||
- Make replies to boosts impossible, connect reply to original status instead ([valerauko](https://github.com/tootsuite/mastodon/pull/9129))
|
||||
- Change e-mail MX validation to check both A and MX records against blacklist ([Gargron](https://github.com/tootsuite/mastodon/pull/9489))
|
||||
- Hide floating action button on search and getting started pages ([tmm576](https://github.com/tootsuite/mastodon/pull/9826))
|
||||
- Redesign public hashtag page to use a masonry layout ([Gargron](https://github.com/tootsuite/mastodon/pull/9822))
|
||||
- Use `summary` as summary instead of content warning for converted ActivityPub objects ([Gargron](https://github.com/tootsuite/mastodon/pull/9823))
|
||||
- Display a double reply arrow on public pages for toots that are replies ([ThibG](https://github.com/tootsuite/mastodon/pull/9808))
|
||||
- Change admin UI right panel size to be wider ([Kjwon15](https://github.com/tootsuite/mastodon/pull/9768))
|
||||
|
||||
### Removed
|
||||
|
||||
- Remove links to bridge.joinmastodon.org (non-functional) ([Gargron](https://github.com/tootsuite/mastodon/pull/9608))
|
||||
- Remove LD-Signatures from activities that do not need them ([ThibG](https://github.com/tootsuite/mastodon/pull/9659))
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix failures caused by commonly-used JSON-LD contexts being unavailable (#9412)
|
||||
- Remove unused computation of reblog references from updateTimeline ([ThibG](https://github.com/tootsuite/mastodon/pull/9244))
|
||||
- Fix loaded embeds resetting if a status arrives from API again ([ThibG](https://github.com/tootsuite/mastodon/pull/9270))
|
||||
- Fix race condition causing shallow status with only a "favourited" attribute ([ThibG](https://github.com/tootsuite/mastodon/pull/9272))
|
||||
- Remove intermediary arrays when creating hash maps from results ([Gargron](https://github.com/tootsuite/mastodon/pull/9291))
|
||||
- Extract counters from accounts table to account_stats table to improve performance ([Gargron](https://github.com/tootsuite/mastodon/pull/9295))
|
||||
- Change identities id column to a bigint ([Gargron](https://github.com/tootsuite/mastodon/pull/9371))
|
||||
- Fix conversations API pagination ([ThibG](https://github.com/tootsuite/mastodon/pull/9407))
|
||||
- Improve account suspension speed and completeness ([Gargron](https://github.com/tootsuite/mastodon/pull/9290))
|
||||
- Fix thread depth computation in statuses_controller ([ThibG](https://github.com/tootsuite/mastodon/pull/9426))
|
||||
- Fix database deadlocks by moving account stats update outside transaction ([ThibG](https://github.com/tootsuite/mastodon/pull/9437))
|
||||
- Escape HTML in profile name preview in profile settings ([pawelngei](https://github.com/tootsuite/mastodon/pull/9446))
|
||||
- Use same CORS policy for /@:username and /users/:username ([ThibG](https://github.com/tootsuite/mastodon/pull/9485))
|
||||
- Make custom emoji domains case insensitive ([Esteth](https://github.com/tootsuite/mastodon/pull/9474))
|
||||
- Various fixes to scrollable lists and media gallery ([ThibG](https://github.com/tootsuite/mastodon/pull/9501))
|
||||
- Fix bootsnap cache directory being declared relatively ([Gargron](https://github.com/tootsuite/mastodon/pull/9511))
|
||||
- Fix timeline pagination in the web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/9516))
|
||||
- Fix padding on dropdown elements in preferences ([ThibG](https://github.com/tootsuite/mastodon/pull/9517))
|
||||
- Make avatar and headers respect GIF autoplay settings ([ThibG](https://github.com/tootsuite/mastodon/pull/9515))
|
||||
- Do no retry Web Push workers if the server returns a 4xx response ([Gargron](https://github.com/tootsuite/mastodon/pull/9434))
|
||||
- Minor scrollable list fixes ([ThibG](https://github.com/tootsuite/mastodon/pull/9551))
|
||||
- Ignore low-confidence CharlockHolmes guesses when parsing link cards ([ThibG](https://github.com/tootsuite/mastodon/pull/9510))
|
||||
- Fix `tootctl accounts rotate` not updating public keys ([Gargron](https://github.com/tootsuite/mastodon/pull/9556))
|
||||
- Fix CSP / X-Frame-Options for media players ([jomo](https://github.com/tootsuite/mastodon/pull/9558))
|
||||
- Fix unnecessary loadMore calls when the end of a timeline has been reached ([ThibG](https://github.com/tootsuite/mastodon/pull/9581))
|
||||
- Skip mailer job retries when a record no longer exists ([Gargron](https://github.com/tootsuite/mastodon/pull/9590))
|
||||
- Fix composer not getting focus after reply confirmation dialog ([ThibG](https://github.com/tootsuite/mastodon/pull/9602))
|
||||
- Fix signature verification stoplight triggering on non-timeout errors ([Gargron](https://github.com/tootsuite/mastodon/pull/9617))
|
||||
- Fix ThreadResolveWorker getting queued with invalid URLs ([Gargron](https://github.com/tootsuite/mastodon/pull/9628))
|
||||
- Fix crash when clearing uninitialized timeline ([ThibG](https://github.com/tootsuite/mastodon/pull/9662))
|
||||
- Avoid duplicate work by merging ReplyDistributionWorker into DistributionWorker ([ThibG](https://github.com/tootsuite/mastodon/pull/9660))
|
||||
- Skip full text search if it fails, instead of erroring out completely ([Kjwon15](https://github.com/tootsuite/mastodon/pull/9654))
|
||||
- Fix profile metadata links not verifying correctly sometimes ([shrft](https://github.com/tootsuite/mastodon/pull/9673))
|
||||
- Ensure blocked user unfollows blocker if Block/Undo-Block activities are processed out of order ([ThibG](https://github.com/tootsuite/mastodon/pull/9687))
|
||||
- Fix unreadable text color in report modal for some statuses ([Gargron](https://github.com/tootsuite/mastodon/pull/9716))
|
||||
- Stop GIFV timeline preview explicitly when it's opened in modal ([kedamaDQ](https://github.com/tootsuite/mastodon/pull/9749))
|
||||
- Fix scrollbar width compensation ([ThibG](https://github.com/tootsuite/mastodon/pull/9824))
|
||||
- Fix race conditions when processing deleted toots ([ThibG](https://github.com/tootsuite/mastodon/pull/9815))
|
||||
- Fix SSO issues on WebKit browsers by disabling Same-Site cookie again ([moritzheiber](https://github.com/tootsuite/mastodon/pull/9819))
|
||||
- Fix empty OEmbed error ([renatolond](https://github.com/tootsuite/mastodon/pull/9807))
|
||||
- Fix drag & drop modal not disappearing sometimes ([hinaloe](https://github.com/tootsuite/mastodon/pull/9797))
|
||||
- Fix statuses with content warnings being displayed in web push notifications sometimes ([ThibG](https://github.com/tootsuite/mastodon/pull/9778))
|
||||
- Fix scroll-to-detailed status not working on public pages ([ThibG](https://github.com/tootsuite/mastodon/pull/9773))
|
||||
- Fix media modal loading indicator ([ThibG](https://github.com/tootsuite/mastodon/pull/9771))
|
||||
- Fix hashtag search results not having a permalink fallback in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/9810))
|
||||
- Fix slightly cropped font on settings page dropdowns when using system font ([ariasuni](https://github.com/tootsuite/mastodon/pull/9839))
|
||||
- Fix not being able to drag & drop text into forms ([tmm576](https://github.com/tootsuite/mastodon/pull/9840))
|
||||
|
||||
### Security
|
||||
|
||||
- Sanitize and sandbox toot embeds in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/9552))
|
||||
- Add tombstones for remote statuses to prevent replay attacks ([ThibG](https://github.com/tootsuite/mastodon/pull/9830))
|
||||
|
||||
## [2.6.5] - 2018-12-01
|
||||
### Changed
|
||||
|
||||
- Change lists to display replies to others on the list and list owner ([ThibG](https://github.com/tootsuite/mastodon/pull/9324))
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix failures caused by commonly-used JSON-LD contexts being unavailable ([ThibG](https://github.com/tootsuite/mastodon/pull/9412))
|
||||
|
||||
## [2.6.4] - 2018-11-30
|
||||
### Fixed
|
||||
|
||||
- Fix yarn dependencies not installing due to yanked event-stream package (#9401)
|
||||
- Fix yarn dependencies not installing due to yanked event-stream package ([Gargron](https://github.com/tootsuite/mastodon/pull/9401))
|
||||
|
||||
## [2.6.3] - 2018-11-30
|
||||
### Added
|
||||
|
||||
- Add hyphen to characters allowed in remote usernames (#9345)
|
||||
- Add hyphen to characters allowed in remote usernames ([ThibG](https://github.com/tootsuite/mastodon/pull/9345))
|
||||
|
||||
### Changed
|
||||
|
||||
- Change server user count to exclude suspended accounts (#9380)
|
||||
- Change server user count to exclude suspended accounts ([Gargron](https://github.com/tootsuite/mastodon/pull/9380))
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix ffmpeg processing sometimes stalling due to overfilled stdout buffer (#9368)
|
||||
- Fix missing DNS records raising the wrong kind of exception (#9379)
|
||||
- Fix already queued deliveries still trying to reach inboxes marked as unavailable (#9358)
|
||||
- Fix ffmpeg processing sometimes stalling due to overfilled stdout buffer ([hugogameiro](https://github.com/tootsuite/mastodon/pull/9368))
|
||||
- Fix missing DNS records raising the wrong kind of exception ([Gargron](https://github.com/tootsuite/mastodon/pull/9379))
|
||||
- Fix already queued deliveries still trying to reach inboxes marked as unavailable ([Gargron](https://github.com/tootsuite/mastodon/pull/9358))
|
||||
|
||||
### Security
|
||||
|
||||
- Fix TLS handshake timeout not being enforced (#9381)
|
||||
- Fix TLS handshake timeout not being enforced ([Gargron](https://github.com/tootsuite/mastodon/pull/9381))
|
||||
|
||||
## [2.6.2] - 2018-11-23
|
||||
### Added
|
||||
|
||||
- Add Page to whitelisted ActivityPub types (#9188)
|
||||
- Add 20px to column width in web UI (#9227)
|
||||
- Add amount of freed disk space in `tootctl media remove` (#9229, #9239, #9288)
|
||||
- Add "Show thread" link to self-replies (#9228)
|
||||
- Add Page to whitelisted ActivityPub types ([mbajur](https://github.com/tootsuite/mastodon/pull/9188))
|
||||
- Add 20px to column width in web UI ([Gargron](https://github.com/tootsuite/mastodon/pull/9227))
|
||||
- Add amount of freed disk space in `tootctl media remove` ([Gargron](https://github.com/tootsuite/mastodon/pull/9229), [Gargron](https://github.com/tootsuite/mastodon/pull/9239), [mayaeh](https://github.com/tootsuite/mastodon/pull/9288))
|
||||
- Add "Show thread" link to self-replies ([Gargron](https://github.com/tootsuite/mastodon/pull/9228))
|
||||
|
||||
### Changed
|
||||
|
||||
- Change order of Atom and RSS links so Atom is first (#9302)
|
||||
- Change Nginx configuration for Nanobox apps (#9310)
|
||||
- Change the follow action to appear instant in web UI (#9220)
|
||||
- Change how the ActiveRecord connection is instantiated in on_worker_boot (#9238)
|
||||
- Change `tootctl accounts cull` to always touch accounts so they can be skipped (#9293)
|
||||
- Change mime type comparison to ignore JSON-LD profile (#9179)
|
||||
- Change order of Atom and RSS links so Atom is first ([Alkarex](https://github.com/tootsuite/mastodon/pull/9302))
|
||||
- Change Nginx configuration for Nanobox apps ([danhunsaker](https://github.com/tootsuite/mastodon/pull/9310))
|
||||
- Change the follow action to appear instant in web UI ([Gargron](https://github.com/tootsuite/mastodon/pull/9220))
|
||||
- Change how the ActiveRecord connection is instantiated in on_worker_boot ([Gargron](https://github.com/tootsuite/mastodon/pull/9238))
|
||||
- Change `tootctl accounts cull` to always touch accounts so they can be skipped ([renatolond](https://github.com/tootsuite/mastodon/pull/9293))
|
||||
- Change mime type comparison to ignore JSON-LD profile ([valerauko](https://github.com/tootsuite/mastodon/pull/9179))
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix web UI crash when conversation has no last status (#9207)
|
||||
- Fix follow limit validator reporting lower number past threshold (#9230)
|
||||
- Fix form validation flash message color and input borders (#9235)
|
||||
- Fix invalid twitter:player cards being displayed (#9254)
|
||||
- Fix emoji update date being processed incorrectly (#9255)
|
||||
- Fix playing embed resetting if status is reloaded in web UI (#9270, #9275)
|
||||
- Fix web UI crash when favouriting a deleted status (#9272)
|
||||
- Fix intermediary arrays being created for hash maps (#9291)
|
||||
- Fix filter ID not being a string in REST API (#9303)
|
||||
- Fix web UI crash when conversation has no last status ([sammy8806](https://github.com/tootsuite/mastodon/pull/9207))
|
||||
- Fix follow limit validator reporting lower number past threshold ([Gargron](https://github.com/tootsuite/mastodon/pull/9230))
|
||||
- Fix form validation flash message color and input borders ([Gargron](https://github.com/tootsuite/mastodon/pull/9235))
|
||||
- Fix invalid twitter:player cards being displayed ([ThibG](https://github.com/tootsuite/mastodon/pull/9254))
|
||||
- Fix emoji update date being processed incorrectly ([ThibG](https://github.com/tootsuite/mastodon/pull/9255))
|
||||
- Fix playing embed resetting if status is reloaded in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/9270), [Gargron](https://github.com/tootsuite/mastodon/pull/9275))
|
||||
- Fix web UI crash when favouriting a deleted status ([ThibG](https://github.com/tootsuite/mastodon/pull/9272))
|
||||
- Fix intermediary arrays being created for hash maps ([Gargron](https://github.com/tootsuite/mastodon/pull/9291))
|
||||
- Fix filter ID not being a string in REST API ([Gargron](https://github.com/tootsuite/mastodon/pull/9303))
|
||||
|
||||
### Security
|
||||
|
||||
- Fix multiple remote account deletions being able to deadlock the database (#9292)
|
||||
- Fix HTTP connection timeout of 10s not being enforced (#9329)
|
||||
- Fix multiple remote account deletions being able to deadlock the database ([Gargron](https://github.com/tootsuite/mastodon/pull/9292))
|
||||
- Fix HTTP connection timeout of 10s not being enforced ([Gargron](https://github.com/tootsuite/mastodon/pull/9329))
|
||||
|
||||
## [2.6.1] - 2018-10-30
|
||||
### Fixed
|
||||
|
||||
- Fix resolving resources by URL not working due to a regression in #9132 (#9171)
|
||||
- Fix reducer error in web UI when a conversation has no last status (#9173)
|
||||
- Fix resolving resources by URL not working due to a regression in [valerauko](https://github.com/tootsuite/mastodon/pull/9132) ([Gargron](https://github.com/tootsuite/mastodon/pull/9171))
|
||||
- Fix reducer error in web UI when a conversation has no last status ([Gargron](https://github.com/tootsuite/mastodon/pull/9173))
|
||||
|
||||
## [2.6.0] - 2018-10-30
|
||||
### Added
|
||||
|
||||
- Add link ownership verification (#8703)
|
||||
- Add conversations API (#8832)
|
||||
- Add limit for the number of people that can be followed from one account (#8807)
|
||||
- Add admin setting to customize mascot (#8766)
|
||||
- Add support for more granular ActivityPub audiences from other software, i.e. circles (#8950, #9093, #9150)
|
||||
- Add option to block all reports from a domain (#8830)
|
||||
- Add user preference to always expand toots marked with content warnings (#8762)
|
||||
- Add user preference to always hide all media (#8569)
|
||||
- Add `force_login` param to OAuth authorize page (#8655)
|
||||
- Add `tootctl accounts backup` (#8642, #8811)
|
||||
- Add `tootctl accounts create` (#8642, #8811)
|
||||
- Add `tootctl accounts cull` (#8642, #8811)
|
||||
- Add `tootctl accounts delete` (#8642, #8811)
|
||||
- Add `tootctl accounts modify` (#8642, #8811)
|
||||
- Add `tootctl accounts refresh` (#8642, #8811)
|
||||
- Add `tootctl feeds build` (#8642, #8811)
|
||||
- Add `tootctl feeds clear` (#8642, #8811)
|
||||
- Add `tootctl settings registrations open` (#8642, #8811)
|
||||
- Add `tootctl settings registrations close` (#8642, #8811)
|
||||
- Add `min_id` param to REST API to support backwards pagination (#8736)
|
||||
- Add a confirmation dialog when hitting reply and the compose box isn't empty (#8893)
|
||||
- Add PostgreSQL disk space growth tracking in PGHero (#8906)
|
||||
- Add button for disabling local account to report quick actions bar (#9024)
|
||||
- Add Czech language (#8594)
|
||||
- Add `same-site` (`lax`) attribute to cookies (#8626)
|
||||
- Add support for styled scrollbars in Firefox Nightly (#8653)
|
||||
- Add highlight to the active tab in web UI profiles (#8673)
|
||||
- Add auto-focus for comment textarea in report modal (#8689)
|
||||
- Add auto-focus for emoji picker's search field (#8688)
|
||||
- Add nginx and systemd templates to `dist/` directory (#8770)
|
||||
- Add support for `/.well-known/change-password` (#8828)
|
||||
- Add option to override FFMPEG binary path (#8855)
|
||||
- Add `dns-prefetch` tag when using different host for assets or uploads (#8942)
|
||||
- Add `description` meta tag (#8941)
|
||||
- Add `Content-Security-Policy` header (#8957)
|
||||
- Add cache for the instance info API (#8765)
|
||||
- Add suggested follows to search screen in mobile layout (#9010)
|
||||
- Add CORS header to `/.well-known/*` routes (#9083)
|
||||
- Add `card` attribute to statuses returned from REST API (#9120)
|
||||
- Add in-stream link preview (#9120)
|
||||
- Add support for ActivityPub `Page` objects (#9121)
|
||||
- Add link ownership verification ([Gargron](https://github.com/tootsuite/mastodon/pull/8703))
|
||||
- Add conversations API ([Gargron](https://github.com/tootsuite/mastodon/pull/8832))
|
||||
- Add limit for the number of people that can be followed from one account ([Gargron](https://github.com/tootsuite/mastodon/pull/8807))
|
||||
- Add admin setting to customize mascot ([ashleyhull-versent](https://github.com/tootsuite/mastodon/pull/8766))
|
||||
- Add support for more granular ActivityPub audiences from other software, i.e. circles ([Gargron](https://github.com/tootsuite/mastodon/pull/8950), [Gargron](https://github.com/tootsuite/mastodon/pull/9093), [Gargron](https://github.com/tootsuite/mastodon/pull/9150))
|
||||
- Add option to block all reports from a domain ([Gargron](https://github.com/tootsuite/mastodon/pull/8830))
|
||||
- Add user preference to always expand toots marked with content warnings ([webroo](https://github.com/tootsuite/mastodon/pull/8762))
|
||||
- Add user preference to always hide all media ([fvh-P](https://github.com/tootsuite/mastodon/pull/8569))
|
||||
- Add `force_login` param to OAuth authorize page ([Gargron](https://github.com/tootsuite/mastodon/pull/8655))
|
||||
- Add `tootctl accounts backup` ([Gargron](https://github.com/tootsuite/mastodon/pull/8642), [Gargron](https://github.com/tootsuite/mastodon/pull/8811))
|
||||
- Add `tootctl accounts create` ([Gargron](https://github.com/tootsuite/mastodon/pull/8642), [Gargron](https://github.com/tootsuite/mastodon/pull/8811))
|
||||
- Add `tootctl accounts cull` ([Gargron](https://github.com/tootsuite/mastodon/pull/8642), [Gargron](https://github.com/tootsuite/mastodon/pull/8811))
|
||||
- Add `tootctl accounts delete` ([Gargron](https://github.com/tootsuite/mastodon/pull/8642), [Gargron](https://github.com/tootsuite/mastodon/pull/8811))
|
||||
- Add `tootctl accounts modify` ([Gargron](https://github.com/tootsuite/mastodon/pull/8642), [Gargron](https://github.com/tootsuite/mastodon/pull/8811))
|
||||
- Add `tootctl accounts refresh` ([Gargron](https://github.com/tootsuite/mastodon/pull/8642), [Gargron](https://github.com/tootsuite/mastodon/pull/8811))
|
||||
- Add `tootctl feeds build` ([Gargron](https://github.com/tootsuite/mastodon/pull/8642), [Gargron](https://github.com/tootsuite/mastodon/pull/8811))
|
||||
- Add `tootctl feeds clear` ([Gargron](https://github.com/tootsuite/mastodon/pull/8642), [Gargron](https://github.com/tootsuite/mastodon/pull/8811))
|
||||
- Add `tootctl settings registrations open` ([Gargron](https://github.com/tootsuite/mastodon/pull/8642), [Gargron](https://github.com/tootsuite/mastodon/pull/8811))
|
||||
- Add `tootctl settings registrations close` ([Gargron](https://github.com/tootsuite/mastodon/pull/8642), [Gargron](https://github.com/tootsuite/mastodon/pull/8811))
|
||||
- Add `min_id` param to REST API to support backwards pagination ([Gargron](https://github.com/tootsuite/mastodon/pull/8736))
|
||||
- Add a confirmation dialog when hitting reply and the compose box isn't empty ([ThibG](https://github.com/tootsuite/mastodon/pull/8893))
|
||||
- Add PostgreSQL disk space growth tracking in PGHero ([Gargron](https://github.com/tootsuite/mastodon/pull/8906))
|
||||
- Add button for disabling local account to report quick actions bar ([Gargron](https://github.com/tootsuite/mastodon/pull/9024))
|
||||
- Add Czech language ([Aditoo17](https://github.com/tootsuite/mastodon/pull/8594))
|
||||
- Add `same-site` (`lax`) attribute to cookies ([sorin-davidoi](https://github.com/tootsuite/mastodon/pull/8626))
|
||||
- Add support for styled scrollbars in Firefox Nightly ([sorin-davidoi](https://github.com/tootsuite/mastodon/pull/8653))
|
||||
- Add highlight to the active tab in web UI profiles ([rhoio](https://github.com/tootsuite/mastodon/pull/8673))
|
||||
- Add auto-focus for comment textarea in report modal ([ThibG](https://github.com/tootsuite/mastodon/pull/8689))
|
||||
- Add auto-focus for emoji picker's search field ([ThibG](https://github.com/tootsuite/mastodon/pull/8688))
|
||||
- Add nginx and systemd templates to `dist/` directory ([Gargron](https://github.com/tootsuite/mastodon/pull/8770))
|
||||
- Add support for `/.well-known/change-password` ([Gargron](https://github.com/tootsuite/mastodon/pull/8828))
|
||||
- Add option to override FFMPEG binary path ([sascha-sl](https://github.com/tootsuite/mastodon/pull/8855))
|
||||
- Add `dns-prefetch` tag when using different host for assets or uploads ([Gargron](https://github.com/tootsuite/mastodon/pull/8942))
|
||||
- Add `description` meta tag ([Gargron](https://github.com/tootsuite/mastodon/pull/8941))
|
||||
- Add `Content-Security-Policy` header ([ThibG](https://github.com/tootsuite/mastodon/pull/8957))
|
||||
- Add cache for the instance info API ([ykzts](https://github.com/tootsuite/mastodon/pull/8765))
|
||||
- Add suggested follows to search screen in mobile layout ([Gargron](https://github.com/tootsuite/mastodon/pull/9010))
|
||||
- Add CORS header to `/.well-known/*` routes ([BenLubar](https://github.com/tootsuite/mastodon/pull/9083))
|
||||
- Add `card` attribute to statuses returned from REST API ([Gargron](https://github.com/tootsuite/mastodon/pull/9120))
|
||||
- Add in-stream link preview ([Gargron](https://github.com/tootsuite/mastodon/pull/9120))
|
||||
- Add support for ActivityPub `Page` objects ([mbajur](https://github.com/tootsuite/mastodon/pull/9121))
|
||||
|
||||
### Changed
|
||||
|
||||
- Change forms design (#8703)
|
||||
- Change reports overview to group by target account (#8674)
|
||||
- Change web UI to show "read more" link on overly long in-stream statuses (#8205)
|
||||
- Change design of direct messages column (#8832, #9022)
|
||||
- Change home timelines to exclude DMs (#8940)
|
||||
- Change list timelines to exclude all replies (#8683)
|
||||
- Change admin accounts UI default sort to most recent (#8813)
|
||||
- Change documentation URL in the UI (#8898)
|
||||
- Change style of success and failure messages (#8973)
|
||||
- Change DM filtering to always allow DMs from staff (#8993)
|
||||
- Change recommended Ruby version to 2.5.3 (#9003)
|
||||
- Change docker-compose default to persist volumes in current directory (#9055)
|
||||
- Change character counters on edit profile page to input length limit (#9100)
|
||||
- Change notification filtering to always let through messages from staff (#9152)
|
||||
- Change "hide boosts from user" function also hiding notifications about boosts (#9147)
|
||||
- Change CSS `detailed-status__wrapper` class actually wrap the detailed status (#8547)
|
||||
- Change forms design ([Gargron](https://github.com/tootsuite/mastodon/pull/8703))
|
||||
- Change reports overview to group by target account ([Gargron](https://github.com/tootsuite/mastodon/pull/8674))
|
||||
- Change web UI to show "read more" link on overly long in-stream statuses ([lanodan](https://github.com/tootsuite/mastodon/pull/8205))
|
||||
- Change design of direct messages column ([Gargron](https://github.com/tootsuite/mastodon/pull/8832), [Gargron](https://github.com/tootsuite/mastodon/pull/9022))
|
||||
- Change home timelines to exclude DMs ([Gargron](https://github.com/tootsuite/mastodon/pull/8940))
|
||||
- Change list timelines to exclude all replies ([cbayerlein](https://github.com/tootsuite/mastodon/pull/8683))
|
||||
- Change admin accounts UI default sort to most recent ([Gargron](https://github.com/tootsuite/mastodon/pull/8813))
|
||||
- Change documentation URL in the UI ([Gargron](https://github.com/tootsuite/mastodon/pull/8898))
|
||||
- Change style of success and failure messages ([Gargron](https://github.com/tootsuite/mastodon/pull/8973))
|
||||
- Change DM filtering to always allow DMs from staff ([qguv](https://github.com/tootsuite/mastodon/pull/8993))
|
||||
- Change recommended Ruby version to 2.5.3 ([zunda](https://github.com/tootsuite/mastodon/pull/9003))
|
||||
- Change docker-compose default to persist volumes in current directory ([Gargron](https://github.com/tootsuite/mastodon/pull/9055))
|
||||
- Change character counters on edit profile page to input length limit ([Gargron](https://github.com/tootsuite/mastodon/pull/9100))
|
||||
- Change notification filtering to always let through messages from staff ([Gargron](https://github.com/tootsuite/mastodon/pull/9152))
|
||||
- Change "hide boosts from user" function also hiding notifications about boosts ([ThibG](https://github.com/tootsuite/mastodon/pull/9147))
|
||||
- Change CSS `detailed-status__wrapper` class actually wrap the detailed status ([trwnh](https://github.com/tootsuite/mastodon/pull/8547))
|
||||
|
||||
### Deprecated
|
||||
|
||||
- `GET /api/v1/timelines/direct` → `GET /api/v1/conversations` (#8832)
|
||||
- `POST /api/v1/notifications/dismiss` → `POST /api/v1/notifications/:id/dismiss` (#8905)
|
||||
- `GET /api/v1/statuses/:id/card` → `card` attributed included in status (#9120)
|
||||
- `GET /api/v1/timelines/direct` → `GET /api/v1/conversations` ([Gargron](https://github.com/tootsuite/mastodon/pull/8832))
|
||||
- `POST /api/v1/notifications/dismiss` → `POST /api/v1/notifications/:id/dismiss` ([Gargron](https://github.com/tootsuite/mastodon/pull/8905))
|
||||
- `GET /api/v1/statuses/:id/card` → `card` attributed included in status ([Gargron](https://github.com/tootsuite/mastodon/pull/9120))
|
||||
|
||||
### Removed
|
||||
|
||||
- Remove "on this device" label in column push settings (#8704)
|
||||
- Remove rake tasks in favour of tootctl commands (#8675)
|
||||
- Remove "on this device" label in column push settings ([rhoio](https://github.com/tootsuite/mastodon/pull/8704))
|
||||
- Remove rake tasks in favour of tootctl commands ([Gargron](https://github.com/tootsuite/mastodon/pull/8675))
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix remote statuses using instance's default locale if no language given (#8861)
|
||||
- Fix streaming API not exiting when port or socket is unavailable (#9023)
|
||||
- Fix network calls being performed in database transaction in ActivityPub handler (#8951)
|
||||
- Fix dropdown arrow position (#8637)
|
||||
- Fix first element of dropdowns being focused even if not using keyboard (#8679)
|
||||
- Fix tootctl requiring `bundle exec` invocation (#8619)
|
||||
- Fix public pages not using animation preference for avatars (#8614)
|
||||
- Fix OEmbed/OpenGraph cards not understanding relative URLs (#8669)
|
||||
- Fix some dark emojis not having a white outline (#8597)
|
||||
- Fix media description not being displayed in various media modals (#8678)
|
||||
- Fix generated URLs of desktop notifications missing base URL (#8758)
|
||||
- Fix RTL styles (#8764, #8767, #8823, #8897, #9005, #9007, #9018, #9021, #9145, #9146)
|
||||
- Fix crash in streaming API when tag param missing (#8955)
|
||||
- Fix hotkeys not working when no element is focused (#8998)
|
||||
- Fix some hotkeys not working on detailed status view (#9006)
|
||||
- Fix og:url on status pages (#9047)
|
||||
- Fix upload option buttons only being visible on hover (#9074)
|
||||
- Fix tootctl not returning exit code 1 on wrong arguments (#9094)
|
||||
- Fix preview cards for appearing for profiles mentioned in toot (#6934, #9158)
|
||||
- Fix local accounts sometimes being duplicated as faux-remote (#9109)
|
||||
- Fix emoji search when the shortcode has multiple separators (#9124)
|
||||
- Fix dropdowns sometimes being partially obscured by other elements (#9126)
|
||||
- Fix cache not updating when reply/boost/favourite counters or media sensitivity update (#9119)
|
||||
- Fix empty display name precedence over username in web UI (#9163)
|
||||
- Fix td instead of th in sessions table header (#9162)
|
||||
- Fix handling of content types with profile (#9132)
|
||||
- Fix remote statuses using instance's default locale if no language given ([Kjwon15](https://github.com/tootsuite/mastodon/pull/8861))
|
||||
- Fix streaming API not exiting when port or socket is unavailable ([Gargron](https://github.com/tootsuite/mastodon/pull/9023))
|
||||
- Fix network calls being performed in database transaction in ActivityPub handler ([Gargron](https://github.com/tootsuite/mastodon/pull/8951))
|
||||
- Fix dropdown arrow position ([ThibG](https://github.com/tootsuite/mastodon/pull/8637))
|
||||
- Fix first element of dropdowns being focused even if not using keyboard ([ThibG](https://github.com/tootsuite/mastodon/pull/8679))
|
||||
- Fix tootctl requiring `bundle exec` invocation ([abcang](https://github.com/tootsuite/mastodon/pull/8619))
|
||||
- Fix public pages not using animation preference for avatars ([renatolond](https://github.com/tootsuite/mastodon/pull/8614))
|
||||
- Fix OEmbed/OpenGraph cards not understanding relative URLs ([ThibG](https://github.com/tootsuite/mastodon/pull/8669))
|
||||
- Fix some dark emojis not having a white outline ([ThibG](https://github.com/tootsuite/mastodon/pull/8597))
|
||||
- Fix media description not being displayed in various media modals ([ThibG](https://github.com/tootsuite/mastodon/pull/8678))
|
||||
- Fix generated URLs of desktop notifications missing base URL ([GenbuHase](https://github.com/tootsuite/mastodon/pull/8758))
|
||||
- Fix RTL styles ([mabkenar](https://github.com/tootsuite/mastodon/pull/8764), [mabkenar](https://github.com/tootsuite/mastodon/pull/8767), [mabkenar](https://github.com/tootsuite/mastodon/pull/8823), [mabkenar](https://github.com/tootsuite/mastodon/pull/8897), [mabkenar](https://github.com/tootsuite/mastodon/pull/9005), [mabkenar](https://github.com/tootsuite/mastodon/pull/9007), [mabkenar](https://github.com/tootsuite/mastodon/pull/9018), [mabkenar](https://github.com/tootsuite/mastodon/pull/9021), [mabkenar](https://github.com/tootsuite/mastodon/pull/9145), [mabkenar](https://github.com/tootsuite/mastodon/pull/9146))
|
||||
- Fix crash in streaming API when tag param missing ([Gargron](https://github.com/tootsuite/mastodon/pull/8955))
|
||||
- Fix hotkeys not working when no element is focused ([ThibG](https://github.com/tootsuite/mastodon/pull/8998))
|
||||
- Fix some hotkeys not working on detailed status view ([ThibG](https://github.com/tootsuite/mastodon/pull/9006))
|
||||
- Fix og:url on status pages ([ThibG](https://github.com/tootsuite/mastodon/pull/9047))
|
||||
- Fix upload option buttons only being visible on hover ([Gargron](https://github.com/tootsuite/mastodon/pull/9074))
|
||||
- Fix tootctl not returning exit code 1 on wrong arguments ([sascha-sl](https://github.com/tootsuite/mastodon/pull/9094))
|
||||
- Fix preview cards for appearing for profiles mentioned in toot ([ThibG](https://github.com/tootsuite/mastodon/pull/6934), [ThibG](https://github.com/tootsuite/mastodon/pull/9158))
|
||||
- Fix local accounts sometimes being duplicated as faux-remote ([Gargron](https://github.com/tootsuite/mastodon/pull/9109))
|
||||
- Fix emoji search when the shortcode has multiple separators ([ThibG](https://github.com/tootsuite/mastodon/pull/9124))
|
||||
- Fix dropdowns sometimes being partially obscured by other elements ([kedamaDQ](https://github.com/tootsuite/mastodon/pull/9126))
|
||||
- Fix cache not updating when reply/boost/favourite counters or media sensitivity update ([Gargron](https://github.com/tootsuite/mastodon/pull/9119))
|
||||
- Fix empty display name precedence over username in web UI ([Gargron](https://github.com/tootsuite/mastodon/pull/9163))
|
||||
- Fix td instead of th in sessions table header ([Gargron](https://github.com/tootsuite/mastodon/pull/9162))
|
||||
- Fix handling of content types with profile ([valerauko](https://github.com/tootsuite/mastodon/pull/9132))
|
||||
|
||||
## [2.5.2] - 2018-10-12
|
||||
### Security
|
||||
|
||||
- Fix XSS vulnerability (#8959)
|
||||
- Fix XSS vulnerability ([Gargron](https://github.com/tootsuite/mastodon/pull/8959))
|
||||
|
||||
## [2.5.1] - 2018-10-07
|
||||
### Fixed
|
||||
|
||||
- Fix database migrations for PostgreSQL below 9.5 (#8903)
|
||||
- Fix class autoloading issue in ActivityPub Create handler (#8820)
|
||||
- Fix cache statistics not being sent via statsd when statsd enabled (#8831)
|
||||
- Bump puma from 3.11.4 to 3.12.0 (#8883)
|
||||
- Fix database migrations for PostgreSQL below 9.5 ([Gargron](https://github.com/tootsuite/mastodon/pull/8903))
|
||||
- Fix class autoloading issue in ActivityPub Create handler ([Gargron](https://github.com/tootsuite/mastodon/pull/8820))
|
||||
- Fix cache statistics not being sent via statsd when statsd enabled ([ykzts](https://github.com/tootsuite/mastodon/pull/8831))
|
||||
- Bump puma from 3.11.4 to 3.12.0 ([dependabot[bot]](https://github.com/tootsuite/mastodon/pull/8883))
|
||||
|
||||
### Security
|
||||
|
||||
- Fix some local images not having their EXIF metadata stripped on upload (#8714)
|
||||
- Fix being able to enable a disabled relay via ActivityPub Accept handler (#8864)
|
||||
- Bump nokogiri from 1.8.4 to 1.8.5 (#8881)
|
||||
- Fix being able to report statuses not belonging to the reported account (#8916)
|
||||
- Fix some local images not having their EXIF metadata stripped on upload ([ThibG](https://github.com/tootsuite/mastodon/pull/8714))
|
||||
- Fix being able to enable a disabled relay via ActivityPub Accept handler ([ThibG](https://github.com/tootsuite/mastodon/pull/8864))
|
||||
- Bump nokogiri from 1.8.4 to 1.8.5 ([dependabot[bot]](https://github.com/tootsuite/mastodon/pull/8881))
|
||||
- Fix being able to report statuses not belonging to the reported account ([ThibG](https://github.com/tootsuite/mastodon/pull/8916))
|
||||
|
|
10
Dockerfile
10
Dockerfile
|
@ -1,5 +1,5 @@
|
|||
FROM node:8.12.0-alpine as node
|
||||
FROM ruby:2.4.5-alpine3.8
|
||||
FROM node:8.15-alpine as node
|
||||
FROM ruby:2.6-alpine3.8
|
||||
|
||||
LABEL maintainer="https://github.com/tootsuite/mastodon" \
|
||||
description="Your self-hosted, globally interconnected microblogging community"
|
||||
|
@ -31,6 +31,8 @@ RUN apk -U upgrade \
|
|||
libidn-dev \
|
||||
libressl \
|
||||
libtool \
|
||||
libxml2-dev \
|
||||
libxslt-dev \
|
||||
postgresql-dev \
|
||||
protobuf-dev \
|
||||
python \
|
||||
|
@ -43,6 +45,8 @@ RUN apk -U upgrade \
|
|||
imagemagick \
|
||||
libidn \
|
||||
libpq \
|
||||
libxml2 \
|
||||
libxslt \
|
||||
protobuf \
|
||||
tini \
|
||||
tzdata \
|
||||
|
@ -64,7 +68,7 @@ RUN apk -U upgrade \
|
|||
|
||||
COPY Gemfile Gemfile.lock package.json yarn.lock .yarnclean /mastodon/
|
||||
|
||||
RUN bundle config build.nokogiri --with-iconv-lib=/usr/local/lib --with-iconv-include=/usr/local/include \
|
||||
RUN bundle config build.nokogiri --use-system-libraries --with-iconv-lib=/usr/local/lib --with-iconv-include=/usr/local/include \
|
||||
&& bundle install -j$(getconf _NPROCESSORS_ONLN) --deployment --without test development \
|
||||
&& yarn install --pure-lockfile --ignore-engines \
|
||||
&& yarn cache clean
|
||||
|
|
46
Gemfile
46
Gemfile
|
@ -1,21 +1,21 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
source 'https://rubygems.org'
|
||||
ruby '>= 2.3.0', '< 2.6.0'
|
||||
ruby '>= 2.4.0', '< 2.7.0'
|
||||
|
||||
gem 'pkg-config', '~> 1.3'
|
||||
|
||||
gem 'puma', '~> 3.12'
|
||||
gem 'rails', '~> 5.2.1'
|
||||
gem 'rails', '~> 5.2.2'
|
||||
gem 'thor', '~> 0.20'
|
||||
|
||||
gem 'hamlit-rails', '~> 0.2'
|
||||
gem 'pg', '~> 1.1'
|
||||
gem 'makara', '~> 0.4'
|
||||
gem 'pghero', '~> 2.2'
|
||||
gem 'dotenv-rails', '~> 2.5'
|
||||
gem 'dotenv-rails', '~> 2.6'
|
||||
|
||||
gem 'aws-sdk-s3', '~> 1.23', require: false
|
||||
gem 'aws-sdk-s3', '~> 1.30', require: false
|
||||
gem 'fog-core', '<= 2.1.0'
|
||||
gem 'fog-openstack', '~> 0.3', require: false
|
||||
gem 'paperclip', '~> 6.0'
|
||||
|
@ -29,7 +29,7 @@ gem 'browser'
|
|||
gem 'charlock_holmes', '~> 0.7.6'
|
||||
gem 'iso-639'
|
||||
gem 'chewy', '~> 5.0'
|
||||
gem 'cld3', '~> 3.2.0'
|
||||
gem 'cld3', '~> 3.2.3'
|
||||
gem 'devise', '~> 4.5'
|
||||
gem 'devise-two-factor', '~> 3.0'
|
||||
|
||||
|
@ -40,7 +40,7 @@ end
|
|||
gem 'net-ldap', '~> 0.10'
|
||||
gem 'omniauth-cas', '~> 1.1'
|
||||
gem 'omniauth-saml', '~> 1.10'
|
||||
gem 'omniauth', '~> 1.2'
|
||||
gem 'omniauth', '~> 1.9'
|
||||
|
||||
gem 'doorkeeper', '~> 5.0'
|
||||
gem 'fast_blank', '~> 1.0'
|
||||
|
@ -52,12 +52,12 @@ gem 'htmlentities', '~> 4.3'
|
|||
gem 'http', '~> 3.3'
|
||||
gem 'http_accept_language', '~> 2.1'
|
||||
gem 'http_parser.rb', '~> 0.6', git: 'https://github.com/tmm1/http_parser.rb', ref: '54b17ba8c7d8d20a16dfc65d1775241833219cf2'
|
||||
gem 'httplog', '~> 1.1'
|
||||
gem 'httplog', '~> 1.2'
|
||||
gem 'idn-ruby', require: 'idn'
|
||||
gem 'kaminari', '~> 1.1'
|
||||
gem 'link_header', '~> 0.0'
|
||||
gem 'mime-types', '~> 3.2', require: 'mime/types/columnar'
|
||||
gem 'nokogiri', '~> 1.8'
|
||||
gem 'nokogiri', '~> 1.10'
|
||||
gem 'nsa', '~> 0.2'
|
||||
gem 'oj', '~> 3.7'
|
||||
gem 'ostatus2', '~> 2.0'
|
||||
|
@ -69,28 +69,28 @@ gem 'rack-attack', '~> 5.4'
|
|||
gem 'rack-cors', '~> 1.0', require: 'rack/cors'
|
||||
gem 'rails-i18n', '~> 5.1'
|
||||
gem 'rails-settings-cached', '~> 0.6'
|
||||
gem 'redis', '~> 4.0', require: ['redis', 'redis/connection/hiredis']
|
||||
gem 'redis', '~> 4.1', require: ['redis', 'redis/connection/hiredis']
|
||||
gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
|
||||
gem 'rqrcode', '~> 0.10'
|
||||
gem 'sanitize', '~> 5.0'
|
||||
gem 'sidekiq', '~> 5.2'
|
||||
gem 'sidekiq-scheduler', '~> 3.0'
|
||||
gem 'sidekiq-unique-jobs', '~> 5.0'
|
||||
gem 'sidekiq-bulk', '~>0.1.1'
|
||||
gem 'sidekiq-unique-jobs', '~> 6.0'
|
||||
gem 'sidekiq-bulk', '~>0.2.0'
|
||||
gem 'simple-navigation', '~> 4.0'
|
||||
gem 'simple_form', '~> 4.0'
|
||||
gem 'simple_form', '~> 4.1'
|
||||
gem 'sprockets-rails', '~> 3.2', require: 'sprockets/railtie'
|
||||
gem 'stoplight', '~> 2.1.3'
|
||||
gem 'strong_migrations', '~> 0.3'
|
||||
gem 'tty-command', '~> 0.8', require: false
|
||||
gem 'tty-prompt', '~> 0.17', require: false
|
||||
gem 'tty-prompt', '~> 0.18', require: false
|
||||
gem 'twitter-text', '~> 1.14'
|
||||
gem 'tzinfo-data', '~> 1.2018'
|
||||
gem 'webpacker', '~> 3.5'
|
||||
gem 'webpush'
|
||||
|
||||
gem 'json-ld', '~> 2.2'
|
||||
gem 'json-ld-preloaded', '~> 2.2'
|
||||
gem 'json-ld', '~> 3.0'
|
||||
gem 'json-ld-preloaded', '~> 3.0'
|
||||
gem 'rdf-normalize', '~> 0.3'
|
||||
|
||||
group :development, :test do
|
||||
|
@ -107,15 +107,15 @@ group :production, :test do
|
|||
end
|
||||
|
||||
group :test do
|
||||
gem 'capybara', '~> 3.10'
|
||||
gem 'capybara', '~> 3.12'
|
||||
gem 'climate_control', '~> 0.2'
|
||||
gem 'faker', '~> 1.9'
|
||||
gem 'microformats', '~> 4.0'
|
||||
gem 'rails-controller-testing', '~> 1.0'
|
||||
gem 'rspec-sidekiq', '~> 3.0'
|
||||
gem 'simplecov', '~> 0.16', require: false
|
||||
gem 'webmock', '~> 3.4'
|
||||
gem 'parallel_tests', '~> 2.26'
|
||||
gem 'webmock', '~> 3.5'
|
||||
gem 'parallel_tests', '~> 2.27'
|
||||
end
|
||||
|
||||
group :development do
|
||||
|
@ -123,12 +123,12 @@ group :development do
|
|||
gem 'annotate', '~> 2.7'
|
||||
gem 'better_errors', '~> 2.5'
|
||||
gem 'binding_of_caller', '~> 0.7'
|
||||
gem 'bullet', '~> 5.7'
|
||||
gem 'letter_opener', '~> 1.4'
|
||||
gem 'bullet', '~> 5.9'
|
||||
gem 'letter_opener', '~> 1.7'
|
||||
gem 'letter_opener_web', '~> 1.3'
|
||||
gem 'memory_profiler'
|
||||
gem 'rubocop', '~> 0.60', require: false
|
||||
gem 'brakeman', '~> 4.3', require: false
|
||||
gem 'rubocop', '~> 0.63', require: false
|
||||
gem 'brakeman', '~> 4.4', require: false
|
||||
gem 'bundler-audit', '~> 0.6', require: false
|
||||
gem 'scss_lint', '~> 0.57', require: false
|
||||
|
||||
|
@ -145,3 +145,5 @@ group :production do
|
|||
gem 'lograge', '~> 0.10'
|
||||
gem 'redis-rails', '~> 5.0'
|
||||
end
|
||||
|
||||
gem 'concurrent-ruby', require: false
|
||||
|
|
278
Gemfile.lock
278
Gemfile.lock
|
@ -15,49 +15,49 @@ GIT
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actioncable (5.2.1)
|
||||
actionpack (= 5.2.1)
|
||||
actioncable (5.2.2)
|
||||
actionpack (= 5.2.2)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (>= 0.6.1)
|
||||
actionmailer (5.2.1)
|
||||
actionpack (= 5.2.1)
|
||||
actionview (= 5.2.1)
|
||||
activejob (= 5.2.1)
|
||||
actionmailer (5.2.2)
|
||||
actionpack (= 5.2.2)
|
||||
actionview (= 5.2.2)
|
||||
activejob (= 5.2.2)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
actionpack (5.2.1)
|
||||
actionview (= 5.2.1)
|
||||
activesupport (= 5.2.1)
|
||||
actionpack (5.2.2)
|
||||
actionview (= 5.2.2)
|
||||
activesupport (= 5.2.2)
|
||||
rack (~> 2.0)
|
||||
rack-test (>= 0.6.3)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
actionview (5.2.1)
|
||||
activesupport (= 5.2.1)
|
||||
actionview (5.2.2)
|
||||
activesupport (= 5.2.2)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
||||
active_model_serializers (0.10.7)
|
||||
active_model_serializers (0.10.8)
|
||||
actionpack (>= 4.1, < 6)
|
||||
activemodel (>= 4.1, < 6)
|
||||
case_transform (>= 0.2)
|
||||
jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
|
||||
active_record_query_trace (1.5.4)
|
||||
activejob (5.2.1)
|
||||
activesupport (= 5.2.1)
|
||||
activejob (5.2.2)
|
||||
activesupport (= 5.2.2)
|
||||
globalid (>= 0.3.6)
|
||||
activemodel (5.2.1)
|
||||
activesupport (= 5.2.1)
|
||||
activerecord (5.2.1)
|
||||
activemodel (= 5.2.1)
|
||||
activesupport (= 5.2.1)
|
||||
activemodel (5.2.2)
|
||||
activesupport (= 5.2.2)
|
||||
activerecord (5.2.2)
|
||||
activemodel (= 5.2.2)
|
||||
activesupport (= 5.2.2)
|
||||
arel (>= 9.0)
|
||||
activestorage (5.2.1)
|
||||
actionpack (= 5.2.1)
|
||||
activerecord (= 5.2.1)
|
||||
activestorage (5.2.2)
|
||||
actionpack (= 5.2.2)
|
||||
activerecord (= 5.2.2)
|
||||
marcel (~> 0.3.1)
|
||||
activesupport (5.2.1)
|
||||
activesupport (5.2.2)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 0.7, < 2)
|
||||
minitest (~> 5.1)
|
||||
|
@ -76,17 +76,17 @@ GEM
|
|||
av (0.9.0)
|
||||
cocaine (~> 0.5.3)
|
||||
aws-eventstream (1.0.1)
|
||||
aws-partitions (1.106.0)
|
||||
aws-sdk-core (3.35.0)
|
||||
aws-partitions (1.131.0)
|
||||
aws-sdk-core (3.45.0)
|
||||
aws-eventstream (~> 1.0)
|
||||
aws-partitions (~> 1.0)
|
||||
aws-sigv4 (~> 1.0)
|
||||
jmespath (~> 1.0)
|
||||
aws-sdk-kms (1.11.0)
|
||||
aws-sdk-core (~> 3, >= 3.26.0)
|
||||
aws-sdk-kms (1.13.0)
|
||||
aws-sdk-core (~> 3, >= 3.39.0)
|
||||
aws-sigv4 (~> 1.0)
|
||||
aws-sdk-s3 (1.23.0)
|
||||
aws-sdk-core (~> 3, >= 3.26.0)
|
||||
aws-sdk-s3 (1.30.1)
|
||||
aws-sdk-core (~> 3, >= 3.39.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.0)
|
||||
aws-sigv4 (1.0.3)
|
||||
|
@ -100,14 +100,14 @@ GEM
|
|||
debug_inspector (>= 0.0.1)
|
||||
bootsnap (1.3.2)
|
||||
msgpack (~> 1.0)
|
||||
brakeman (4.3.1)
|
||||
brakeman (4.4.0)
|
||||
browser (2.5.3)
|
||||
builder (3.2.3)
|
||||
bullet (5.7.6)
|
||||
bullet (5.9.0)
|
||||
activesupport (>= 3.0.0)
|
||||
uniform_notifier (~> 1.11.0)
|
||||
bundler-audit (0.6.0)
|
||||
bundler (~> 1.2)
|
||||
uniform_notifier (~> 1.11)
|
||||
bundler-audit (0.6.1)
|
||||
bundler (>= 1.2.0, < 3)
|
||||
thor (~> 0.18)
|
||||
byebug (10.0.2)
|
||||
capistrano (3.11.0)
|
||||
|
@ -126,7 +126,7 @@ GEM
|
|||
sshkit (~> 1.3)
|
||||
capistrano-yarn (2.0.2)
|
||||
capistrano (~> 3.0)
|
||||
capybara (3.10.0)
|
||||
capybara (3.12.0)
|
||||
addressable
|
||||
mini_mime (>= 0.1.3)
|
||||
nokogiri (~> 1.8)
|
||||
|
@ -142,13 +142,13 @@ GEM
|
|||
elasticsearch (>= 2.0.0)
|
||||
elasticsearch-dsl
|
||||
chunky_png (1.3.10)
|
||||
cld3 (3.2.2)
|
||||
cld3 (3.2.3)
|
||||
ffi (>= 1.1.0, < 1.10.0)
|
||||
climate_control (0.2.0)
|
||||
cocaine (0.5.8)
|
||||
climate_control (>= 0.0.3, < 1.0)
|
||||
coderay (1.1.2)
|
||||
concurrent-ruby (1.0.5)
|
||||
concurrent-ruby (1.1.4)
|
||||
connection_pool (2.2.2)
|
||||
crack (0.4.3)
|
||||
safe_yaml (~> 1.0.0)
|
||||
|
@ -185,9 +185,9 @@ GEM
|
|||
unf (>= 0.0.5, < 1.0.0)
|
||||
doorkeeper (5.0.2)
|
||||
railties (>= 4.2)
|
||||
dotenv (2.5.0)
|
||||
dotenv-rails (2.5.0)
|
||||
dotenv (= 2.5.0)
|
||||
dotenv (2.6.0)
|
||||
dotenv-rails (2.6.0)
|
||||
dotenv (= 2.6.0)
|
||||
railties (>= 3.2, < 6.0)
|
||||
elasticsearch (6.0.2)
|
||||
elasticsearch-api (= 6.0.2)
|
||||
|
@ -200,7 +200,7 @@ GEM
|
|||
multi_json
|
||||
encryptor (3.0.0)
|
||||
equatable (0.5.0)
|
||||
erubi (1.7.1)
|
||||
erubi (1.8.0)
|
||||
et-orbi (1.1.6)
|
||||
tzinfo
|
||||
excon (0.62.0)
|
||||
|
@ -210,7 +210,7 @@ GEM
|
|||
faraday (0.15.0)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
fast_blank (1.0.0)
|
||||
fastimage (2.1.4)
|
||||
fastimage (2.1.5)
|
||||
ffi (1.9.25)
|
||||
fog-core (2.1.0)
|
||||
builder
|
||||
|
@ -231,7 +231,7 @@ GEM
|
|||
fuubar (2.3.2)
|
||||
rspec-core (~> 3.0)
|
||||
ruby-progressbar (~> 1.4)
|
||||
get_process_mem (0.2.2)
|
||||
get_process_mem (0.2.3)
|
||||
globalid (0.4.1)
|
||||
activesupport (>= 4.2.0)
|
||||
goldfinger (2.1.0)
|
||||
|
@ -251,11 +251,10 @@ GEM
|
|||
hamster (3.0.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
hashdiff (0.3.7)
|
||||
hashie (3.5.7)
|
||||
hashie (3.6.0)
|
||||
heapy (0.1.4)
|
||||
highline (2.0.0)
|
||||
hiredis (0.6.1)
|
||||
hitimes (1.3.0)
|
||||
hiredis (0.6.3)
|
||||
hkdf (0.3.0)
|
||||
htmlentities (4.3.4)
|
||||
http (3.3.0)
|
||||
|
@ -267,10 +266,10 @@ GEM
|
|||
domain_name (~> 0.5)
|
||||
http-form_data (2.1.1)
|
||||
http_accept_language (2.1.1)
|
||||
httplog (1.1.1)
|
||||
httplog (1.2.0)
|
||||
rack (>= 1.0)
|
||||
rainbow (>= 2.0.0)
|
||||
i18n (1.1.1)
|
||||
i18n (1.5.2)
|
||||
concurrent-ruby (~> 1.0)
|
||||
i18n-tasks (0.9.28)
|
||||
activesupport (>= 4.0.2)
|
||||
|
@ -285,16 +284,16 @@ GEM
|
|||
idn-ruby (0.1.0)
|
||||
ipaddress (0.8.3)
|
||||
iso-639 (0.2.8)
|
||||
jaro_winkler (1.5.1)
|
||||
jaro_winkler (1.5.2)
|
||||
jmespath (1.4.0)
|
||||
json (2.1.0)
|
||||
json-ld (2.2.1)
|
||||
json-ld (3.0.2)
|
||||
multi_json (~> 1.12)
|
||||
rdf (>= 2.2.8, < 4.0)
|
||||
json-ld-preloaded (2.2.3)
|
||||
json-ld-preloaded (3.0.0)
|
||||
json-ld (>= 2.2, < 4.0)
|
||||
multi_json (~> 1.12)
|
||||
rdf (>= 2.2, < 4.0)
|
||||
rdf (~> 3.0)
|
||||
jsonapi-renderer (0.2.0)
|
||||
jwt (2.1.0)
|
||||
kaminari (1.1.1)
|
||||
|
@ -311,7 +310,7 @@ GEM
|
|||
kaminari-core (1.1.1)
|
||||
launchy (2.4.3)
|
||||
addressable (~> 2.3)
|
||||
letter_opener (1.6.0)
|
||||
letter_opener (1.7.0)
|
||||
launchy (~> 2.2)
|
||||
letter_opener_web (1.3.4)
|
||||
actionmailer (>= 3.2)
|
||||
|
@ -326,16 +325,16 @@ GEM
|
|||
loofah (2.2.3)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
mail (2.7.0)
|
||||
mail (2.7.1)
|
||||
mini_mime (>= 0.1.1)
|
||||
makara (0.4.0)
|
||||
activerecord (>= 3.0.0)
|
||||
marcel (0.3.2)
|
||||
marcel (0.3.3)
|
||||
mimemagic (~> 0.3.2)
|
||||
mario-redis-lock (1.2.1)
|
||||
redis (>= 3.0.5)
|
||||
memory_profiler (0.9.12)
|
||||
method_source (0.9.0)
|
||||
method_source (0.9.2)
|
||||
microformats (4.0.7)
|
||||
json
|
||||
nokogiri
|
||||
|
@ -344,7 +343,7 @@ GEM
|
|||
mime-types-data (3.2018.0812)
|
||||
mimemagic (0.3.2)
|
||||
mini_mime (1.0.1)
|
||||
mini_portile2 (2.3.0)
|
||||
mini_portile2 (2.4.0)
|
||||
minitest (5.11.3)
|
||||
msgpack (1.2.4)
|
||||
multi_json (1.13.1)
|
||||
|
@ -355,18 +354,18 @@ GEM
|
|||
net-ssh (>= 2.6.5)
|
||||
net-ssh (5.0.2)
|
||||
nio4r (2.3.1)
|
||||
nokogiri (1.8.5)
|
||||
mini_portile2 (~> 2.3.0)
|
||||
nokogiri (1.10.1)
|
||||
mini_portile2 (~> 2.4.0)
|
||||
nokogumbo (2.0.0)
|
||||
nokogiri (~> 1.8, >= 1.8.4)
|
||||
nsa (0.2.4)
|
||||
nsa (0.2.7)
|
||||
activesupport (>= 4.2, < 6)
|
||||
concurrent-ruby (~> 1.0.0)
|
||||
sidekiq (>= 3.5.0)
|
||||
statsd-ruby (~> 1.2.0)
|
||||
oj (3.7.0)
|
||||
omniauth (1.8.1)
|
||||
hashie (>= 3.4.6, < 3.6.0)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
sidekiq (>= 3.5)
|
||||
statsd-ruby (~> 1.4, >= 1.4.0)
|
||||
oj (3.7.7)
|
||||
omniauth (1.9.0)
|
||||
hashie (>= 3.4.6, < 3.7.0)
|
||||
rack (>= 1.6.2, < 3)
|
||||
omniauth-cas (1.1.1)
|
||||
addressable (~> 2.3)
|
||||
|
@ -391,17 +390,17 @@ GEM
|
|||
av (~> 0.9.0)
|
||||
paperclip (>= 2.5.2)
|
||||
parallel (1.12.1)
|
||||
parallel_tests (2.26.0)
|
||||
parallel_tests (2.27.1)
|
||||
parallel
|
||||
parser (2.5.3.0)
|
||||
parser (2.6.0.0)
|
||||
ast (~> 2.4.0)
|
||||
pastel (0.7.2)
|
||||
equatable (~> 0.5.0)
|
||||
tty-color (~> 0.4.0)
|
||||
pg (1.1.3)
|
||||
pg (1.1.4)
|
||||
pghero (2.2.0)
|
||||
activerecord
|
||||
pkg-config (1.3.1)
|
||||
pkg-config (1.3.2)
|
||||
powerpack (0.1.2)
|
||||
premailer (1.11.1)
|
||||
addressable
|
||||
|
@ -411,46 +410,46 @@ GEM
|
|||
actionmailer (>= 3, < 6)
|
||||
premailer (~> 1.7, >= 1.7.9)
|
||||
private_address_check (0.5.0)
|
||||
pry (0.11.3)
|
||||
pry (0.12.2)
|
||||
coderay (~> 1.1.0)
|
||||
method_source (~> 0.9.0)
|
||||
pry-byebug (3.6.0)
|
||||
byebug (~> 10.0)
|
||||
pry (~> 0.10)
|
||||
pry-rails (0.3.6)
|
||||
pry-rails (0.3.9)
|
||||
pry (>= 0.10.4)
|
||||
public_suffix (3.0.3)
|
||||
puma (3.12.0)
|
||||
pundit (2.0.0)
|
||||
activesupport (>= 3.0.0)
|
||||
raabro (1.1.6)
|
||||
rack (2.0.5)
|
||||
rack-attack (5.4.1)
|
||||
rack (2.0.6)
|
||||
rack-attack (5.4.2)
|
||||
rack (>= 1.0, < 3)
|
||||
rack-cors (1.0.2)
|
||||
rack-protection (2.0.4)
|
||||
rack-protection (2.0.5)
|
||||
rack
|
||||
rack-proxy (0.6.4)
|
||||
rack
|
||||
rack-test (1.1.0)
|
||||
rack (>= 1.0, < 3)
|
||||
rails (5.2.1)
|
||||
actioncable (= 5.2.1)
|
||||
actionmailer (= 5.2.1)
|
||||
actionpack (= 5.2.1)
|
||||
actionview (= 5.2.1)
|
||||
activejob (= 5.2.1)
|
||||
activemodel (= 5.2.1)
|
||||
activerecord (= 5.2.1)
|
||||
activestorage (= 5.2.1)
|
||||
activesupport (= 5.2.1)
|
||||
rails (5.2.2)
|
||||
actioncable (= 5.2.2)
|
||||
actionmailer (= 5.2.2)
|
||||
actionpack (= 5.2.2)
|
||||
actionview (= 5.2.2)
|
||||
activejob (= 5.2.2)
|
||||
activemodel (= 5.2.2)
|
||||
activerecord (= 5.2.2)
|
||||
activestorage (= 5.2.2)
|
||||
activesupport (= 5.2.2)
|
||||
bundler (>= 1.3.0)
|
||||
railties (= 5.2.1)
|
||||
railties (= 5.2.2)
|
||||
sprockets-rails (>= 2.0.0)
|
||||
rails-controller-testing (1.0.2)
|
||||
actionpack (~> 5.x, >= 5.0.1)
|
||||
actionview (~> 5.x, >= 5.0.1)
|
||||
activesupport (~> 5.x)
|
||||
rails-controller-testing (1.0.4)
|
||||
actionpack (>= 5.0.1.x)
|
||||
actionview (>= 5.0.1.x)
|
||||
activesupport (>= 5.0.1.x)
|
||||
rails-dom-testing (2.0.3)
|
||||
activesupport (>= 4.2.0)
|
||||
nokogiri (>= 1.6)
|
||||
|
@ -461,23 +460,23 @@ GEM
|
|||
railties (>= 5.0, < 6)
|
||||
rails-settings-cached (0.6.6)
|
||||
rails (>= 4.2.0)
|
||||
railties (5.2.1)
|
||||
actionpack (= 5.2.1)
|
||||
activesupport (= 5.2.1)
|
||||
railties (5.2.2)
|
||||
actionpack (= 5.2.2)
|
||||
activesupport (= 5.2.2)
|
||||
method_source
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.19.0, < 2.0)
|
||||
rainbow (3.0.0)
|
||||
rake (12.3.1)
|
||||
rake (12.3.2)
|
||||
rb-fsevent (0.10.3)
|
||||
rb-inotify (0.9.10)
|
||||
ffi (>= 0.5.0, < 2)
|
||||
rdf (3.0.2)
|
||||
rdf (3.0.9)
|
||||
hamster (~> 3.0)
|
||||
link_header (~> 0.0, >= 0.0.8)
|
||||
rdf-normalize (0.3.3)
|
||||
rdf (>= 2.2, < 4.0)
|
||||
redis (4.0.2)
|
||||
redis (4.1.0)
|
||||
redis-actionpack (5.0.2)
|
||||
actionpack (>= 4.0, < 6)
|
||||
redis-rack (>= 1, < 3)
|
||||
|
@ -496,7 +495,7 @@ GEM
|
|||
redis-store (>= 1.2, < 2)
|
||||
redis-store (1.5.0)
|
||||
redis (>= 2.2, < 5)
|
||||
regexp_parser (1.2.0)
|
||||
regexp_parser (1.3.0)
|
||||
request_store (1.4.1)
|
||||
rack (>= 1.4)
|
||||
responders (2.4.0)
|
||||
|
@ -526,7 +525,7 @@ GEM
|
|||
rspec-core (~> 3.0, >= 3.0.0)
|
||||
sidekiq (>= 2.4.0)
|
||||
rspec-support (3.8.0)
|
||||
rubocop (0.60.0)
|
||||
rubocop (0.63.0)
|
||||
jaro_winkler (~> 1.5.1)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 2.5, != 2.5.1.1)
|
||||
|
@ -552,24 +551,25 @@ GEM
|
|||
scss_lint (0.57.1)
|
||||
rake (>= 0.9, < 13)
|
||||
sass (~> 3.5, >= 3.5.5)
|
||||
sidekiq (5.2.2)
|
||||
sidekiq (5.2.5)
|
||||
connection_pool (~> 2.2, >= 2.2.2)
|
||||
rack (>= 1.5.0)
|
||||
rack-protection (>= 1.5.0)
|
||||
redis (>= 3.3.5, < 5)
|
||||
sidekiq-bulk (0.1.1)
|
||||
activesupport
|
||||
sidekiq-bulk (0.2.0)
|
||||
sidekiq
|
||||
sidekiq-scheduler (3.0.0)
|
||||
redis (>= 3, < 5)
|
||||
rufus-scheduler (~> 3.2)
|
||||
sidekiq (>= 3)
|
||||
tilt (>= 1.4.0)
|
||||
sidekiq-unique-jobs (5.0.10)
|
||||
sidekiq (>= 4.0, <= 6.0)
|
||||
sidekiq-unique-jobs (6.0.8)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.5)
|
||||
sidekiq (>= 4.0, < 6.0)
|
||||
thor (~> 0)
|
||||
simple-navigation (4.0.5)
|
||||
activesupport (>= 2.3.2)
|
||||
simple_form (4.0.1)
|
||||
simple_form (4.1.0)
|
||||
actionpack (>= 5.0)
|
||||
activemodel (>= 5.0)
|
||||
simplecov (0.16.1)
|
||||
|
@ -588,7 +588,7 @@ GEM
|
|||
net-scp (>= 1.1.2)
|
||||
net-ssh (>= 2.8.0)
|
||||
stackprof (0.2.12)
|
||||
statsd-ruby (1.2.1)
|
||||
statsd-ruby (1.4.0)
|
||||
stoplight (2.1.3)
|
||||
streamio-ffmpeg (3.0.2)
|
||||
multi_json (~> 1.8)
|
||||
|
@ -599,22 +599,21 @@ GEM
|
|||
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||
terrapin (0.6.0)
|
||||
climate_control (>= 0.0.3, < 1.0)
|
||||
thor (0.20.0)
|
||||
thor (0.20.3)
|
||||
thread_safe (0.3.6)
|
||||
tilt (2.0.8)
|
||||
timers (4.1.2)
|
||||
hitimes
|
||||
timers (4.2.0)
|
||||
tty-color (0.4.3)
|
||||
tty-command (0.8.2)
|
||||
pastel (~> 0.7.0)
|
||||
tty-cursor (0.6.0)
|
||||
tty-prompt (0.17.1)
|
||||
tty-prompt (0.18.1)
|
||||
necromancer (~> 0.4.0)
|
||||
pastel (~> 0.7.0)
|
||||
timers (~> 4.0)
|
||||
tty-cursor (~> 0.6.0)
|
||||
tty-reader (~> 0.4.0)
|
||||
tty-reader (0.4.0)
|
||||
tty-reader (~> 0.5.0)
|
||||
tty-reader (0.5.0)
|
||||
tty-cursor (~> 0.6.0)
|
||||
tty-screen (~> 0.6.4)
|
||||
wisper (~> 2.0.0)
|
||||
|
@ -623,16 +622,16 @@ GEM
|
|||
unf (~> 0.1.0)
|
||||
tzinfo (1.2.5)
|
||||
thread_safe (~> 0.1)
|
||||
tzinfo-data (1.2018.7)
|
||||
tzinfo-data (1.2018.9)
|
||||
tzinfo (>= 1.0.0)
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.7.5)
|
||||
unicode-display_width (1.4.0)
|
||||
uniform_notifier (1.11.0)
|
||||
unicode-display_width (1.4.1)
|
||||
uniform_notifier (1.12.1)
|
||||
warden (1.2.7)
|
||||
rack (>= 1.0)
|
||||
webmock (3.4.2)
|
||||
webmock (3.5.1)
|
||||
addressable (>= 2.3.6)
|
||||
crack (>= 0.3.2)
|
||||
hashdiff
|
||||
|
@ -640,7 +639,7 @@ GEM
|
|||
activesupport (>= 4.2)
|
||||
rack-proxy (>= 0.6.1)
|
||||
railties (>= 4.2)
|
||||
webpush (0.3.4)
|
||||
webpush (0.3.6)
|
||||
hkdf (~> 0.2)
|
||||
jwt (~> 2.0)
|
||||
websocket-driver (0.7.0)
|
||||
|
@ -658,29 +657,30 @@ DEPENDENCIES
|
|||
active_record_query_trace (~> 1.5)
|
||||
addressable (~> 2.5)
|
||||
annotate (~> 2.7)
|
||||
aws-sdk-s3 (~> 1.23)
|
||||
aws-sdk-s3 (~> 1.30)
|
||||
better_errors (~> 2.5)
|
||||
binding_of_caller (~> 0.7)
|
||||
bootsnap (~> 1.3)
|
||||
brakeman (~> 4.3)
|
||||
brakeman (~> 4.4)
|
||||
browser
|
||||
bullet (~> 5.7)
|
||||
bullet (~> 5.9)
|
||||
bundler-audit (~> 0.6)
|
||||
capistrano (~> 3.11)
|
||||
capistrano-rails (~> 1.4)
|
||||
capistrano-rbenv (~> 2.1)
|
||||
capistrano-yarn (~> 2.0)
|
||||
capybara (~> 3.10)
|
||||
capybara (~> 3.12)
|
||||
charlock_holmes (~> 0.7.6)
|
||||
chewy (~> 5.0)
|
||||
cld3 (~> 3.2.0)
|
||||
cld3 (~> 3.2.3)
|
||||
climate_control (~> 0.2)
|
||||
concurrent-ruby
|
||||
derailed_benchmarks
|
||||
devise (~> 4.5)
|
||||
devise-two-factor (~> 3.0)
|
||||
devise_pam_authenticatable2 (~> 9.2)
|
||||
doorkeeper (~> 5.0)
|
||||
dotenv-rails (~> 2.5)
|
||||
dotenv-rails (~> 2.6)
|
||||
fabrication (~> 2.20)
|
||||
faker (~> 1.9)
|
||||
fast_blank (~> 1.0)
|
||||
|
@ -695,14 +695,14 @@ DEPENDENCIES
|
|||
http (~> 3.3)
|
||||
http_accept_language (~> 2.1)
|
||||
http_parser.rb (~> 0.6)!
|
||||
httplog (~> 1.1)
|
||||
httplog (~> 1.2)
|
||||
i18n-tasks (~> 0.9)
|
||||
idn-ruby
|
||||
iso-639
|
||||
json-ld (~> 2.2)
|
||||
json-ld-preloaded (~> 2.2)
|
||||
json-ld (~> 3.0)
|
||||
json-ld-preloaded (~> 3.0)
|
||||
kaminari (~> 1.1)
|
||||
letter_opener (~> 1.4)
|
||||
letter_opener (~> 1.7)
|
||||
letter_opener_web (~> 1.3)
|
||||
link_header (~> 0.0)
|
||||
lograge (~> 0.10)
|
||||
|
@ -712,17 +712,17 @@ DEPENDENCIES
|
|||
microformats (~> 4.0)
|
||||
mime-types (~> 3.2)
|
||||
net-ldap (~> 0.10)
|
||||
nokogiri (~> 1.8)
|
||||
nokogiri (~> 1.10)
|
||||
nsa (~> 0.2)
|
||||
oj (~> 3.7)
|
||||
omniauth (~> 1.2)
|
||||
omniauth (~> 1.9)
|
||||
omniauth-cas (~> 1.1)
|
||||
omniauth-saml (~> 1.10)
|
||||
ostatus2 (~> 2.0)
|
||||
ox (~> 2.10)
|
||||
paperclip (~> 6.0)
|
||||
paperclip-av-transcoder (~> 0.6)
|
||||
parallel_tests (~> 2.26)
|
||||
parallel_tests (~> 2.27)
|
||||
pg (~> 1.1)
|
||||
pghero (~> 2.2)
|
||||
pkg-config (~> 1.3)
|
||||
|
@ -735,26 +735,26 @@ DEPENDENCIES
|
|||
pundit (~> 2.0)
|
||||
rack-attack (~> 5.4)
|
||||
rack-cors (~> 1.0)
|
||||
rails (~> 5.2.1)
|
||||
rails (~> 5.2.2)
|
||||
rails-controller-testing (~> 1.0)
|
||||
rails-i18n (~> 5.1)
|
||||
rails-settings-cached (~> 0.6)
|
||||
rdf-normalize (~> 0.3)
|
||||
redis (~> 4.0)
|
||||
redis (~> 4.1)
|
||||
redis-namespace (~> 1.5)
|
||||
redis-rails (~> 5.0)
|
||||
rqrcode (~> 0.10)
|
||||
rspec-rails (~> 3.8)
|
||||
rspec-sidekiq (~> 3.0)
|
||||
rubocop (~> 0.60)
|
||||
rubocop (~> 0.63)
|
||||
sanitize (~> 5.0)
|
||||
scss_lint (~> 0.57)
|
||||
sidekiq (~> 5.2)
|
||||
sidekiq-bulk (~> 0.1.1)
|
||||
sidekiq-bulk (~> 0.2.0)
|
||||
sidekiq-scheduler (~> 3.0)
|
||||
sidekiq-unique-jobs (~> 5.0)
|
||||
sidekiq-unique-jobs (~> 6.0)
|
||||
simple-navigation (~> 4.0)
|
||||
simple_form (~> 4.0)
|
||||
simple_form (~> 4.1)
|
||||
simplecov (~> 0.16)
|
||||
sprockets-rails (~> 3.2)
|
||||
stackprof
|
||||
|
@ -763,15 +763,15 @@ DEPENDENCIES
|
|||
strong_migrations (~> 0.3)
|
||||
thor (~> 0.20)
|
||||
tty-command (~> 0.8)
|
||||
tty-prompt (~> 0.17)
|
||||
tty-prompt (~> 0.18)
|
||||
twitter-text (~> 1.14)
|
||||
tzinfo-data (~> 1.2018)
|
||||
webmock (~> 3.4)
|
||||
webmock (~> 3.5)
|
||||
webpacker (~> 3.5)
|
||||
webpush
|
||||
|
||||
RUBY VERSION
|
||||
ruby 2.5.3p105
|
||||
ruby 2.6.0p0
|
||||
|
||||
BUNDLED WITH
|
||||
1.16.6
|
||||
1.17.3
|
||||
|
|
2
Vagrantfile
vendored
2
Vagrantfile
vendored
|
@ -44,7 +44,7 @@ sudo apt-get install \
|
|||
|
||||
# Install rvm
|
||||
read RUBY_VERSION < .ruby-version
|
||||
gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
|
||||
gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
|
||||
curl -sSL https://raw.githubusercontent.com/rvm/rvm/stable/binscripts/rvm-installer | bash -s stable --ruby=$RUBY_VERSION
|
||||
source /home/vagrant/.rvm/scripts/rvm
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ class ActivityPub::CollectionsController < Api::BaseController
|
|||
when 'featured'
|
||||
@account.pinned_statuses.count
|
||||
else
|
||||
raise ActiveRecord::NotFound
|
||||
raise ActiveRecord::RecordNotFound
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -42,7 +42,7 @@ class ActivityPub::CollectionsController < Api::BaseController
|
|||
scope.merge!(@account.pinned_statuses)
|
||||
end
|
||||
else
|
||||
raise ActiveRecord::NotFound
|
||||
raise ActiveRecord::RecordNotFound
|
||||
end
|
||||
end
|
||||
|
||||
|
|
36
app/controllers/admin/account_actions_controller.rb
Normal file
36
app/controllers/admin/account_actions_controller.rb
Normal file
|
@ -0,0 +1,36 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Admin
|
||||
class AccountActionsController < BaseController
|
||||
before_action :set_account
|
||||
|
||||
def new
|
||||
@account_action = Admin::AccountAction.new(type: params[:type], report_id: params[:report_id], send_email_notification: true)
|
||||
@warning_presets = AccountWarningPreset.all
|
||||
end
|
||||
|
||||
def create
|
||||
account_action = Admin::AccountAction.new(resource_params)
|
||||
account_action.target_account = @account
|
||||
account_action.current_account = current_account
|
||||
|
||||
account_action.save!
|
||||
|
||||
if account_action.with_report?
|
||||
redirect_to admin_reports_path
|
||||
else
|
||||
redirect_to admin_account_path(@account.id)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_account
|
||||
@account = Account.find(params[:account_id])
|
||||
end
|
||||
|
||||
def resource_params
|
||||
params.require(:admin_account_action).permit(:type, :report_id, :warning_preset_id, :text, :send_email_notification)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -14,6 +14,7 @@ module Admin
|
|||
else
|
||||
@account = @account_moderation_note.target_account
|
||||
@moderation_notes = @account.targeted_moderation_notes.latest
|
||||
@warnings = @account.targeted_account_warnings.latest.custom
|
||||
|
||||
render template: 'admin/accounts/show'
|
||||
end
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
module Admin
|
||||
class AccountsController < BaseController
|
||||
before_action :set_account, only: [:show, :subscribe, :unsubscribe, :redownload, :remove_avatar, :enable, :disable, :memorialize]
|
||||
before_action :set_account, only: [:show, :subscribe, :unsubscribe, :redownload, :remove_avatar, :remove_header, :enable, :unsilence, :unsuspend, :memorialize]
|
||||
before_action :require_remote_account!, only: [:subscribe, :unsubscribe, :redownload]
|
||||
before_action :require_local_account!, only: [:enable, :disable, :memorialize]
|
||||
before_action :require_local_account!, only: [:enable, :memorialize]
|
||||
|
||||
def index
|
||||
authorize :account, :index?
|
||||
|
@ -13,8 +13,10 @@ module Admin
|
|||
|
||||
def show
|
||||
authorize @account, :show?
|
||||
|
||||
@account_moderation_note = current_account.account_moderation_notes.new(target_account: @account)
|
||||
@moderation_notes = @account.targeted_moderation_notes.latest
|
||||
@warnings = @account.targeted_account_warnings.latest.custom
|
||||
end
|
||||
|
||||
def subscribe
|
||||
|
@ -43,19 +45,25 @@ module Admin
|
|||
redirect_to admin_account_path(@account.id)
|
||||
end
|
||||
|
||||
def disable
|
||||
authorize @account.user, :disable?
|
||||
@account.user.disable!
|
||||
log_action :disable, @account.user
|
||||
def unsilence
|
||||
authorize @account, :unsilence?
|
||||
@account.unsilence!
|
||||
log_action :unsilence, @account
|
||||
redirect_to admin_account_path(@account.id)
|
||||
end
|
||||
|
||||
def unsuspend
|
||||
authorize @account, :unsuspend?
|
||||
@account.unsuspend!
|
||||
log_action :unsuspend, @account
|
||||
redirect_to admin_account_path(@account.id)
|
||||
end
|
||||
|
||||
def redownload
|
||||
authorize @account, :redownload?
|
||||
|
||||
@account.reset_avatar!
|
||||
@account.reset_header!
|
||||
@account.save!
|
||||
@account.update!(last_webfingered_at: nil)
|
||||
ResolveAccountService.new.call(@account)
|
||||
|
||||
redirect_to admin_account_path(@account.id)
|
||||
end
|
||||
|
@ -71,6 +79,17 @@ module Admin
|
|||
redirect_to admin_account_path(@account.id)
|
||||
end
|
||||
|
||||
def remove_header
|
||||
authorize @account, :remove_header?
|
||||
|
||||
@account.header = nil
|
||||
@account.save!
|
||||
|
||||
log_action :remove_header, @account.user
|
||||
|
||||
redirect_to admin_account_path(@account.id)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_account
|
||||
|
@ -94,8 +113,8 @@ module Admin
|
|||
:local,
|
||||
:remote,
|
||||
:by_domain,
|
||||
:active,
|
||||
:silenced,
|
||||
:alphabetic,
|
||||
:suspended,
|
||||
:username,
|
||||
:display_name,
|
||||
|
|
|
@ -15,5 +15,9 @@ module Admin
|
|||
def set_body_classes
|
||||
@body_classes = 'admin'
|
||||
end
|
||||
|
||||
def set_user
|
||||
@user = Account.find(params[:account_id]).user || raise(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -25,10 +25,6 @@ module Admin
|
|||
|
||||
private
|
||||
|
||||
def set_user
|
||||
@user = Account.find(params[:account_id]).user || raise(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
|
||||
def check_confirmation
|
||||
if @user.confirmed?
|
||||
flash[:error] = I18n.t('admin.accounts.resend_confirmation.already_confirmed')
|
||||
|
|
|
@ -28,6 +28,7 @@ module Admin
|
|||
@pam_enabled = ENV['PAM_ENABLED'] == 'true'
|
||||
@hidden_service = ENV['ALLOW_ACCESS_TO_HIDDEN_SERVICE'] == 'true'
|
||||
@trending_hashtags = TrendingTags.get(7)
|
||||
@profile_directory = Setting.profile_directory
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -4,14 +4,9 @@ module Admin
|
|||
class DomainBlocksController < BaseController
|
||||
before_action :set_domain_block, only: [:show, :destroy]
|
||||
|
||||
def index
|
||||
authorize :domain_block, :index?
|
||||
@domain_blocks = DomainBlock.page(params[:page])
|
||||
end
|
||||
|
||||
def new
|
||||
authorize :domain_block, :create?
|
||||
@domain_block = DomainBlock.new
|
||||
@domain_block = DomainBlock.new(domain: params[:_domain])
|
||||
end
|
||||
|
||||
def create
|
||||
|
@ -22,7 +17,7 @@ module Admin
|
|||
if @domain_block.save
|
||||
DomainBlockWorker.perform_async(@domain_block.id)
|
||||
log_action :create, @domain_block
|
||||
redirect_to admin_domain_blocks_path, notice: I18n.t('admin.domain_blocks.created_msg')
|
||||
redirect_to admin_instances_path(limited: '1'), notice: I18n.t('admin.domain_blocks.created_msg')
|
||||
else
|
||||
render :new
|
||||
end
|
||||
|
@ -36,7 +31,7 @@ module Admin
|
|||
authorize @domain_block, :destroy?
|
||||
UnblockDomainService.new.call(@domain_block, retroactive_unblock?)
|
||||
log_action :destroy, @domain_block
|
||||
redirect_to admin_domain_blocks_path, notice: I18n.t('admin.domain_blocks.destroyed_msg')
|
||||
redirect_to admin_instances_path(limited: '1'), notice: I18n.t('admin.domain_blocks.destroyed_msg')
|
||||
end
|
||||
|
||||
private
|
||||
|
|
18
app/controllers/admin/followers_controller.rb
Normal file
18
app/controllers/admin/followers_controller.rb
Normal file
|
@ -0,0 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Admin
|
||||
class FollowersController < BaseController
|
||||
before_action :set_account
|
||||
|
||||
PER_PAGE = 40
|
||||
|
||||
def index
|
||||
authorize :account, :index?
|
||||
@followers = @account.followers.local.recent.page(params[:page]).per(PER_PAGE)
|
||||
end
|
||||
|
||||
def set_account
|
||||
@account = Account.find(params[:account_id])
|
||||
end
|
||||
end
|
||||
end
|
|
@ -4,14 +4,21 @@ module Admin
|
|||
class InstancesController < BaseController
|
||||
def index
|
||||
authorize :instance, :index?
|
||||
|
||||
@instances = ordered_instances
|
||||
end
|
||||
|
||||
def resubscribe
|
||||
authorize :instance, :resubscribe?
|
||||
params.require(:by_domain)
|
||||
Pubsubhubbub::SubscribeWorker.push_bulk(subscribeable_accounts.pluck(:id))
|
||||
redirect_to admin_instances_path
|
||||
def show
|
||||
authorize :instance, :show?
|
||||
|
||||
@instance = Instance.new(Account.by_domain_accounts.find_by(domain: params[:id]) || DomainBlock.find_by!(domain: params[:id]))
|
||||
@following_count = Follow.where(account: Account.where(domain: params[:id])).count
|
||||
@followers_count = Follow.where(target_account: Account.where(domain: params[:id])).count
|
||||
@reports_count = Report.where(target_account: Account.where(domain: params[:id])).count
|
||||
@blocks_count = Block.where(target_account: Account.where(domain: params[:id])).count
|
||||
@available = DeliveryFailureTracker.available?(Account.select(:shared_inbox_url).where(domain: params[:id]).first&.shared_inbox_url)
|
||||
@media_storage = MediaAttachment.where(account: Account.where(domain: params[:id])).sum(:file_file_size)
|
||||
@domain_block = DomainBlock.find_by(domain: params[:id])
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -27,17 +34,11 @@ module Admin
|
|||
helper_method :paginated_instances
|
||||
|
||||
def ordered_instances
|
||||
paginated_instances.map { |account| Instance.new(account) }
|
||||
end
|
||||
|
||||
def subscribeable_accounts
|
||||
Account.with_followers.remote.where(domain: params[:by_domain])
|
||||
paginated_instances.map { |resource| Instance.new(resource) }
|
||||
end
|
||||
|
||||
def filter_params
|
||||
params.permit(
|
||||
:domain_name
|
||||
)
|
||||
params.permit(:limited)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,75 +13,42 @@ module Admin
|
|||
authorize @report, :show?
|
||||
|
||||
@report_note = @report.notes.new
|
||||
@report_notes = (@report.notes.latest + @report.history).sort_by(&:created_at)
|
||||
@report_notes = (@report.notes.latest + @report.history + @report.target_account.targeted_account_warnings.latest.custom).sort_by(&:created_at)
|
||||
@form = Form::StatusBatch.new
|
||||
end
|
||||
|
||||
def update
|
||||
def assign_to_self
|
||||
authorize @report, :update?
|
||||
process_report
|
||||
|
||||
if @report.action_taken?
|
||||
redirect_to admin_reports_path, notice: I18n.t('admin.reports.resolved_msg')
|
||||
else
|
||||
@report.update!(assigned_account_id: current_account.id)
|
||||
log_action :assigned_to_self, @report
|
||||
redirect_to admin_report_path(@report)
|
||||
end
|
||||
|
||||
def unassign
|
||||
authorize @report, :update?
|
||||
@report.update!(assigned_account_id: nil)
|
||||
log_action :unassigned, @report
|
||||
redirect_to admin_report_path(@report)
|
||||
end
|
||||
|
||||
def reopen
|
||||
authorize @report, :update?
|
||||
@report.unresolve!
|
||||
log_action :reopen, @report
|
||||
redirect_to admin_report_path(@report)
|
||||
end
|
||||
|
||||
def resolve
|
||||
authorize @report, :update?
|
||||
@report.resolve!(current_account)
|
||||
log_action :resolve, @report
|
||||
redirect_to admin_reports_path, notice: I18n.t('admin.reports.resolved_msg')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def process_report
|
||||
case params[:outcome].to_s
|
||||
when 'assign_to_self'
|
||||
@report.update!(assigned_account_id: current_account.id)
|
||||
log_action :assigned_to_self, @report
|
||||
when 'unassign'
|
||||
@report.update!(assigned_account_id: nil)
|
||||
log_action :unassigned, @report
|
||||
when 'reopen'
|
||||
@report.unresolve!
|
||||
log_action :reopen, @report
|
||||
when 'resolve'
|
||||
@report.resolve!(current_account)
|
||||
log_action :resolve, @report
|
||||
when 'disable'
|
||||
@report.resolve!(current_account)
|
||||
@report.target_account.user.disable!
|
||||
|
||||
log_action :resolve, @report
|
||||
log_action :disable, @report.target_account.user
|
||||
|
||||
resolve_all_target_account_reports
|
||||
when 'silence'
|
||||
@report.resolve!(current_account)
|
||||
@report.target_account.update!(silenced: true)
|
||||
|
||||
log_action :resolve, @report
|
||||
log_action :silence, @report.target_account
|
||||
|
||||
resolve_all_target_account_reports
|
||||
else
|
||||
raise ActiveRecord::RecordNotFound
|
||||
end
|
||||
|
||||
@report.reload
|
||||
end
|
||||
|
||||
def resolve_all_target_account_reports
|
||||
unresolved_reports_for_target_account.update_all(action_taken: true, action_taken_by_account_id: current_account.id)
|
||||
end
|
||||
|
||||
def unresolved_reports_for_target_account
|
||||
Report.where(
|
||||
target_account: @report.target_account
|
||||
).unresolved
|
||||
end
|
||||
|
||||
def filtered_reports
|
||||
ReportFilter.new(filter_params).results.order(id: :desc).includes(
|
||||
:account,
|
||||
:target_account
|
||||
)
|
||||
ReportFilter.new(filter_params).results.order(id: :desc).includes(:account, :target_account)
|
||||
end
|
||||
|
||||
def filter_params
|
||||
|
|
|
@ -10,11 +10,5 @@ module Admin
|
|||
log_action :reset_password, @user
|
||||
redirect_to admin_accounts_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_user
|
||||
@user = Account.find(params[:account_id]).user || raise(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -17,11 +17,5 @@ module Admin
|
|||
log_action :demote, @user
|
||||
redirect_to admin_account_path(@user.account_id)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_user
|
||||
@user = Account.find(params[:account_id]).user || raise(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -26,6 +26,7 @@ module Admin
|
|||
show_known_fediverse_at_about_page
|
||||
preview_sensitive_media
|
||||
custom_css
|
||||
profile_directory
|
||||
).freeze
|
||||
|
||||
BOOLEAN_SETTINGS = %w(
|
||||
|
@ -37,6 +38,7 @@ module Admin
|
|||
peers_api_enabled
|
||||
show_known_fediverse_at_about_page
|
||||
preview_sensitive_media
|
||||
profile_directory
|
||||
).freeze
|
||||
|
||||
UPLOAD_SETTINGS = %w(
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Admin
|
||||
class SilencesController < BaseController
|
||||
before_action :set_account
|
||||
|
||||
def create
|
||||
authorize @account, :silence?
|
||||
@account.update!(silenced: true)
|
||||
log_action :silence, @account
|
||||
redirect_to admin_accounts_path
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize @account, :unsilence?
|
||||
@account.update!(silenced: false)
|
||||
log_action :unsilence, @account
|
||||
redirect_to admin_accounts_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_account
|
||||
@account = Account.find(params[:account_id])
|
||||
end
|
||||
end
|
||||
end
|
|
@ -22,6 +22,15 @@ module Admin
|
|||
@form = Form::StatusBatch.new
|
||||
end
|
||||
|
||||
def show
|
||||
authorize :status, :index?
|
||||
|
||||
@statuses = @account.statuses.where(id: params[:id])
|
||||
authorize @statuses.first, :show?
|
||||
|
||||
@form = Form::StatusBatch.new
|
||||
end
|
||||
|
||||
def create
|
||||
authorize :status, :update?
|
||||
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Admin
|
||||
class SuspensionsController < BaseController
|
||||
before_action :set_account
|
||||
|
||||
def new
|
||||
@suspension = Form::AdminSuspensionConfirmation.new(report_id: params[:report_id])
|
||||
end
|
||||
|
||||
def create
|
||||
authorize @account, :suspend?
|
||||
|
||||
@suspension = Form::AdminSuspensionConfirmation.new(suspension_params)
|
||||
|
||||
if suspension_params[:acct] == @account.acct
|
||||
resolve_report! if suspension_params[:report_id].present?
|
||||
perform_suspend!
|
||||
mark_reports_resolved!
|
||||
redirect_to admin_accounts_path
|
||||
else
|
||||
flash.now[:alert] = I18n.t('admin.suspensions.bad_acct_msg')
|
||||
render :new
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize @account, :unsuspend?
|
||||
@account.unsuspend!
|
||||
log_action :unsuspend, @account
|
||||
redirect_to admin_accounts_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_account
|
||||
@account = Account.find(params[:account_id])
|
||||
end
|
||||
|
||||
def suspension_params
|
||||
params.require(:form_admin_suspension_confirmation).permit(:acct, :report_id)
|
||||
end
|
||||
|
||||
def resolve_report!
|
||||
report = Report.find(suspension_params[:report_id])
|
||||
report.resolve!(current_account)
|
||||
log_action :resolve, report
|
||||
end
|
||||
|
||||
def perform_suspend!
|
||||
@account.suspend!
|
||||
Admin::SuspensionWorker.perform_async(@account.id)
|
||||
log_action :suspend, @account
|
||||
end
|
||||
|
||||
def mark_reports_resolved!
|
||||
Report.where(target_account: @account).unresolved.update_all(action_taken: true, action_taken_by_account_id: current_account.id)
|
||||
end
|
||||
end
|
||||
end
|
44
app/controllers/admin/tags_controller.rb
Normal file
44
app/controllers/admin/tags_controller.rb
Normal file
|
@ -0,0 +1,44 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Admin
|
||||
class TagsController < BaseController
|
||||
before_action :set_tags, only: :index
|
||||
before_action :set_tag, except: :index
|
||||
before_action :set_filter_params
|
||||
|
||||
def index
|
||||
authorize :tag, :index?
|
||||
end
|
||||
|
||||
def hide
|
||||
authorize @tag, :hide?
|
||||
@tag.account_tag_stat.update!(hidden: true)
|
||||
redirect_to admin_tags_path(@filter_params)
|
||||
end
|
||||
|
||||
def unhide
|
||||
authorize @tag, :unhide?
|
||||
@tag.account_tag_stat.update!(hidden: false)
|
||||
redirect_to admin_tags_path(@filter_params)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_tags
|
||||
@tags = Tag.discoverable
|
||||
@tags.merge!(Tag.hidden) if filter_params[:hidden]
|
||||
end
|
||||
|
||||
def set_tag
|
||||
@tag = Tag.find(params[:id])
|
||||
end
|
||||
|
||||
def set_filter_params
|
||||
@filter_params = filter_params.to_hash.symbolize_keys
|
||||
end
|
||||
|
||||
def filter_params
|
||||
params.permit(:hidden)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
module Admin
|
||||
class TwoFactorAuthenticationsController < BaseController
|
||||
before_action :set_user
|
||||
before_action :set_target_user
|
||||
|
||||
def destroy
|
||||
authorize @user, :disable_2fa?
|
||||
|
@ -13,7 +13,7 @@ module Admin
|
|||
|
||||
private
|
||||
|
||||
def set_user
|
||||
def set_target_user
|
||||
@user = User.find(params[:user_id])
|
||||
end
|
||||
end
|
||||
|
|
58
app/controllers/admin/warning_presets_controller.rb
Normal file
58
app/controllers/admin/warning_presets_controller.rb
Normal file
|
@ -0,0 +1,58 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Admin
|
||||
class WarningPresetsController < BaseController
|
||||
before_action :set_warning_preset, except: [:index, :create]
|
||||
|
||||
def index
|
||||
authorize :account_warning_preset, :index?
|
||||
|
||||
@warning_presets = AccountWarningPreset.all
|
||||
@warning_preset = AccountWarningPreset.new
|
||||
end
|
||||
|
||||
def create
|
||||
authorize :account_warning_preset, :create?
|
||||
|
||||
@warning_preset = AccountWarningPreset.new(warning_preset_params)
|
||||
|
||||
if @warning_preset.save
|
||||
redirect_to admin_warning_presets_path
|
||||
else
|
||||
@warning_presets = AccountWarningPreset.all
|
||||
render :index
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
authorize @warning_preset, :update?
|
||||
end
|
||||
|
||||
def update
|
||||
authorize @warning_preset, :update?
|
||||
|
||||
if @warning_preset.update(warning_preset_params)
|
||||
redirect_to admin_warning_presets_path
|
||||
else
|
||||
render :edit
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize @warning_preset, :destroy?
|
||||
|
||||
@warning_preset.destroy!
|
||||
redirect_to admin_warning_presets_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_warning_preset
|
||||
@warning_preset = AccountWarningPreset.find(params[:id])
|
||||
end
|
||||
|
||||
def warning_preset_params
|
||||
params.require(:account_warning_preset).permit(:text)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -68,12 +68,14 @@ class Api::BaseController < ApplicationController
|
|||
end
|
||||
|
||||
def require_user!
|
||||
if current_user && !current_user.disabled?
|
||||
set_user_activity
|
||||
elsif current_user
|
||||
render json: { error: 'Your login is currently disabled' }, status: 403
|
||||
else
|
||||
if !current_user
|
||||
render json: { error: 'This method requires an authenticated user' }, status: 422
|
||||
elsif current_user.disabled?
|
||||
render json: { error: 'Your login is currently disabled' }, status: 403
|
||||
elsif !current_user.confirmed?
|
||||
render json: { error: 'Email confirmation is not completed' }, status: 403
|
||||
else
|
||||
set_user_activity
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ class Api::V1::Accounts::CredentialsController < Api::BaseController
|
|||
private
|
||||
|
||||
def account_params
|
||||
params.permit(:display_name, :note, :avatar, :header, :locked, :bot, fields_attributes: [:name, :value])
|
||||
params.permit(:display_name, :note, :avatar, :header, :locked, :bot, :discoverable, fields_attributes: [:name, :value])
|
||||
end
|
||||
|
||||
def user_settings_params
|
||||
|
|
|
@ -25,7 +25,7 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController
|
|||
end
|
||||
|
||||
def default_accounts
|
||||
Account.includes(:active_relationships).references(:active_relationships)
|
||||
Account.includes(:active_relationships, :account_stat).references(:active_relationships)
|
||||
end
|
||||
|
||||
def paginated_follows
|
||||
|
|
|
@ -25,7 +25,7 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController
|
|||
end
|
||||
|
||||
def default_accounts
|
||||
Account.includes(:passive_relationships).references(:passive_relationships)
|
||||
Account.includes(:passive_relationships, :account_stat).references(:passive_relationships)
|
||||
end
|
||||
|
||||
def paginated_follows
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Accounts::StatusesController < Api::BaseController
|
||||
before_action -> { doorkeeper_authorize! :read, :'read:statuses' }
|
||||
before_action -> { authorize_if_got_token! :read, :'read:statuses' }
|
||||
before_action :set_account
|
||||
after_action :insert_pagination_headers
|
||||
|
||||
|
@ -28,13 +28,11 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
|
|||
|
||||
def account_statuses
|
||||
statuses = truthy_param?(:pinned) ? pinned_scope : permitted_account_statuses
|
||||
statuses = statuses.paginate_by_id(
|
||||
limit_param(DEFAULT_STATUSES_LIMIT),
|
||||
params_slice(:max_id, :since_id, :min_id)
|
||||
)
|
||||
statuses = statuses.paginate_by_id(limit_param(DEFAULT_STATUSES_LIMIT), params_slice(:max_id, :since_id, :min_id))
|
||||
|
||||
statuses.merge!(only_media_scope) if truthy_param?(:only_media)
|
||||
statuses.merge!(no_replies_scope) if truthy_param?(:exclude_replies)
|
||||
statuses.merge!(no_reblogs_scope) if truthy_param?(:exclude_reblogs)
|
||||
|
||||
statuses
|
||||
end
|
||||
|
@ -65,6 +63,10 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
|
|||
Status.without_replies
|
||||
end
|
||||
|
||||
def no_reblogs_scope
|
||||
Status.without_reblogs
|
||||
end
|
||||
|
||||
def pagination_params(core_params)
|
||||
params.slice(:limit, :only_media, :exclude_replies).permit(:limit, :only_media, :exclude_replies).merge(core_params)
|
||||
end
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::AccountsController < Api::BaseController
|
||||
before_action -> { authorize_if_got_token! :read, :'read:accounts' }, except: [:follow, :unfollow, :block, :unblock, :mute, :unmute]
|
||||
before_action -> { authorize_if_got_token! :read, :'read:accounts' }, except: [:create, :follow, :unfollow, :block, :unblock, :mute, :unmute]
|
||||
before_action -> { doorkeeper_authorize! :follow, :'write:follows' }, only: [:follow, :unfollow]
|
||||
before_action -> { doorkeeper_authorize! :follow, :'write:mutes' }, only: [:mute, :unmute]
|
||||
before_action -> { doorkeeper_authorize! :follow, :'write:blocks' }, only: [:block, :unblock]
|
||||
before_action -> { doorkeeper_authorize! :write, :'write:accounts' }, only: [:create]
|
||||
|
||||
before_action :require_user!, except: [:show]
|
||||
before_action :set_account
|
||||
before_action :require_user!, except: [:show, :create]
|
||||
before_action :set_account, except: [:create]
|
||||
before_action :check_account_suspension, only: [:show]
|
||||
before_action :check_enabled_registrations, only: [:create]
|
||||
|
||||
respond_to :json
|
||||
|
||||
|
@ -16,6 +18,16 @@ class Api::V1::AccountsController < Api::BaseController
|
|||
render json: @account, serializer: REST::AccountSerializer
|
||||
end
|
||||
|
||||
def create
|
||||
token = AppSignUpService.new.call(doorkeeper_token.application, account_params)
|
||||
response = Doorkeeper::OAuth::TokenResponse.new(token)
|
||||
|
||||
headers.merge!(response.headers)
|
||||
|
||||
self.response_body = Oj.dump(response.body)
|
||||
self.status = response.status
|
||||
end
|
||||
|
||||
def follow
|
||||
FollowService.new.call(current_user.account, @account, reblogs: truthy_param?(:reblogs))
|
||||
|
||||
|
@ -62,4 +74,12 @@ class Api::V1::AccountsController < Api::BaseController
|
|||
def check_account_suspension
|
||||
gone if @account.suspended?
|
||||
end
|
||||
|
||||
def account_params
|
||||
params.permit(:username, :email, :password, :agreement, :locale)
|
||||
end
|
||||
|
||||
def check_enabled_registrations
|
||||
forbidden if single_user_mode? || !Setting.open_registrations
|
||||
end
|
||||
end
|
||||
|
|
|
@ -19,7 +19,7 @@ class Api::V1::BlocksController < Api::BaseController
|
|||
end
|
||||
|
||||
def paginated_blocks
|
||||
@paginated_blocks ||= Block.eager_load(:target_account)
|
||||
@paginated_blocks ||= Block.eager_load(target_account: :account_stat)
|
||||
.where(account: current_account)
|
||||
.paginate_by_max_id(
|
||||
limit_param(DEFAULT_ACCOUNTS_LIMIT),
|
||||
|
|
|
@ -4,6 +4,8 @@ class Api::V1::CustomEmojisController < Api::BaseController
|
|||
respond_to :json
|
||||
|
||||
def index
|
||||
render json: CustomEmoji.local.where(disabled: false), each_serializer: REST::CustomEmojiSerializer
|
||||
render_cached_json('api:v1:custom_emojis', expires_in: 1.minute) do
|
||||
ActiveModelSerializers::SerializableResource.new(CustomEmoji.local.where(disabled: false), each_serializer: REST::CustomEmojiSerializer)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -27,7 +27,7 @@ class Api::V1::EndorsementsController < Api::BaseController
|
|||
end
|
||||
|
||||
def endorsed_accounts
|
||||
current_account.endorsed_accounts
|
||||
current_account.endorsed_accounts.includes(:account_stat)
|
||||
end
|
||||
|
||||
def insert_pagination_headers
|
||||
|
|
|
@ -33,7 +33,7 @@ class Api::V1::FollowRequestsController < Api::BaseController
|
|||
end
|
||||
|
||||
def default_accounts
|
||||
Account.includes(:follow_requests).references(:follow_requests)
|
||||
Account.includes(:follow_requests, :account_stat).references(:follow_requests)
|
||||
end
|
||||
|
||||
def paginated_follow_requests
|
||||
|
|
|
@ -37,9 +37,9 @@ class Api::V1::Lists::AccountsController < Api::BaseController
|
|||
|
||||
def load_accounts
|
||||
if unlimited?
|
||||
@list.accounts.all
|
||||
@list.accounts.includes(:account_stat).all
|
||||
else
|
||||
@list.accounts.paginate_by_max_id(limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:max_id], params[:since_id])
|
||||
@list.accounts.includes(:account_stat).paginate_by_max_id(limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:max_id], params[:since_id])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
77
app/controllers/api/v1/scheduled_statuses_controller.rb
Normal file
77
app/controllers/api/v1/scheduled_statuses_controller.rb
Normal file
|
@ -0,0 +1,77 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::ScheduledStatusesController < Api::BaseController
|
||||
include Authorization
|
||||
|
||||
before_action -> { doorkeeper_authorize! :read, :'read:statuses' }, except: [:update, :destroy]
|
||||
before_action -> { doorkeeper_authorize! :write, :'write:statuses' }, only: [:update, :destroy]
|
||||
|
||||
before_action :set_statuses, only: :index
|
||||
before_action :set_status, except: :index
|
||||
|
||||
after_action :insert_pagination_headers, only: :index
|
||||
|
||||
def index
|
||||
render json: @statuses, each_serializer: REST::ScheduledStatusSerializer
|
||||
end
|
||||
|
||||
def show
|
||||
render json: @status, serializer: REST::ScheduledStatusSerializer
|
||||
end
|
||||
|
||||
def update
|
||||
@status.update!(scheduled_status_params)
|
||||
render json: @status, serializer: REST::ScheduledStatusSerializer
|
||||
end
|
||||
|
||||
def destroy
|
||||
@status.destroy!
|
||||
render_empty
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_statuses
|
||||
@statuses = current_account.scheduled_statuses.paginate_by_id(limit_param(DEFAULT_STATUSES_LIMIT), params_slice(:max_id, :since_id, :min_id))
|
||||
end
|
||||
|
||||
def set_status
|
||||
@status = current_account.scheduled_statuses.find(params[:id])
|
||||
end
|
||||
|
||||
def scheduled_status_params
|
||||
params.permit(:scheduled_at)
|
||||
end
|
||||
|
||||
def pagination_params(core_params)
|
||||
params.slice(:limit).permit(:limit).merge(core_params)
|
||||
end
|
||||
|
||||
def insert_pagination_headers
|
||||
set_pagination_headers(next_path, prev_path)
|
||||
end
|
||||
|
||||
def next_path
|
||||
if records_continue?
|
||||
api_v1_scheduled_statuses_url pagination_params(max_id: pagination_max_id)
|
||||
end
|
||||
end
|
||||
|
||||
def prev_path
|
||||
unless @statuses.empty?
|
||||
api_v1_scheduled_statuses_url pagination_params(min_id: pagination_since_id)
|
||||
end
|
||||
end
|
||||
|
||||
def records_continue?
|
||||
@statuses.size == limit_param(DEFAULT_STATUSES_LIMIT)
|
||||
end
|
||||
|
||||
def pagination_max_id
|
||||
@statuses.last.id
|
||||
end
|
||||
|
||||
def pagination_since_id
|
||||
@statuses.first.id
|
||||
end
|
||||
end
|
|
@ -22,7 +22,7 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController
|
|||
|
||||
def default_accounts
|
||||
Account
|
||||
.includes(:favourites)
|
||||
.includes(:favourites, :account_stat)
|
||||
.references(:favourites)
|
||||
.where(favourites: { status_id: @status.id })
|
||||
end
|
||||
|
|
|
@ -21,11 +21,11 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController
|
|||
end
|
||||
|
||||
def default_accounts
|
||||
Account.includes(:statuses).references(:statuses)
|
||||
Account.includes(:statuses, :account_stat).references(:statuses)
|
||||
end
|
||||
|
||||
def paginated_statuses
|
||||
Status.where(reblog_of_id: @status.id).paginate_by_max_id(
|
||||
Status.where(reblog_of_id: @status.id).where(visibility: [:public, :unlisted]).paginate_by_max_id(
|
||||
limit_param(DEFAULT_ACCOUNTS_LIMIT),
|
||||
params[:max_id],
|
||||
params[:since_id]
|
||||
|
|
|
@ -45,16 +45,17 @@ class Api::V1::StatusesController < Api::BaseController
|
|||
|
||||
def create
|
||||
@status = PostStatusService.new.call(current_user.account,
|
||||
status_params[:status],
|
||||
status_params[:in_reply_to_id].blank? ? nil : Status.find(status_params[:in_reply_to_id]),
|
||||
text: status_params[:status],
|
||||
thread: status_params[:in_reply_to_id].blank? ? nil : Status.find(status_params[:in_reply_to_id]),
|
||||
media_ids: status_params[:media_ids],
|
||||
sensitive: status_params[:sensitive],
|
||||
spoiler_text: status_params[:spoiler_text],
|
||||
visibility: status_params[:visibility],
|
||||
scheduled_at: status_params[:scheduled_at],
|
||||
application: doorkeeper_token.application,
|
||||
idempotency: request.headers['Idempotency-Key'])
|
||||
|
||||
render json: @status, serializer: REST::StatusSerializer
|
||||
render json: @status, serializer: @status.is_a?(ScheduledStatus) ? REST::ScheduledStatusSerializer : REST::StatusSerializer
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
@ -77,7 +78,7 @@ class Api::V1::StatusesController < Api::BaseController
|
|||
end
|
||||
|
||||
def status_params
|
||||
params.permit(:status, :in_reply_to_id, :sensitive, :spoiler_text, :visibility, media_ids: [])
|
||||
params.permit(:status, :in_reply_to_id, :sensitive, :spoiler_text, :visibility, :scheduled_at, media_ids: [])
|
||||
end
|
||||
|
||||
def pagination_params(core_params)
|
||||
|
|
|
@ -45,7 +45,7 @@ class Api::V1::Timelines::TagController < Api::BaseController
|
|||
end
|
||||
|
||||
def tag_timeline_statuses
|
||||
Status.as_tag_timeline(@tag, current_account, truthy_param?(:local))
|
||||
HashtagQueryService.new.call(@tag, params.slice(:any, :all, :none), current_account, truthy_param?(:local))
|
||||
end
|
||||
|
||||
def insert_pagination_headers
|
||||
|
|
|
@ -10,6 +10,7 @@ class Api::Web::EmbedsController < Api::Web::BaseController
|
|||
render json: status, serializer: OEmbedSerializer, width: 400
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
oembed = FetchOEmbedService.new.call(params[:url])
|
||||
oembed[:html] = Formatter.instance.sanitize(oembed[:html], Sanitize::Config::MASTODON_OEMBED) if oembed[:html].present?
|
||||
|
||||
if oembed
|
||||
render json: oembed
|
||||
|
|
|
@ -6,9 +6,9 @@ class Auth::ConfirmationsController < Devise::ConfirmationsController
|
|||
before_action :set_body_classes
|
||||
before_action :set_user, only: [:finish_signup]
|
||||
|
||||
# GET/PATCH /users/:id/finish_signup
|
||||
def finish_signup
|
||||
return unless request.patch? && params[:user]
|
||||
|
||||
if @user.update(user_params)
|
||||
@user.skip_reconfirmation!
|
||||
bypass_sign_in(@user)
|
||||
|
@ -31,4 +31,12 @@ class Auth::ConfirmationsController < Devise::ConfirmationsController
|
|||
def user_params
|
||||
params.require(:user).permit(:email)
|
||||
end
|
||||
|
||||
def after_confirmation_path_for(_resource_name, user)
|
||||
if user.created_by_application && truthy_param?(:redirect_to_app)
|
||||
user.created_by_application.redirect_uri
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -26,6 +26,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
|
|||
|
||||
resource.locale = I18n.locale
|
||||
resource.invite_code = params[:invite_code] if resource.invite_code.blank?
|
||||
resource.agreement = true
|
||||
|
||||
resource.build_account if resource.account.nil?
|
||||
end
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module RemoteAccountControllerConcern
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
layout 'public'
|
||||
before_action :set_account
|
||||
before_action :check_account_suspension
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_account
|
||||
@account = Account.find_remote!(params[:acct])
|
||||
end
|
||||
|
||||
def check_account_suspension
|
||||
gone if @account.suspended?
|
||||
end
|
||||
end
|
|
@ -43,7 +43,13 @@ module SignatureVerification
|
|||
return
|
||||
end
|
||||
|
||||
account = account_from_key_id(signature_params['keyId'])
|
||||
account_stoplight = Stoplight("source:#{request.ip}") { account_from_key_id(signature_params['keyId']) }
|
||||
.with_fallback { nil }
|
||||
.with_threshold(1)
|
||||
.with_cool_off_time(5.minutes.seconds)
|
||||
.with_error_handler { |error, handle| error.is_a?(HTTP::Error) ? handle.call(error) : raise(error) }
|
||||
|
||||
account = account_stoplight.run
|
||||
|
||||
if account.nil?
|
||||
@signature_verification_failure_reason = "Public key not found for key #{signature_params['keyId']}"
|
||||
|
@ -54,24 +60,27 @@ module SignatureVerification
|
|||
signature = Base64.decode64(signature_params['signature'])
|
||||
compare_signed_string = build_signed_string(signature_params['headers'])
|
||||
|
||||
if account.keypair.public_key.verify(OpenSSL::Digest::SHA256.new, signature, compare_signed_string)
|
||||
@signed_request_account = account
|
||||
@signed_request_account
|
||||
elsif account.possibly_stale?
|
||||
account = account.refresh!
|
||||
return account unless verify_signature(account, signature, compare_signed_string).nil?
|
||||
|
||||
account_stoplight = Stoplight("source:#{request.ip}") { account.possibly_stale? ? account.refresh! : account_refresh_key(account) }
|
||||
.with_fallback { nil }
|
||||
.with_threshold(1)
|
||||
.with_cool_off_time(5.minutes.seconds)
|
||||
.with_error_handler { |error, handle| error.is_a?(HTTP::Error) ? handle.call(error) : raise(error) }
|
||||
|
||||
account = account_stoplight.run
|
||||
|
||||
if account.nil?
|
||||
@signature_verification_failure_reason = "Public key not found for key #{signature_params['keyId']}"
|
||||
@signed_request_account = nil
|
||||
return
|
||||
end
|
||||
|
||||
return account unless verify_signature(account, signature, compare_signed_string).nil?
|
||||
|
||||
if account.keypair.public_key.verify(OpenSSL::Digest::SHA256.new, signature, compare_signed_string)
|
||||
@signed_request_account = account
|
||||
@signed_request_account
|
||||
else
|
||||
@signature_verification_failure_reason = "Verification failed for #{account.username}@#{account.domain} #{account.uri}"
|
||||
@signed_request_account = nil
|
||||
end
|
||||
else
|
||||
@signature_verification_failure_reason = "Verification failed for #{account.username}@#{account.domain} #{account.uri}"
|
||||
@signed_request_account = nil
|
||||
end
|
||||
end
|
||||
|
||||
def request_body
|
||||
@request_body ||= request.raw_post
|
||||
|
@ -79,6 +88,15 @@ module SignatureVerification
|
|||
|
||||
private
|
||||
|
||||
def verify_signature(account, signature, compare_signed_string)
|
||||
if account.keypair.public_key.verify(OpenSSL::Digest::SHA256.new, signature, compare_signed_string)
|
||||
@signed_request_account = account
|
||||
@signed_request_account
|
||||
end
|
||||
rescue OpenSSL::PKey::RSAError
|
||||
nil
|
||||
end
|
||||
|
||||
def build_signed_string(signed_headers)
|
||||
signed_headers = 'date' if signed_headers.blank?
|
||||
|
||||
|
@ -125,4 +143,9 @@ module SignatureVerification
|
|||
account
|
||||
end
|
||||
end
|
||||
|
||||
def account_refresh_key(account)
|
||||
return if account.local? || !account.activitypub?
|
||||
ActivityPub::FetchRemoteAccountService.new.call(account.uri, only_key: true)
|
||||
end
|
||||
end
|
||||
|
|
43
app/controllers/directories_controller.rb
Normal file
43
app/controllers/directories_controller.rb
Normal file
|
@ -0,0 +1,43 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class DirectoriesController < ApplicationController
|
||||
layout 'public'
|
||||
|
||||
before_action :check_enabled
|
||||
before_action :set_instance_presenter
|
||||
before_action :set_tag, only: :show
|
||||
before_action :set_tags
|
||||
before_action :set_accounts
|
||||
|
||||
def index
|
||||
render :index
|
||||
end
|
||||
|
||||
def show
|
||||
render :index
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_enabled
|
||||
return not_found unless Setting.profile_directory
|
||||
end
|
||||
|
||||
def set_tag
|
||||
@tag = Tag.discoverable.find_by!(name: params[:id].downcase)
|
||||
end
|
||||
|
||||
def set_tags
|
||||
@tags = Tag.discoverable.limit(30).reject { |tag| tag.cached_sample_accounts.empty? }
|
||||
end
|
||||
|
||||
def set_accounts
|
||||
@accounts = Account.discoverable.page(params[:page]).per(40).tap do |query|
|
||||
query.merge!(Account.tagged_with(@tag.id)) if @tag
|
||||
end
|
||||
end
|
||||
|
||||
def set_instance_presenter
|
||||
@instance_presenter = InstancePresenter.new
|
||||
end
|
||||
end
|
|
@ -6,12 +6,17 @@ class MediaController < ApplicationController
|
|||
before_action :set_media_attachment
|
||||
before_action :verify_permitted_status!
|
||||
|
||||
content_security_policy only: :player do |p|
|
||||
p.frame_ancestors(false)
|
||||
end
|
||||
|
||||
def show
|
||||
redirect_to @media_attachment.file.url(:original)
|
||||
end
|
||||
|
||||
def player
|
||||
@body_classes = 'player'
|
||||
response.headers['X-Frame-Options'] = 'ALLOWALL'
|
||||
raise ActiveRecord::RecordNotFound unless @media_attachment.video? || @media_attachment.gifv?
|
||||
end
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ class RemoteInteractionController < ApplicationController
|
|||
|
||||
layout 'modal'
|
||||
|
||||
before_action :set_interaction_type
|
||||
before_action :set_status
|
||||
before_action :set_body_classes
|
||||
|
||||
|
@ -45,4 +46,8 @@ class RemoteInteractionController < ApplicationController
|
|||
@body_classes = 'modal-layout'
|
||||
@hide_header = true
|
||||
end
|
||||
|
||||
def set_interaction_type
|
||||
@interaction_type = %w(reply reblog favourite).include?(params[:type]) ? params[:type] : 'reply'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Settings::ApplicationsController < ApplicationController
|
||||
class Settings::ApplicationsController < Settings::BaseController
|
||||
layout 'admin'
|
||||
|
||||
before_action :authenticate_user!
|
||||
before_action :set_application, only: [:show, :update, :destroy, :regenerate]
|
||||
before_action :prepare_scopes, only: [:create, :update]
|
||||
before_action :set_body_classes
|
||||
|
||||
def index
|
||||
@applications = current_user.applications.order(id: :desc).page(params[:page])
|
||||
|
@ -70,8 +69,4 @@ class Settings::ApplicationsController < ApplicationController
|
|||
scopes = params.fetch(:doorkeeper_application, {}).fetch(:scopes, nil)
|
||||
params[:doorkeeper_application][:scopes] = scopes.join(' ') if scopes.is_a? Array
|
||||
end
|
||||
|
||||
def set_body_classes
|
||||
@body_classes = 'admin'
|
||||
end
|
||||
end
|
||||
|
|
11
app/controllers/settings/base_controller.rb
Normal file
11
app/controllers/settings/base_controller.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Settings::BaseController < ApplicationController
|
||||
before_action :set_body_classes
|
||||
|
||||
private
|
||||
|
||||
def set_body_classes
|
||||
@body_classes = 'admin'
|
||||
end
|
||||
end
|
|
@ -1,11 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Settings::DeletesController < ApplicationController
|
||||
class Settings::DeletesController < Settings::BaseController
|
||||
layout 'admin'
|
||||
|
||||
before_action :check_enabled_deletion
|
||||
before_action :authenticate_user!
|
||||
before_action :set_body_classes
|
||||
|
||||
def show
|
||||
@confirmation = Form::DeleteConfirmation.new
|
||||
|
@ -30,8 +29,4 @@ class Settings::DeletesController < ApplicationController
|
|||
def delete_params
|
||||
params.require(:form_delete_confirmation).permit(:password)
|
||||
end
|
||||
|
||||
def set_body_classes
|
||||
@body_classes = 'admin'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Settings
|
||||
module Exports
|
||||
class BlockedDomainsController < ApplicationController
|
||||
include ExportControllerConcern
|
||||
|
||||
def index
|
||||
send_export_file
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def export_data
|
||||
@export.to_blocked_domains_csv
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
19
app/controllers/settings/exports/lists_controller.rb
Normal file
19
app/controllers/settings/exports/lists_controller.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Settings
|
||||
module Exports
|
||||
class ListsController < ApplicationController
|
||||
include ExportControllerConcern
|
||||
|
||||
def index
|
||||
send_export_file
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def export_data
|
||||
@export.to_lists_csv
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,12 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Settings::ExportsController < ApplicationController
|
||||
class Settings::ExportsController < Settings::BaseController
|
||||
include Authorization
|
||||
|
||||
layout 'admin'
|
||||
|
||||
before_action :authenticate_user!
|
||||
before_action :set_body_classes
|
||||
|
||||
def show
|
||||
@export = Export.new(current_account)
|
||||
|
@ -21,10 +20,4 @@ class Settings::ExportsController < ApplicationController
|
|||
|
||||
redirect_to settings_export_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_body_classes
|
||||
@body_classes = 'admin'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Settings::FollowerDomainsController < ApplicationController
|
||||
class Settings::FollowerDomainsController < Settings::BaseController
|
||||
layout 'admin'
|
||||
|
||||
before_action :authenticate_user!
|
||||
before_action :set_body_classes
|
||||
|
||||
def show
|
||||
@account = current_account
|
||||
|
@ -26,8 +25,4 @@ class Settings::FollowerDomainsController < ApplicationController
|
|||
def bulk_params
|
||||
params.permit(select: [])
|
||||
end
|
||||
|
||||
def set_body_classes
|
||||
@body_classes = 'admin'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Settings::ImportsController < ApplicationController
|
||||
class Settings::ImportsController < Settings::BaseController
|
||||
layout 'admin'
|
||||
|
||||
before_action :authenticate_user!
|
||||
before_action :set_account
|
||||
before_action :set_body_classes
|
||||
|
||||
def show
|
||||
@import = Import.new
|
||||
|
@ -32,8 +31,4 @@ class Settings::ImportsController < ApplicationController
|
|||
def import_params
|
||||
params.require(:import).permit(:data, :type)
|
||||
end
|
||||
|
||||
def set_body_classes
|
||||
@body_classes = 'admin'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Settings::MigrationsController < ApplicationController
|
||||
class Settings::MigrationsController < Settings::BaseController
|
||||
layout 'admin'
|
||||
|
||||
before_action :authenticate_user!
|
||||
before_action :set_body_classes
|
||||
|
||||
def show
|
||||
@migration = Form::Migration.new(account: current_account.moved_to_account)
|
||||
|
@ -32,8 +31,4 @@ class Settings::MigrationsController < ApplicationController
|
|||
current_account.moved_to_account_id != @migration.account&.id &&
|
||||
current_account.id != @migration.account&.id
|
||||
end
|
||||
|
||||
def set_body_classes
|
||||
@body_classes = 'admin'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Settings::NotificationsController < ApplicationController
|
||||
class Settings::NotificationsController < Settings::BaseController
|
||||
layout 'admin'
|
||||
|
||||
before_action :authenticate_user!
|
||||
before_action :set_body_classes
|
||||
|
||||
def show; end
|
||||
|
||||
|
@ -30,8 +29,4 @@ class Settings::NotificationsController < ApplicationController
|
|||
interactions: %i(must_be_follower must_be_following must_be_following_dm)
|
||||
)
|
||||
end
|
||||
|
||||
def set_body_classes
|
||||
@body_classes = 'admin'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Settings::PreferencesController < ApplicationController
|
||||
class Settings::PreferencesController < Settings::BaseController
|
||||
layout 'admin'
|
||||
|
||||
before_action :authenticate_user!
|
||||
before_action :set_body_classes
|
||||
|
||||
def show; end
|
||||
|
||||
|
@ -48,12 +47,9 @@ class Settings::PreferencesController < ApplicationController
|
|||
:setting_noindex,
|
||||
:setting_theme,
|
||||
:setting_hide_network,
|
||||
:setting_aggregate_reblogs,
|
||||
notification_emails: %i(follow follow_request reblog favourite mention digest report),
|
||||
interactions: %i(must_be_follower must_be_following)
|
||||
)
|
||||
end
|
||||
|
||||
def set_body_classes
|
||||
@body_classes = 'admin'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Settings::ProfilesController < ApplicationController
|
||||
class Settings::ProfilesController < Settings::BaseController
|
||||
include ObfuscateFilename
|
||||
|
||||
layout 'admin'
|
||||
|
||||
before_action :authenticate_user!
|
||||
before_action :set_account
|
||||
before_action :set_body_classes
|
||||
|
||||
obfuscate_filename [:account, :avatar]
|
||||
obfuscate_filename [:account, :header]
|
||||
|
@ -29,14 +28,10 @@ class Settings::ProfilesController < ApplicationController
|
|||
private
|
||||
|
||||
def account_params
|
||||
params.require(:account).permit(:display_name, :note, :avatar, :header, :locked, :bot, fields_attributes: [:name, :value])
|
||||
params.require(:account).permit(:display_name, :note, :avatar, :header, :locked, :bot, :discoverable, fields_attributes: [:name, :value])
|
||||
end
|
||||
|
||||
def set_account
|
||||
@account = current_user.account
|
||||
end
|
||||
|
||||
def set_body_classes
|
||||
@body_classes = 'admin'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Settings::SessionsController < ApplicationController
|
||||
class Settings::SessionsController < Settings::BaseController
|
||||
before_action :set_session, only: :destroy
|
||||
before_action :set_body_classes
|
||||
|
||||
def destroy
|
||||
@session.destroy!
|
||||
|
@ -15,8 +14,4 @@ class Settings::SessionsController < ApplicationController
|
|||
def set_session
|
||||
@session = current_user.session_activations.find(params[:id])
|
||||
end
|
||||
|
||||
def set_body_classes
|
||||
@body_classes = 'admin'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,12 +2,11 @@
|
|||
|
||||
module Settings
|
||||
module TwoFactorAuthentication
|
||||
class ConfirmationsController < ApplicationController
|
||||
class ConfirmationsController < BaseController
|
||||
layout 'admin'
|
||||
|
||||
before_action :authenticate_user!
|
||||
before_action :ensure_otp_secret
|
||||
before_action :set_body_classes
|
||||
|
||||
def new
|
||||
prepare_two_factor_form
|
||||
|
@ -44,10 +43,6 @@ module Settings
|
|||
def ensure_otp_secret
|
||||
redirect_to settings_two_factor_authentication_path unless current_user.otp_secret
|
||||
end
|
||||
|
||||
def set_body_classes
|
||||
@body_classes = 'admin'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,11 +2,10 @@
|
|||
|
||||
module Settings
|
||||
module TwoFactorAuthentication
|
||||
class RecoveryCodesController < ApplicationController
|
||||
class RecoveryCodesController < BaseController
|
||||
layout 'admin'
|
||||
|
||||
before_action :authenticate_user!
|
||||
before_action :set_body_classes
|
||||
|
||||
def create
|
||||
@recovery_codes = current_user.generate_otp_backup_codes!
|
||||
|
@ -14,12 +13,6 @@ module Settings
|
|||
flash[:notice] = I18n.t('two_factor_authentication.recovery_codes_regenerated')
|
||||
render :index
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_body_classes
|
||||
@body_classes = 'admin'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Settings
|
||||
class TwoFactorAuthenticationsController < ApplicationController
|
||||
class TwoFactorAuthenticationsController < BaseController
|
||||
layout 'admin'
|
||||
|
||||
before_action :authenticate_user!
|
||||
before_action :verify_otp_required, only: [:create]
|
||||
before_action :set_body_classes
|
||||
|
||||
def show
|
||||
@confirmation = Form::TwoFactorConfirmation.new
|
||||
|
@ -44,9 +43,5 @@ module Settings
|
|||
current_user.validate_and_consume_otp!(confirmation_params[:code]) ||
|
||||
current_user.invalidate_otp_backup_code!(confirmation_params[:code])
|
||||
end
|
||||
|
||||
def set_body_classes
|
||||
@body_classes = 'admin'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -65,12 +65,13 @@ class StatusesController < ApplicationController
|
|||
|
||||
private
|
||||
|
||||
def create_descendant_thread(depth, statuses)
|
||||
def create_descendant_thread(starting_depth, statuses)
|
||||
depth = starting_depth + statuses.size
|
||||
if depth < DESCENDANTS_DEPTH_LIMIT
|
||||
{ statuses: statuses }
|
||||
{ statuses: statuses, starting_depth: starting_depth }
|
||||
else
|
||||
next_status = statuses.pop
|
||||
{ statuses: statuses, next_status: next_status }
|
||||
{ statuses: statuses, starting_depth: starting_depth, next_status: next_status }
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -102,15 +103,18 @@ class StatusesController < ApplicationController
|
|||
|
||||
if descendants.present?
|
||||
statuses = [descendants.first]
|
||||
depth = 1
|
||||
starting_depth = 0
|
||||
|
||||
descendants.drop(1).each_with_index do |descendant, index|
|
||||
if descendants[index].id == descendant.in_reply_to_id
|
||||
depth += 1
|
||||
statuses << descendant
|
||||
else
|
||||
@descendant_threads << create_descendant_thread(depth, statuses)
|
||||
@descendant_threads << create_descendant_thread(starting_depth, statuses)
|
||||
|
||||
# The thread is broken, assume it's a reply to the root status
|
||||
starting_depth = 0
|
||||
|
||||
# ... unless we can find its ancestor in one of the already-processed threads
|
||||
@descendant_threads.reverse_each do |descendant_thread|
|
||||
statuses = descendant_thread[:statuses]
|
||||
|
||||
|
@ -119,18 +123,16 @@ class StatusesController < ApplicationController
|
|||
end
|
||||
|
||||
if index.present?
|
||||
depth += index - statuses.size
|
||||
starting_depth = descendant_thread[:starting_depth] + index + 1
|
||||
break
|
||||
end
|
||||
|
||||
depth -= statuses.size
|
||||
end
|
||||
|
||||
statuses = [descendant]
|
||||
end
|
||||
end
|
||||
|
||||
@descendant_threads << create_descendant_thread(depth, statuses)
|
||||
@descendant_threads << create_descendant_thread(starting_depth, statuses)
|
||||
end
|
||||
|
||||
@max_descendant_thread_id = @descendant_threads.pop[:statuses].first.id if descendants.size >= DESCENDANTS_LIMIT
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
class TagsController < ApplicationController
|
||||
PAGE_SIZE = 20
|
||||
|
||||
layout 'public'
|
||||
|
||||
before_action :set_body_classes
|
||||
before_action :set_instance_presenter
|
||||
|
||||
|
@ -16,14 +18,15 @@ class TagsController < ApplicationController
|
|||
end
|
||||
|
||||
format.rss do
|
||||
@statuses = Status.as_tag_timeline(@tag).limit(PAGE_SIZE)
|
||||
@statuses = HashtagQueryService.new.call(@tag, params.slice(:any, :all, :none)).limit(PAGE_SIZE)
|
||||
@statuses = cache_collection(@statuses, Status)
|
||||
|
||||
render xml: RSS::TagSerializer.render(@tag, @statuses)
|
||||
end
|
||||
|
||||
format.json do
|
||||
@statuses = Status.as_tag_timeline(@tag, current_account, params[:local]).paginate_by_max_id(PAGE_SIZE, params[:max_id])
|
||||
@statuses = HashtagQueryService.new.call(@tag, params.slice(:any, :all, :none), current_account, params[:local])
|
||||
.paginate_by_max_id(PAGE_SIZE, params[:max_id])
|
||||
@statuses = cache_collection(@statuses, Status)
|
||||
|
||||
render json: collection_presenter,
|
||||
|
@ -46,7 +49,7 @@ class TagsController < ApplicationController
|
|||
|
||||
def collection_presenter
|
||||
ActivityPub::CollectionPresenter.new(
|
||||
id: tag_url(@tag),
|
||||
id: tag_url(@tag, params.slice(:any, :all, :none)),
|
||||
type: :ordered,
|
||||
size: @tag.statuses.count,
|
||||
items: @statuses.map { |s| ActivityPub::TagManager.instance.uri_for(s) }
|
||||
|
|
|
@ -24,7 +24,7 @@ module Admin::AccountModerationNotesHelper
|
|||
|
||||
def name_tag_classes(account, inline = false)
|
||||
classes = [inline ? 'inline-name-tag' : 'name-tag']
|
||||
classes << 'suspended' if account.suspended?
|
||||
classes << 'suspended' if account.suspended? || (account.local? && account.user.nil?)
|
||||
classes.join(' ')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -23,6 +23,8 @@ module Admin::ActionLogsHelper
|
|||
link_to record.domain, "https://#{record.domain}"
|
||||
when 'Status'
|
||||
link_to record.account.acct, TagManager.instance.url_for(record)
|
||||
when 'AccountWarning'
|
||||
link_to record.target_account.acct, admin_account_path(record.target_account_id)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -34,6 +36,7 @@ module Admin::ActionLogsHelper
|
|||
link_to attributes['domain'], "https://#{attributes['domain']}"
|
||||
when 'Status'
|
||||
tmp_status = Status.new(attributes.except('reblogs_count', 'favourites_count'))
|
||||
|
||||
if tmp_status.account
|
||||
link_to tmp_status.account&.acct || "##{tmp_status.account_id}", admin_account_path(tmp_status.account_id)
|
||||
else
|
||||
|
@ -81,6 +84,8 @@ module Admin::ActionLogsHelper
|
|||
'envelope'
|
||||
when 'Status'
|
||||
'pencil'
|
||||
when 'AccountWarning'
|
||||
'warning'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -92,7 +97,7 @@ module Admin::ActionLogsHelper
|
|||
opposite_verbs?(log) ? 'negative' : 'positive'
|
||||
when :update, :reset_password, :disable_2fa, :memorialize, :change_email
|
||||
'neutral'
|
||||
when :demote, :silence, :disable, :suspend, :remove_avatar, :reopen
|
||||
when :demote, :silence, :disable, :suspend, :remove_avatar, :remove_header, :reopen
|
||||
'negative'
|
||||
when :destroy
|
||||
opposite_verbs?(log) ? 'positive' : 'negative'
|
||||
|
@ -104,6 +109,6 @@ module Admin::ActionLogsHelper
|
|||
private
|
||||
|
||||
def opposite_verbs?(log)
|
||||
%w(DomainBlock EmailDomainBlock).include?(log.target_type)
|
||||
%w(DomainBlock EmailDomainBlock AccountWarning).include?(log.target_type)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Admin::FilterHelper
|
||||
ACCOUNT_FILTERS = %i(local remote by_domain silenced suspended alphabetic username display_name email ip staff).freeze
|
||||
ACCOUNT_FILTERS = %i(local remote by_domain active silenced suspended username display_name email ip staff).freeze
|
||||
REPORT_FILTERS = %i(resolved account_id target_account_id).freeze
|
||||
INVITE_FILTER = %i(available expired).freeze
|
||||
CUSTOM_EMOJI_FILTERS = %i(local remote by_domain shortcode).freeze
|
||||
TAGS_FILTERS = %i(hidden).freeze
|
||||
INSTANCES_FILTERS = %i(limited).freeze
|
||||
|
||||
FILTERS = ACCOUNT_FILTERS + REPORT_FILTERS + INVITE_FILTER + CUSTOM_EMOJI_FILTERS
|
||||
FILTERS = ACCOUNT_FILTERS + REPORT_FILTERS + INVITE_FILTER + CUSTOM_EMOJI_FILTERS + TAGS_FILTERS + INSTANCES_FILTERS
|
||||
|
||||
def filter_link_to(text, link_to_params, link_class_params = link_to_params)
|
||||
new_url = filtered_url_for(link_to_params)
|
||||
|
|
|
@ -69,8 +69,12 @@ module ApplicationHelper
|
|||
tag(:meta, content: content, property: property)
|
||||
end
|
||||
|
||||
def react_component(name, props = {})
|
||||
def react_component(name, props = {}, &block)
|
||||
if block.nil?
|
||||
content_tag(:div, nil, data: { component: name.to_s.camelcase, props: Oj.dump(props) })
|
||||
else
|
||||
content_tag(:div, data: { component: name.to_s.camelcase, props: Oj.dump(props) }, &block)
|
||||
end
|
||||
end
|
||||
|
||||
def body_classes
|
||||
|
|
|
@ -23,7 +23,7 @@ module HomeHelper
|
|||
else
|
||||
link_to(path || TagManager.instance.url_for(account), class: 'account__display-name') do
|
||||
content_tag(:div, class: 'account__avatar-wrapper') do
|
||||
content_tag(:div, '', class: 'account__avatar', style: "width: #{size}px; height: #{size}px; background-size: #{size}px #{size}px; background-image: url(#{account.avatar.url})")
|
||||
content_tag(:div, '', class: 'account__avatar', style: "width: #{size}px; height: #{size}px; background-size: #{size}px #{size}px; background-image: url(#{full_asset_url(current_account&.user&.setting_auto_play_gif ? account.avatar_original_url : account.avatar_static_url)})")
|
||||
end +
|
||||
content_tag(:span, class: 'display-name') do
|
||||
content_tag(:bdi) do
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module MailerHelper
|
||||
end
|
|
@ -30,6 +30,7 @@ module SettingsHelper
|
|||
ja: '日本語',
|
||||
ka: 'ქართული',
|
||||
ko: '한국어',
|
||||
ml: 'മലയാളം',
|
||||
nl: 'Nederlands',
|
||||
no: 'Norsk',
|
||||
oc: 'Occitan',
|
||||
|
|
|
@ -34,12 +34,14 @@ module StreamEntriesHelper
|
|||
end
|
||||
end
|
||||
|
||||
def account_badge(account)
|
||||
def account_badge(account, all: false)
|
||||
if account.bot?
|
||||
content_tag(:div, content_tag(:div, t('accounts.roles.bot'), class: 'account-role bot'), class: 'roles')
|
||||
elsif Setting.show_staff_badge && account.user_staff?
|
||||
elsif (Setting.show_staff_badge && account.user_staff?) || all
|
||||
content_tag(:div, class: 'roles') do
|
||||
if account.user_admin?
|
||||
if all && !account.user_staff?
|
||||
content_tag(:div, t('admin.accounts.roles.user'), class: 'account-role')
|
||||
elsif account.user_admin?
|
||||
content_tag(:div, t('accounts.roles.admin'), class: 'account-role admin')
|
||||
elsif account.user_moderator?
|
||||
content_tag(:div, t('accounts.roles.moderator'), class: 'account-role moderator')
|
||||
|
|
4
app/javascript/images/icon_flag.svg
Normal file
4
app/javascript/images/icon_flag.svg
Normal file
|
@ -0,0 +1,4 @@
|
|||
<svg fill="#FFFFFF" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||
<path d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M14.4 6L14 4H5v17h2v-7h5.6l.4 2h7V6z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 197 B |
BIN
app/javascript/images/mailer/icon_warning.png
Normal file
BIN
app/javascript/images/mailer/icon_warning.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 371 B |
1
app/javascript/images/screen_federation.svg
Normal file
1
app/javascript/images/screen_federation.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 37 KiB |
1
app/javascript/images/screen_hello.svg
Normal file
1
app/javascript/images/screen_hello.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 8.8 KiB |
1
app/javascript/images/screen_interactions.svg
Normal file
1
app/javascript/images/screen_interactions.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 27 KiB |
|
@ -130,6 +130,12 @@ export function submitCompose(routerHistory) {
|
|||
'Idempotency-Key': getState().getIn(['compose', 'idempotencyKey']),
|
||||
},
|
||||
}).then(function (response) {
|
||||
if (response.data.visibility === 'direct' && getState().getIn(['conversations', 'mounted']) <= 0 && routerHistory) {
|
||||
routerHistory.push('/timelines/direct');
|
||||
} else if (routerHistory && routerHistory.location.pathname === '/statuses/new' && window.history.state) {
|
||||
routerHistory.goBack();
|
||||
}
|
||||
|
||||
dispatch(insertIntoTagHistory(response.data.tags, status));
|
||||
dispatch(submitComposeSuccess({ ...response.data }));
|
||||
|
||||
|
@ -142,9 +148,7 @@ export function submitCompose(routerHistory) {
|
|||
}
|
||||
};
|
||||
|
||||
if (response.data.visibility === 'direct' && getState().getIn(['conversations', 'mounted']) <= 0 && routerHistory) {
|
||||
routerHistory.push('/timelines/direct');
|
||||
} else if (response.data.visibility !== 'direct') {
|
||||
if (response.data.visibility !== 'direct') {
|
||||
insertIfOnline('home');
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ export const expandConversations = ({ maxId } = {}) => (dispatch, getState) => {
|
|||
const params = { max_id: maxId };
|
||||
|
||||
if (!maxId) {
|
||||
params.since_id = getState().getIn(['conversations', 0, 'last_status']);
|
||||
params.since_id = getState().getIn(['conversations', 'items', 0, 'last_status']);
|
||||
}
|
||||
|
||||
api(getState).get('/api/v1/conversations', { params })
|
||||
|
|
|
@ -19,6 +19,7 @@ export function fetchCustomEmojis() {
|
|||
export function fetchCustomEmojisRequest() {
|
||||
return {
|
||||
type: CUSTOM_EMOJIS_FETCH_REQUEST,
|
||||
skipLoading: true,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -26,6 +27,7 @@ export function fetchCustomEmojisSuccess(custom_emojis) {
|
|||
return {
|
||||
type: CUSTOM_EMOJIS_FETCH_SUCCESS,
|
||||
custom_emojis,
|
||||
skipLoading: true,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -33,5 +35,6 @@ export function fetchCustomEmojisFail(error) {
|
|||
return {
|
||||
type: CUSTOM_EMOJIS_FETCH_FAIL,
|
||||
error,
|
||||
skipLoading: true,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -30,6 +30,7 @@ export function fetchFavouritedStatuses() {
|
|||
export function fetchFavouritedStatusesRequest() {
|
||||
return {
|
||||
type: FAVOURITED_STATUSES_FETCH_REQUEST,
|
||||
skipLoading: true,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -38,6 +39,7 @@ export function fetchFavouritedStatusesSuccess(statuses, next) {
|
|||
type: FAVOURITED_STATUSES_FETCH_SUCCESS,
|
||||
statuses,
|
||||
next,
|
||||
skipLoading: true,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -45,6 +47,7 @@ export function fetchFavouritedStatusesFail(error) {
|
|||
return {
|
||||
type: FAVOURITED_STATUSES_FETCH_FAIL,
|
||||
error,
|
||||
skipLoading: true,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -42,6 +42,13 @@ export const LIST_EDITOR_REMOVE_REQUEST = 'LIST_EDITOR_REMOVE_REQUEST';
|
|||
export const LIST_EDITOR_REMOVE_SUCCESS = 'LIST_EDITOR_REMOVE_SUCCESS';
|
||||
export const LIST_EDITOR_REMOVE_FAIL = 'LIST_EDITOR_REMOVE_FAIL';
|
||||
|
||||
export const LIST_ADDER_RESET = 'LIST_ADDER_RESET';
|
||||
export const LIST_ADDER_SETUP = 'LIST_ADDER_SETUP';
|
||||
|
||||
export const LIST_ADDER_LISTS_FETCH_REQUEST = 'LIST_ADDER_LISTS_FETCH_REQUEST';
|
||||
export const LIST_ADDER_LISTS_FETCH_SUCCESS = 'LIST_ADDER_LISTS_FETCH_SUCCESS';
|
||||
export const LIST_ADDER_LISTS_FETCH_FAIL = 'LIST_ADDER_LISTS_FETCH_FAIL';
|
||||
|
||||
export const fetchList = id => (dispatch, getState) => {
|
||||
if (getState().getIn(['lists', id])) {
|
||||
return;
|
||||
|
@ -316,3 +323,50 @@ export const removeFromListFail = (listId, accountId, error) => ({
|
|||
accountId,
|
||||
error,
|
||||
});
|
||||
|
||||
export const resetListAdder = () => ({
|
||||
type: LIST_ADDER_RESET,
|
||||
});
|
||||
|
||||
export const setupListAdder = accountId => (dispatch, getState) => {
|
||||
dispatch({
|
||||
type: LIST_ADDER_SETUP,
|
||||
account: getState().getIn(['accounts', accountId]),
|
||||
});
|
||||
dispatch(fetchLists());
|
||||
dispatch(fetchAccountLists(accountId));
|
||||
};
|
||||
|
||||
export const fetchAccountLists = accountId => (dispatch, getState) => {
|
||||
dispatch(fetchAccountListsRequest(accountId));
|
||||
|
||||
api(getState).get(`/api/v1/accounts/${accountId}/lists`)
|
||||
.then(({ data }) => dispatch(fetchAccountListsSuccess(accountId, data)))
|
||||
.catch(err => dispatch(fetchAccountListsFail(accountId, err)));
|
||||
};
|
||||
|
||||
export const fetchAccountListsRequest = id => ({
|
||||
type:LIST_ADDER_LISTS_FETCH_REQUEST,
|
||||
id,
|
||||
});
|
||||
|
||||
export const fetchAccountListsSuccess = (id, lists) => ({
|
||||
type: LIST_ADDER_LISTS_FETCH_SUCCESS,
|
||||
id,
|
||||
lists,
|
||||
});
|
||||
|
||||
export const fetchAccountListsFail = (id, err) => ({
|
||||
type: LIST_ADDER_LISTS_FETCH_FAIL,
|
||||
id,
|
||||
err,
|
||||
});
|
||||
|
||||
export const addToListAdder = listId => (dispatch, getState) => {
|
||||
dispatch(addToList(listId, getState().getIn(['listAdder', 'accountId'])));
|
||||
};
|
||||
|
||||
export const removeFromListAdder = listId => (dispatch, getState) => {
|
||||
dispatch(removeFromList(listId, getState().getIn(['listAdder', 'accountId'])));
|
||||
};
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
importFetchedStatuses,
|
||||
} from './importer';
|
||||
import { defineMessages } from 'react-intl';
|
||||
import { List as ImmutableList } from 'immutable';
|
||||
import { unescapeHTML } from '../utils/html';
|
||||
import { getFilters, regexFromFilters } from '../selectors';
|
||||
|
||||
|
@ -18,6 +19,8 @@ export const NOTIFICATIONS_EXPAND_REQUEST = 'NOTIFICATIONS_EXPAND_REQUEST';
|
|||
export const NOTIFICATIONS_EXPAND_SUCCESS = 'NOTIFICATIONS_EXPAND_SUCCESS';
|
||||
export const NOTIFICATIONS_EXPAND_FAIL = 'NOTIFICATIONS_EXPAND_FAIL';
|
||||
|
||||
export const NOTIFICATIONS_FILTER_SET = 'NOTIFICATIONS_FILTER_SET';
|
||||
|
||||
export const NOTIFICATIONS_CLEAR = 'NOTIFICATIONS_CLEAR';
|
||||
export const NOTIFICATIONS_SCROLL_TOP = 'NOTIFICATIONS_SCROLL_TOP';
|
||||
|
||||
|
@ -88,11 +91,18 @@ export function updateNotifications(notification, intlMessages, intlLocale) {
|
|||
|
||||
const excludeTypesFromSettings = state => state.getIn(['settings', 'notifications', 'shows']).filter(enabled => !enabled).keySeq().toJS();
|
||||
|
||||
const excludeTypesFromFilter = filter => {
|
||||
const allTypes = ImmutableList(['follow', 'favourite', 'reblog', 'mention']);
|
||||
return allTypes.filterNot(item => item === filter).toJS();
|
||||
};
|
||||
|
||||
const noOp = () => {};
|
||||
|
||||
export function expandNotifications({ maxId } = {}, done = noOp) {
|
||||
return (dispatch, getState) => {
|
||||
const activeFilter = getState().getIn(['settings', 'notifications', 'quickFilter', 'active']);
|
||||
const notifications = getState().get('notifications');
|
||||
const isLoadingMore = !!maxId;
|
||||
|
||||
if (notifications.get('isLoading')) {
|
||||
done();
|
||||
|
@ -101,14 +111,16 @@ export function expandNotifications({ maxId } = {}, done = noOp) {
|
|||
|
||||
const params = {
|
||||
max_id: maxId,
|
||||
exclude_types: excludeTypesFromSettings(getState()),
|
||||
exclude_types: activeFilter === 'all'
|
||||
? excludeTypesFromSettings(getState())
|
||||
: excludeTypesFromFilter(activeFilter),
|
||||
};
|
||||
|
||||
if (!maxId && notifications.get('items').size > 0) {
|
||||
params.since_id = notifications.getIn(['items', 0]);
|
||||
params.since_id = notifications.getIn(['items', 0, 'id']);
|
||||
}
|
||||
|
||||
dispatch(expandNotificationsRequest());
|
||||
dispatch(expandNotificationsRequest(isLoadingMore));
|
||||
|
||||
api(getState).get('/api/v1/notifications', { params }).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
|
@ -116,34 +128,37 @@ export function expandNotifications({ maxId } = {}, done = noOp) {
|
|||
dispatch(importFetchedAccounts(response.data.map(item => item.account)));
|
||||
dispatch(importFetchedStatuses(response.data.map(item => item.status).filter(status => !!status)));
|
||||
|
||||
dispatch(expandNotificationsSuccess(response.data, next ? next.uri : null));
|
||||
dispatch(expandNotificationsSuccess(response.data, next ? next.uri : null, isLoadingMore));
|
||||
fetchRelatedRelationships(dispatch, response.data);
|
||||
done();
|
||||
}).catch(error => {
|
||||
dispatch(expandNotificationsFail(error));
|
||||
dispatch(expandNotificationsFail(error, isLoadingMore));
|
||||
done();
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export function expandNotificationsRequest() {
|
||||
export function expandNotificationsRequest(isLoadingMore) {
|
||||
return {
|
||||
type: NOTIFICATIONS_EXPAND_REQUEST,
|
||||
skipLoading: !isLoadingMore,
|
||||
};
|
||||
};
|
||||
|
||||
export function expandNotificationsSuccess(notifications, next) {
|
||||
export function expandNotificationsSuccess(notifications, next, isLoadingMore) {
|
||||
return {
|
||||
type: NOTIFICATIONS_EXPAND_SUCCESS,
|
||||
notifications,
|
||||
next,
|
||||
skipLoading: !isLoadingMore,
|
||||
};
|
||||
};
|
||||
|
||||
export function expandNotificationsFail(error) {
|
||||
export function expandNotificationsFail(error, isLoadingMore) {
|
||||
return {
|
||||
type: NOTIFICATIONS_EXPAND_FAIL,
|
||||
error,
|
||||
skipLoading: !isLoadingMore,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -163,3 +178,14 @@ export function scrollTopNotifications(top) {
|
|||
top,
|
||||
};
|
||||
};
|
||||
|
||||
export function setFilter (filterType) {
|
||||
return dispatch => {
|
||||
dispatch({
|
||||
type: NOTIFICATIONS_FILTER_SET,
|
||||
path: ['notifications', 'quickFilter', 'active'],
|
||||
value: filterType,
|
||||
});
|
||||
dispatch(expandNotifications());
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,14 +1,8 @@
|
|||
import { openModal } from './modal';
|
||||
import { changeSetting, saveSettings } from './settings';
|
||||
|
||||
export function showOnboardingOnce() {
|
||||
return (dispatch, getState) => {
|
||||
const alreadySeen = getState().getIn(['settings', 'onboarded']);
|
||||
export const INTRODUCTION_VERSION = 20181216044202;
|
||||
|
||||
if (!alreadySeen) {
|
||||
dispatch(openModal('ONBOARDING'));
|
||||
dispatch(changeSetting(['onboarded'], true));
|
||||
export const closeOnboarding = () => dispatch => {
|
||||
dispatch(changeSetting(['introductionVersion'], INTRODUCTION_VERSION));
|
||||
dispatch(saveSettings());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -12,7 +12,7 @@ import { getLocale } from '../locales';
|
|||
|
||||
const { messages } = getLocale();
|
||||
|
||||
export function connectTimelineStream (timelineId, path, pollingRefresh = null) {
|
||||
export function connectTimelineStream (timelineId, path, pollingRefresh = null, accept = null) {
|
||||
|
||||
return connectStream (path, pollingRefresh, (dispatch, getState) => {
|
||||
const locale = getState().getIn(['meta', 'locale']);
|
||||
|
@ -24,7 +24,7 @@ export function connectTimelineStream (timelineId, path, pollingRefresh = null)
|
|||
onReceive (data) {
|
||||
switch(data.event) {
|
||||
case 'update':
|
||||
dispatch(updateTimeline(timelineId, JSON.parse(data.payload)));
|
||||
dispatch(updateTimeline(timelineId, JSON.parse(data.payload), accept));
|
||||
break;
|
||||
case 'delete':
|
||||
dispatch(deleteFromTimelines(data.payload));
|
||||
|
@ -51,6 +51,6 @@ const refreshHomeTimelineAndNotification = (dispatch, done) => {
|
|||
export const connectUserStream = () => connectTimelineStream('home', 'user', refreshHomeTimelineAndNotification);
|
||||
export const connectCommunityStream = ({ onlyMedia } = {}) => connectTimelineStream(`community${onlyMedia ? ':media' : ''}`, `public:local${onlyMedia ? ':media' : ''}`);
|
||||
export const connectPublicStream = ({ onlyMedia } = {}) => connectTimelineStream(`public${onlyMedia ? ':media' : ''}`, `public${onlyMedia ? ':media' : ''}`);
|
||||
export const connectHashtagStream = tag => connectTimelineStream(`hashtag:${tag}`, `hashtag&tag=${tag}`);
|
||||
export const connectHashtagStream = (id, tag, accept) => connectTimelineStream(`hashtag:${id}`, `hashtag&tag=${tag}`, null, accept);
|
||||
export const connectDirectStream = () => connectTimelineStream('direct', 'direct');
|
||||
export const connectListStream = id => connectTimelineStream(`list:${id}`, `list&list=${id}`);
|
||||
|
|
|
@ -4,6 +4,7 @@ import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
|||
|
||||
export const TIMELINE_UPDATE = 'TIMELINE_UPDATE';
|
||||
export const TIMELINE_DELETE = 'TIMELINE_DELETE';
|
||||
export const TIMELINE_CLEAR = 'TIMELINE_CLEAR';
|
||||
|
||||
export const TIMELINE_EXPAND_REQUEST = 'TIMELINE_EXPAND_REQUEST';
|
||||
export const TIMELINE_EXPAND_SUCCESS = 'TIMELINE_EXPAND_SUCCESS';
|
||||
|
@ -13,9 +14,11 @@ export const TIMELINE_SCROLL_TOP = 'TIMELINE_SCROLL_TOP';
|
|||
|
||||
export const TIMELINE_DISCONNECT = 'TIMELINE_DISCONNECT';
|
||||
|
||||
export function updateTimeline(timeline, status) {
|
||||
return (dispatch, getState) => {
|
||||
const references = status.reblog ? getState().get('statuses').filter((item, itemId) => (itemId === status.reblog.id || item.get('reblog') === status.reblog.id)).map((_, itemId) => itemId) : [];
|
||||
export function updateTimeline(timeline, status, accept) {
|
||||
return dispatch => {
|
||||
if (typeof accept === 'function' && !accept(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(importFetchedStatus(status));
|
||||
|
||||
|
@ -23,7 +26,6 @@ export function updateTimeline(timeline, status) {
|
|||
type: TIMELINE_UPDATE,
|
||||
timeline,
|
||||
status,
|
||||
references,
|
||||
});
|
||||
};
|
||||
};
|
||||
|
@ -44,11 +46,24 @@ export function deleteFromTimelines(id) {
|
|||
};
|
||||
};
|
||||
|
||||
export function clearTimeline(timeline) {
|
||||
return (dispatch) => {
|
||||
dispatch({ type: TIMELINE_CLEAR, timeline });
|
||||
};
|
||||
};
|
||||
|
||||
const noOp = () => {};
|
||||
|
||||
const parseTags = (tags = {}, mode) => {
|
||||
return (tags[mode] || []).map((tag) => {
|
||||
return tag.value;
|
||||
});
|
||||
};
|
||||
|
||||
export function expandTimeline(timelineId, path, params = {}, done = noOp) {
|
||||
return (dispatch, getState) => {
|
||||
const timeline = getState().getIn(['timelines', timelineId], ImmutableMap());
|
||||
const isLoadingMore = !!params.max_id;
|
||||
|
||||
if (timeline.get('isLoading')) {
|
||||
done();
|
||||
|
@ -59,15 +74,17 @@ export function expandTimeline(timelineId, path, params = {}, done = noOp) {
|
|||
params.since_id = timeline.getIn(['items', 0]);
|
||||
}
|
||||
|
||||
dispatch(expandTimelineRequest(timelineId));
|
||||
const isLoadingRecent = !!params.since_id;
|
||||
|
||||
dispatch(expandTimelineRequest(timelineId, isLoadingMore));
|
||||
|
||||
api(getState).get(path, { params }).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedStatuses(response.data));
|
||||
dispatch(expandTimelineSuccess(timelineId, response.data, next ? next.uri : null, response.code === 206));
|
||||
dispatch(expandTimelineSuccess(timelineId, response.data, next ? next.uri : null, response.code === 206, isLoadingRecent, isLoadingMore));
|
||||
done();
|
||||
}).catch(error => {
|
||||
dispatch(expandTimelineFail(timelineId, error));
|
||||
dispatch(expandTimelineFail(timelineId, error, isLoadingMore));
|
||||
done();
|
||||
});
|
||||
};
|
||||
|
@ -79,31 +96,42 @@ export const expandCommunityTimeline = ({ maxId, onlyMedia } = {}, done =
|
|||
export const expandAccountTimeline = (accountId, { maxId, withReplies } = {}) => expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies, max_id: maxId });
|
||||
export const expandAccountFeaturedTimeline = accountId => expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, { pinned: true });
|
||||
export const expandAccountMediaTimeline = (accountId, { maxId } = {}) => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { max_id: maxId, only_media: true });
|
||||
export const expandHashtagTimeline = (hashtag, { maxId } = {}, done = noOp) => expandTimeline(`hashtag:${hashtag}`, `/api/v1/timelines/tag/${hashtag}`, { max_id: maxId }, done);
|
||||
export const expandListTimeline = (id, { maxId } = {}, done = noOp) => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId }, done);
|
||||
export const expandHashtagTimeline = (hashtag, { maxId, tags } = {}, done = noOp) => {
|
||||
return expandTimeline(`hashtag:${hashtag}`, `/api/v1/timelines/tag/${hashtag}`, {
|
||||
max_id: maxId,
|
||||
any: parseTags(tags, 'any'),
|
||||
all: parseTags(tags, 'all'),
|
||||
none: parseTags(tags, 'none'),
|
||||
}, done);
|
||||
};
|
||||
|
||||
export function expandTimelineRequest(timeline) {
|
||||
export function expandTimelineRequest(timeline, isLoadingMore) {
|
||||
return {
|
||||
type: TIMELINE_EXPAND_REQUEST,
|
||||
timeline,
|
||||
skipLoading: !isLoadingMore,
|
||||
};
|
||||
};
|
||||
|
||||
export function expandTimelineSuccess(timeline, statuses, next, partial) {
|
||||
export function expandTimelineSuccess(timeline, statuses, next, partial, isLoadingRecent, isLoadingMore) {
|
||||
return {
|
||||
type: TIMELINE_EXPAND_SUCCESS,
|
||||
timeline,
|
||||
statuses,
|
||||
next,
|
||||
partial,
|
||||
isLoadingRecent,
|
||||
skipLoading: !isLoadingMore,
|
||||
};
|
||||
};
|
||||
|
||||
export function expandTimelineFail(timeline, error) {
|
||||
export function expandTimelineFail(timeline, error, isLoadingMore) {
|
||||
return {
|
||||
type: TIMELINE_EXPAND_FAIL,
|
||||
timeline,
|
||||
error,
|
||||
skipLoading: !isLoadingMore,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import axios from 'axios';
|
||||
import LinkHeader from 'http-link-header';
|
||||
import ready from './ready';
|
||||
import LinkHeader from './link_header';
|
||||
|
||||
export const getLinks = response => {
|
||||
const value = response.headers.link;
|
||||
|
|
|
@ -4,5 +4,9 @@ export function start() {
|
|||
require('font-awesome/css/font-awesome.css');
|
||||
require.context('../images/', true);
|
||||
|
||||
try {
|
||||
Rails.start();
|
||||
} catch (e) {
|
||||
// If called twice
|
||||
}
|
||||
};
|
||||
|
|
|
@ -68,10 +68,10 @@ class Account extends ImmutablePureComponent {
|
|||
|
||||
if (hidden) {
|
||||
return (
|
||||
<div>
|
||||
<Fragment>
|
||||
{account.get('display_name')}
|
||||
{account.get('username')}
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue