Compare commits

..

44 Commits

Author SHA1 Message Date
chr 19780fe584 Merge tag 'v2.4.4' into cybrespace 2018-08-22 18:31:52 -07:00
Eugen Rochko 612d02028c Bump version to 2.4.4 2018-08-22 20:56:43 +02:00
Eugen Rochko f100e84372 Improve federated ID validation (#8372)
* Fix URI not being sufficiently validated with prefetched JSON

* Add additional id validation to OStatus documents, when possible
2018-08-22 20:56:26 +02:00
ThibG 31a209cb01 Upgrade doorkeeper to 4.4.2 (#8321) 2018-08-22 19:31:27 +02:00
Eugen Rochko 13a062a5d9 Upgrade Doorkeeper to 4.4.1 (#8197) 2018-08-22 19:30:02 +02:00
chr 02fdc0d5c6 Merge branch 'theme_win95' into cybrespace 2018-08-21 21:41:08 -07:00
blackle b820776a98 Set drawer__pager z-index to be greater than clippy (#23) 2018-08-21 21:33:12 -07:00
chr b41247ecf0 Grab the updated en.yml which was out of date for some reason 2018-07-21 16:07:53 -07:00
chr dc0b442228 Merge branch 'theme_light' into cybrespace 2018-07-21 16:04:07 -07:00
chr 7f583e3f0f Cybrespace light theme 2018-07-21 16:03:31 -07:00
chr c9ae6c6be8 Merge branches 'theme_light' and 'theme_win95' into cybrespace 2018-07-21 15:55:49 -07:00
chr 378f3e41b6 Merge branch 'theme_cybre' into cybrespace 2018-07-21 15:54:59 -07:00
chr 5c6be91d86 Merge branches 'branding_cybre', 'dependency_whatinput', 'feature_512_char_toots', 'feature_cybrespace_locale', 'feature_doodlebox', 'feature_hotlink_twitter_mentions', 'feature_longer_bios', 'feature_machine_registration_task' and 'theme_base' into cybrespace 2018-07-21 15:54:52 -07:00
chr f6a8ac76b6 Windows 95 theme 2018-07-21 15:53:21 -07:00
chr 21d6a10707 Cybrespace light theme 2018-07-21 15:51:09 -07:00
chr d74271faa9 Cybrespace dark theme 2018-07-21 15:49:15 -07:00
chr c231e16adb Base SCSS for cybrespace themes 2018-07-21 15:47:19 -07:00
nightpool 46566ffcb6 fix bio length autosizing 2018-07-21 15:42:14 -07:00
Andrew fcc5feceab Feature: increase bio length to 413 characters 2018-07-21 15:42:14 -07:00
Andrew 014b564f12 Hotlink twitter mentions
Differentiate twitter mentions from normal mentions
2018-07-21 15:41:50 -07:00
Andrew c22efcaee7 Feature: add a rake task that's like register but also accepts password
and produces cleaner output
2018-07-21 15:41:19 -07:00
Andrew e5bb9455a3 Move doodle-relevant css into doodle css 2018-07-21 15:39:43 -07:00
Andrew f5f007f5e0 Update doodlebox and compose form button layout 2018-07-21 15:39:42 -07:00
Ondřej Hruška 1b9efd28c8 Doodle improvements 2 (#176)
* Fix some doodle bugs and added Background color functionality

* added protections against accidental doodle erase, screen size changing

* resolve react warning about 'selected' on <option>
2018-07-21 15:39:42 -07:00
Ondřej Hruška 71f86dc99d Doodle palette, options, fill tool (#172) 2018-07-21 15:39:42 -07:00
Ondřej Hruška 835c4281ba Fixed a bug where the canvas would get transparent bg upon erase 2018-07-21 15:39:42 -07:00
Ondřej Hruška 825f9449d5 Initial doodle support 2018-07-21 15:39:42 -07:00
nightpool d81e1e5554 fix locale update for 2.3.x 2018-07-21 15:33:43 -07:00
Andrew f8d0ebbe4f Add more timeline labels 2018-07-21 15:33:42 -07:00
nightpool 98232134f8 en-cy: fix logged out locale 2018-07-21 15:33:42 -07:00
nightpool e82de8035d cybre-locale: new stings for 2.3.1 + datetime fixes 2018-07-21 15:33:42 -07:00
nightpool 18238ba71d locale: normalize 2018-07-21 15:33:42 -07:00
nightpool b31f0072e4 en-cy : manage translations 2018-07-21 15:33:42 -07:00
nightpool 998baec655 add direct column to en-CY 2018-07-21 15:33:42 -07:00
Andrew 423604bc03 Feature: sublocale of english for the cybrespace customizations that apply to translateable text 2018-07-21 15:33:42 -07:00
Andrew d6dd4a21ea Feature: 512-character limit in the toot box on client and serverside 2018-07-21 15:29:21 -07:00
Andrew 3bb71deb4f Add whatinput dependency for more responsive focus styling 2018-07-21 15:27:59 -07:00
chr d06b6340ff 2.4.2rc2 except without the bad stuff 2018-07-21 15:24:48 -07:00
chr eba9da0297 Use cybrespace repo url in getting started footer 2018-07-21 15:18:58 -07:00
chr f23bacf504 Remove image file only used in cybre theme 2018-07-21 15:18:58 -07:00
Andrew c06366cf09 Add new panels to branding 2018-07-21 15:18:58 -07:00
nightpool 7b760d60c5 hide header image w/o css 2018-07-21 15:18:58 -07:00
Andrew 8626ba1f6b New landing page for 2.3 2018-07-21 15:18:58 -07:00
Andrew 618a8c2a4d Cybrespace branding 2018-07-21 15:18:58 -07:00
900 changed files with 11029 additions and 30560 deletions

66
.babelrc Normal file
View File

@ -0,0 +1,66 @@
{
"presets": [
"react",
[
"env",
{
"exclude": ["transform-async-to-generator", "transform-regenerator"],
"loose": true,
"modules": false,
"targets": {
"browsers": ["last 2 versions", "IE >= 11", "iOS >= 9"]
}
}
]
],
"plugins": [
"syntax-dynamic-import",
["transform-object-rest-spread", { "useBuiltIns": true }],
"transform-decorators-legacy",
"transform-class-properties",
[
"react-intl",
{
"messagesDir": "./build/messages"
}
],
"preval"
],
"env": {
"development": {
"plugins": [
"transform-react-jsx-source",
"transform-react-jsx-self"
]
},
"production": {
"plugins": [
"lodash",
[
"transform-react-remove-prop-types",
{
"mode": "remove",
"removeImport": true,
"additionalLibraries": [
"react-immutable-proptypes"
]
}
],
"transform-react-inline-elements",
[
"transform-runtime",
{
"helpers": true,
"polyfill": false,
"regenerator": false
}
]
]
},
"test": {
"plugins": [
"transform-es2015-modules-commonjs"
]
}
}
}

View File

@ -1,4 +1,3 @@
https://github.com/heroku/heroku-buildpack-apt https://github.com/heroku/heroku-buildpack-apt
https://github.com/Scalingo/ffmpeg-buildpack
https://github.com/Scalingo/nodejs-buildpack https://github.com/Scalingo/nodejs-buildpack
https://github.com/Scalingo/ruby-buildpack https://github.com/Scalingo/ruby-buildpack

View File

@ -13,9 +13,6 @@ aliases:
ALLOW_NOPAM: true ALLOW_NOPAM: true
CONTINUOUS_INTEGRATION: true CONTINUOUS_INTEGRATION: true
DISABLE_SIMPLECOV: true DISABLE_SIMPLECOV: true
PAM_ENABLED: true
PAM_DEFAULT_SERVICE: pam_test
PAM_CONTROLLED_SERVICE: pam_test_controlled
working_directory: ~/projects/mastodon/ working_directory: ~/projects/mastodon/
- &attach_workspace - &attach_workspace
@ -67,17 +64,12 @@ aliases:
- run: ruby -e 'puts RUBY_VERSION' | tee /tmp/.ruby-version - run: ruby -e 'puts RUBY_VERSION' | tee /tmp/.ruby-version
- *restore_ruby_dependencies - *restore_ruby_dependencies
- run: bundle install --clean --jobs 16 --path ./vendor/bundle/ --retry 3 --with pam_authentication --without development production && bundle clean - run: bundle install --clean --jobs 16 --path ./vendor/bundle/ --retry 3 --with pam_authentication --without development production
- save_cache: - save_cache:
key: v2-ruby-dependencies-{{ checksum "/tmp/.ruby-version" }}-{{ checksum "Gemfile.lock" }} key: v2-ruby-dependencies-{{ checksum "/tmp/.ruby-version" }}-{{ checksum "Gemfile.lock" }}
paths: paths:
- ./.bundle/ - ./.bundle/
- ./vendor/bundle/ - ./vendor/bundle/
- persist_to_workspace:
root: ~/projects/
paths:
- ./mastodon/.bundle/
- ./mastodon/vendor/bundle/
- &test_steps - &test_steps
steps: steps:
@ -86,6 +78,15 @@ aliases:
- *install_system_dependencies - *install_system_dependencies
- run: sudo apt-get install -y ffmpeg - run: sudo apt-get install -y ffmpeg
- run: ruby -e 'puts RUBY_VERSION' | tee /tmp/.ruby-version
- *restore_ruby_dependencies
- restore_cache:
keys:
- precompiled-assets-{{ .Branch }}-{{ .Revision }}
- precompiled-assets-{{ .Branch }}-
- precompiled-assets-
- run: - run:
name: Prepare Tests name: Prepare Tests
command: ./bin/rails parallel:create parallel:load_schema parallel:prepare command: ./bin/rails parallel:create parallel:load_schema parallel:prepare
@ -121,12 +122,14 @@ jobs:
steps: steps:
- *attach_workspace - *attach_workspace
- *install_system_dependencies - *install_system_dependencies
- run: ruby -e 'puts RUBY_VERSION' | tee /tmp/.ruby-version
- *restore_ruby_dependencies
- run: ./bin/rails assets:precompile - run: ./bin/rails assets:precompile
- persist_to_workspace: - save_cache:
root: ~/projects/ key: precompiled-assets-{{ .Branch }}-{{ .Revision }}
paths: paths:
- ./mastodon/public/assets - ./public/assets
- ./mastodon/public/packs-test/ - ./public/packs-test/
test-ruby2.5: test-ruby2.5:
<<: *defaults <<: *defaults
@ -173,10 +176,10 @@ jobs:
<<: *defaults <<: *defaults
steps: steps:
- *attach_workspace - *attach_workspace
- run: ruby -e 'puts RUBY_VERSION' | tee /tmp/.ruby-version
- *restore_ruby_dependencies
- run: bundle exec i18n-tasks check-normalized - run: bundle exec i18n-tasks check-normalized
- run: bundle exec i18n-tasks unused - run: bundle exec i18n-tasks unused
- run: bundle exec i18n-tasks missing -t plural
- run: bundle exec i18n-tasks check-consistent-interpolations
workflows: workflows:
version: 2 version: 2
@ -189,11 +192,9 @@ workflows:
- install-ruby2.4: - install-ruby2.4:
requires: requires:
- install - install
- install-ruby2.5
- install-ruby2.3: - install-ruby2.3:
requires: requires:
- install - install
- install-ruby2.5
- build: - build:
requires: requires:
- install-ruby2.5 - install-ruby2.5

View File

@ -136,8 +136,8 @@ SMTP_FROM_ADDRESS=notifications@${APP_NAME}.nanoapp.io
# Defaults to 60 seconds. Set to 0 to disable # Defaults to 60 seconds. Set to 0 to disable
# SWIFT_CACHE_TTL= # SWIFT_CACHE_TTL=
# Optional alias for S3 (e.g. to serve files on a custom domain, possibly using Cloudfront or Cloudflare) # Optional alias for S3 if you want to use Cloudfront or Cloudflare in front
# S3_ALIAS_HOST= # S3_CLOUDFRONT_HOST=
# Streaming API integration # Streaming API integration
# STREAMING_API_BASE_URL= # STREAMING_API_BASE_URL=

View File

@ -134,8 +134,8 @@ SMTP_FROM_ADDRESS=notifications@example.com
# Defaults to 60 seconds. Set to 0 to disable # Defaults to 60 seconds. Set to 0 to disable
# SWIFT_CACHE_TTL= # SWIFT_CACHE_TTL=
# Optional alias for S3 (e.g. to serve files on a custom domain, possibly using Cloudfront or Cloudflare) # Optional alias for S3 if you want to use Cloudfront or Cloudflare in front
# S3_ALIAS_HOST= # S3_CLOUDFRONT_HOST=
# Streaming API integration # Streaming API integration
# STREAMING_API_BASE_URL= # STREAMING_API_BASE_URL=
@ -162,7 +162,6 @@ STREAMING_CLUSTER_NUM=1
# LDAP_BIND_DN= # LDAP_BIND_DN=
# LDAP_PASSWORD= # LDAP_PASSWORD=
# LDAP_UID=cn # LDAP_UID=cn
# LDAP_SEARCH_FILTER="%{uid}=%{email}"
# PAM authentication (optional) # PAM authentication (optional)
# PAM authentication uses for the email generation the "email" pam variable # PAM authentication uses for the email generation the "email" pam variable

View File

@ -3,3 +3,7 @@ NODE_ENV=test
# Federation # Federation
LOCAL_DOMAIN=cb6e6126.ngrok.io LOCAL_DOMAIN=cb6e6126.ngrok.io
LOCAL_HTTPS=true LOCAL_HTTPS=true
# test pam authentication
PAM_ENABLED=true
PAM_DEFAULT_SERVICE=pam_test
PAM_CONTROLLED_SERVICE=pam_test_controlled

View File

@ -1,2 +1,2 @@
VAGRANT=true VAGRANT=true
LOCAL_DOMAIN=mastodon.local LOCAL_DOMAIN=mastodon.dev

View File

@ -1,27 +1,12 @@
--- ---
name: Bug Report name: Bug Report
about: If something isn't working as expected about: Create a report to help us improve
--- ---
<!-- Make sure that you are submitting a new bug that was not previously reported or already fixed --> [Issue text goes here].
<!-- Please use a concise and distinct title for the issue --> * * * *
### Expected behaviour - [ ] I searched or browsed the repos other issues to ensure this is not a duplicate.
- [ ] This bug happens on a [tagged release](https://github.com/tootsuite/mastodon/releases) and not on `master` (If you're a user, don't worry about this).
<!-- What should have happened? -->
### Actual behaviour
<!-- What happened? -->
### Steps to reproduce the problem
<!-- What were you trying to do? -->
### Specifications
<!-- What version or commit hash of Mastodon did you find this bug in? -->
<!-- If a front-end issue, what browser and operating systems were you using? -->

View File

@ -1,17 +1,11 @@
--- ---
name: Feature Request name: Feature Request
about: I have a suggestion about: Suggest an idea for this project
--- ---
<!-- Please use a concise and distinct title for the issue --> [Issue text goes here].
<!-- Consider: Could it be implemented as a 3rd party app using the REST API instead? --> * * * *
### Pitch - [ ] I searched or browsed the repos other issues to ensure this is not a duplicate.
<!-- Describe your idea for a feature. Make sure it has not already been suggested/implemented/turned down before -->
### Motivation
<!-- Why do you think this feature is needed? Who would benefit from it? -->

View File

@ -1,10 +0,0 @@
---
name: Support
about: Ask for help with your deployment
---
We primarily use GitHub as a bug and feature tracker. For usage questions, troubleshooting of deployments and other individual technical assistance, please use one of the resources below:
- https://discourse.joinmastodon.org
- #mastodon on irc.freenode.net

2
.nvmrc
View File

@ -1 +1 @@
8 6

View File

@ -11,7 +11,6 @@ AllCops:
- 'Vagrantfile' - 'Vagrantfile'
- 'vendor/**/*' - 'vendor/**/*'
- 'lib/json_ld/*' - 'lib/json_ld/*'
- 'lib/templates/**/*'
Bundler/OrderedGems: Bundler/OrderedGems:
Enabled: false Enabled: false
@ -62,9 +61,6 @@ Metrics/ParameterLists:
Metrics/PerceivedComplexity: Metrics/PerceivedComplexity:
Max: 20 Max: 20
Naming/MemoizedInstanceVariableName:
Enabled: false
Rails: Rails:
Enabled: true Enabled: true
@ -74,14 +70,6 @@ Rails/HasAndBelongsToMany:
Rails/SkipsModelValidations: Rails/SkipsModelValidations:
Enabled: false Enabled: false
Rails/HttpStatus:
Enabled: false
Rails/Exit:
Exclude:
- 'lib/mastodon/*'
- 'lib/cli'
Style/ClassAndModuleChildren: Style/ClassAndModuleChildren:
Enabled: false Enabled: false

View File

@ -1 +1 @@
2.5.3 2.5.1

View File

@ -3,85 +3,76 @@ and provided thanks to the work of the following contributors:
* [Gargron](https://github.com/Gargron) * [Gargron](https://github.com/Gargron)
* [ykzts](https://github.com/ykzts) * [ykzts](https://github.com/ykzts)
* [akihikodaki](https://github.com/akihikodaki)
* [mjankowski](https://github.com/mjankowski) * [mjankowski](https://github.com/mjankowski)
* [ThibG](https://github.com/ThibG) * [akihikodaki](https://github.com/akihikodaki)
* [unarist](https://github.com/unarist) * [unarist](https://github.com/unarist)
* [m4sk1n](https://github.com/m4sk1n)
* [yiskah](https://github.com/yiskah) * [yiskah](https://github.com/yiskah)
* [m4sk1n](https://github.com/m4sk1n)
* [nolanlawson](https://github.com/nolanlawson) * [nolanlawson](https://github.com/nolanlawson)
* [sorin-davidoi](https://github.com/sorin-davidoi) * [sorin-davidoi](https://github.com/sorin-davidoi)
* [abcang](https://github.com/abcang) * [abcang](https://github.com/abcang)
* [ThibG](https://github.com/ThibG)
* [lynlynlynx](https://github.com/lynlynlynx) * [lynlynlynx](https://github.com/lynlynlynx)
* [dependabot[bot]](https://github.com/apps/dependabot)
* [alpaca-tc](https://github.com/alpaca-tc) * [alpaca-tc](https://github.com/alpaca-tc)
* [nclm](https://github.com/nclm) * [nclm](https://github.com/nclm)
* [ineffyble](https://github.com/ineffyble) * [ineffyble](https://github.com/ineffyble)
* [renatolond](https://github.com/renatolond)
* [jeroenpraat](https://github.com/jeroenpraat) * [jeroenpraat](https://github.com/jeroenpraat)
* [mayaeh](https://github.com/mayaeh)
* [blackle](https://github.com/blackle) * [blackle](https://github.com/blackle)
* [Quent-in](https://github.com/Quent-in) * [Quent-in](https://github.com/Quent-in)
* [JantsoP](https://github.com/JantsoP) * [JantsoP](https://github.com/JantsoP)
* [nullkal](https://github.com/nullkal) * [nullkal](https://github.com/nullkal)
* [yookoala](https://github.com/yookoala) * [yookoala](https://github.com/yookoala)
* [mabkenar](https://github.com/mabkenar)
* [ysksn](https://github.com/ysksn) * [ysksn](https://github.com/ysksn)
* [shuheiktgw](https://github.com/shuheiktgw)
* [ashfurrow](https://github.com/ashfurrow) * [ashfurrow](https://github.com/ashfurrow)
* [Kjwon15](https://github.com/Kjwon15)
* [zunda](https://github.com/zunda)
* [eramdam](https://github.com/eramdam) * [eramdam](https://github.com/eramdam)
* [masarakki](https://github.com/masarakki) * [mayaeh](https://github.com/mayaeh)
* [takayamaki](https://github.com/takayamaki) * [zunda](https://github.com/zunda)
* [ticky](https://github.com/ticky) * [ticky](https://github.com/ticky)
* [Quenty31](https://github.com/Quenty31) * [masarakki](https://github.com/masarakki)
* [danhunsaker](https://github.com/danhunsaker)
* [ThisIsMissEm](https://github.com/ThisIsMissEm)
* [hcmiya](https://github.com/hcmiya)
* [stephenburgess8](https://github.com/stephenburgess8)
* [Wonderfall](https://github.com/Wonderfall) * [Wonderfall](https://github.com/Wonderfall)
* [matteoaquila](https://github.com/matteoaquila) * [matteoaquila](https://github.com/matteoaquila)
* [rkarabut](https://github.com/rkarabut) * [rkarabut](https://github.com/rkarabut)
* [yukimochi](https://github.com/yukimochi) * [stephenburgess8](https://github.com/stephenburgess8)
* [Kjwon15](https://github.com/Kjwon15)
* [Artoria2e5](https://github.com/Artoria2e5) * [Artoria2e5](https://github.com/Artoria2e5)
* [yukimochi](https://github.com/yukimochi)
* [marrus-sh](https://github.com/marrus-sh) * [marrus-sh](https://github.com/marrus-sh)
* [krainboltgreene](https://github.com/krainboltgreene) * [krainboltgreene](https://github.com/krainboltgreene)
* [patf](https://github.com/patf) * [renatolond](https://github.com/renatolond)
* [Aldarone](https://github.com/Aldarone)
* [BoFFire](https://github.com/BoFFire) * [BoFFire](https://github.com/BoFFire)
* [clworld](https://github.com/clworld) * [clworld](https://github.com/clworld)
* [dracos](https://github.com/dracos) * [danhunsaker](https://github.com/danhunsaker)
* [SerCom_KC](mailto:sercom-kc@users.noreply.github.com) * [patf](https://github.com/patf)
* [Sylvhem](https://github.com/Sylvhem) * [Quenty31](https://github.com/Quenty31)
* [nightpool](https://github.com/nightpool) * [MitarashiDango](https://github.com/MitarashiDango)
* [MasterGroosha](https://github.com/MasterGroosha) * [Aldarone](https://github.com/Aldarone)
* [JeanGauthier](https://github.com/JeanGauthier) * [JeanGauthier](https://github.com/JeanGauthier)
* [kschaper](https://github.com/kschaper) * [kschaper](https://github.com/kschaper)
* [MaciekBaron](https://github.com/MaciekBaron) * [takayamaki](https://github.com/takayamaki)
* [MitarashiDango](mailto:mitarashidango@users.noreply.github.com)
* [beatrix-bitrot](https://github.com/beatrix-bitrot)
* [adbelle](https://github.com/adbelle) * [adbelle](https://github.com/adbelle)
* [evanminto](https://github.com/evanminto) * [evanminto](https://github.com/evanminto)
* [mabkenar](https://github.com/mabkenar)
* [MightyPork](https://github.com/MightyPork) * [MightyPork](https://github.com/MightyPork)
* [beatrix-bitrot](https://github.com/beatrix-bitrot)
* [yhirano55](https://github.com/yhirano55) * [yhirano55](https://github.com/yhirano55)
* [camponez](https://github.com/camponez) * [camponez](https://github.com/camponez)
* [SerCom-KC](https://github.com/SerCom-KC)
* [aschmitz](https://github.com/aschmitz) * [aschmitz](https://github.com/aschmitz)
* [devkral](https://github.com/devkral)
* [fpiesche](https://github.com/fpiesche) * [fpiesche](https://github.com/fpiesche)
* [gandaro](https://github.com/gandaro) * [gandaro](https://github.com/gandaro)
* [johnsudaar](https://github.com/johnsudaar) * [johnsudaar](https://github.com/johnsudaar)
* [trebmuh](https://github.com/trebmuh) * [trebmuh](https://github.com/trebmuh)
* [Rakib Hasan](mailto:rmhasan@gmail.com) * [Sylvhem](https://github.com/Sylvhem)
* [lindwurm](https://github.com/lindwurm) * [lindwurm](https://github.com/lindwurm)
* [victorhck](mailto:victorhck@geeko.site)
* [voidsatisfaction](https://github.com/voidsatisfaction) * [voidsatisfaction](https://github.com/voidsatisfaction)
* [neetshin](https://github.com/neetshin)
* [valentin2105](https://github.com/valentin2105)
* [hikari-no-yume](https://github.com/hikari-no-yume) * [hikari-no-yume](https://github.com/hikari-no-yume)
* [angristan](https://github.com/angristan) * [Angristan](https://github.com/Angristan)
* [seefood](https://github.com/seefood) * [seefood](https://github.com/seefood)
* [jackjennings](https://github.com/jackjennings) * [jackjennings](https://github.com/jackjennings)
* [spla](mailto:spla@mastodont.cat) * [hcmiya](https://github.com/hcmiya)
* [nightpool](https://github.com/nightpool)
* [salvadorpla](https://github.com/salvadorpla)
* [expenses](https://github.com/expenses) * [expenses](https://github.com/expenses)
* [walf443](https://github.com/walf443) * [walf443](https://github.com/walf443)
* [JoelQ](https://github.com/JoelQ) * [JoelQ](https://github.com/JoelQ)
@ -93,93 +84,74 @@ and provided thanks to the work of the following contributors:
* [tsuwatch](https://github.com/tsuwatch) * [tsuwatch](https://github.com/tsuwatch)
* [victorhck](https://github.com/victorhck) * [victorhck](https://github.com/victorhck)
* [puckipedia](https://github.com/puckipedia) * [puckipedia](https://github.com/puckipedia)
* [fvh-P](https://github.com/fvh-P)
* [contraexemplo](https://github.com/contraexemplo) * [contraexemplo](https://github.com/contraexemplo)
* [hugogameiro](https://github.com/hugogameiro)
* [kazu9su](https://github.com/kazu9su) * [kazu9su](https://github.com/kazu9su)
* [Komic](https://github.com/Komic) * [Komic](https://github.com/Komic)
* [diomed](https://github.com/diomed) * [diomed](https://github.com/diomed)
* [ariasuni](https://github.com/ariasuni)
* [Neetshin](mailto:neetshin@neetsh.in)
* [rainyday](https://github.com/rainyday) * [rainyday](https://github.com/rainyday)
* [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) * [kadiix](https://github.com/kadiix)
* [kodacs](https://github.com/kodacs) * [kodacs](https://github.com/kodacs)
* [rtucker](https://github.com/rtucker) * [ProgVal](https://github.com/ProgVal)
* [KScl](https://github.com/KScl)
* [sterdev](https://github.com/sterdev) * [sterdev](https://github.com/sterdev)
* [TheKinrar](https://github.com/TheKinrar) * [TheKinrar](https://github.com/TheKinrar)
* [AA4ch1](https://github.com/AA4ch1) * [AA4ch1](https://github.com/AA4ch1)
* [alexgleason](https://github.com/alexgleason) * [alexgleason](https://github.com/alexgleason)
* [cpytel](https://github.com/cpytel) * [cpytel](https://github.com/cpytel)
* [northerner](https://github.com/northerner) * [northerner](https://github.com/northerner)
* [fhemberger](https://github.com/fhemberger)
* [greysteil](https://github.com/greysteil)
* [hnrysmth](https://github.com/hnrysmth) * [hnrysmth](https://github.com/hnrysmth)
* [d6rkaiz](https://github.com/d6rkaiz) * [hugogameiro](https://github.com/hugogameiro)
* [JMendyk](https://github.com/JMendyk)
* [JohnD28](https://github.com/JohnD28) * [JohnD28](https://github.com/JohnD28)
* [znz](https://github.com/znz) * [znz](https://github.com/znz)
* [Naouak](https://github.com/Naouak) * [Naouak](https://github.com/Naouak)
* [rtucker](https://github.com/rtucker)
* [reneklacan](https://github.com/reneklacan) * [reneklacan](https://github.com/reneklacan)
* [ekiru](https://github.com/ekiru) * [KScl](https://github.com/KScl)
* [SerCom-KC](https://github.com/SerCom-KC)
* [tcitworld](https://github.com/tcitworld) * [tcitworld](https://github.com/tcitworld)
* [geta6](https://github.com/geta6) * [geta6](https://github.com/geta6)
* [goofy-bz](https://github.com/goofy-bz)
* [happycoloredbanana](https://github.com/happycoloredbanana) * [happycoloredbanana](https://github.com/happycoloredbanana)
* [kedamaDQ](https://github.com/kedamaDQ)
* [leopku](https://github.com/leopku) * [leopku](https://github.com/leopku)
* [SansPseudoFix](https://github.com/SansPseudoFix) * [SansPseudoFix](https://github.com/SansPseudoFix)
* [tomfhowe](https://github.com/tomfhowe) * [tomfhowe](https://github.com/tomfhowe)
* [noraworld](https://github.com/noraworld) * [noraworld](https://github.com/noraworld)
* [theboss](https://github.com/theboss) * [fvh-P](https://github.com/fvh-P)
* [178inaba](https://github.com/178inaba) * [178inaba](https://github.com/178inaba)
* [devkral](https://github.com/devkral)
* [alyssais](https://github.com/alyssais) * [alyssais](https://github.com/alyssais)
* [kodnaplakal](https://github.com/kodnaplakal) * [kodnaplakal](https://github.com/kodnaplakal)
* [stalker314314](https://github.com/stalker314314) * [stalker314314](https://github.com/stalker314314)
* [huertanix](https://github.com/huertanix) * [huertanix](https://github.com/huertanix)
* [genesixx](https://github.com/genesixx) * [genesixx](https://github.com/genesixx)
* [fhemberger](https://github.com/fhemberger)
* [halkeye](https://github.com/halkeye) * [halkeye](https://github.com/halkeye)
* [hinaloe](https://github.com/hinaloe)
* [treby](https://github.com/treby) * [treby](https://github.com/treby)
* [Reverite](https://github.com/Reverite) * [d6rkaiz](https://github.com/d6rkaiz)
* [jpdevries](https://github.com/jpdevries) * [jpdevries](https://github.com/jpdevries)
* [H-C-F](https://github.com/H-C-F) * [rndm-stranger](https://github.com/rndm-stranger)
* [Kurtis Rainbolt-Greene](mailto:me@kurtisrainboltgreene.name)
* [saper](https://github.com/saper) * [saper](https://github.com/saper)
* [nevillepark](https://github.com/nevillepark) * [nevillepark](https://github.com/nevillepark)
* [ornithocoder](https://github.com/ornithocoder) * [ornithocoder](https://github.com/ornithocoder)
* [pierreozoux](https://github.com/pierreozoux) * [pierreozoux](https://github.com/pierreozoux)
* [qguv](https://github.com/qguv) * [ramlmn](https://github.com/ramlmn)
* [Ram Lmn](mailto:ramlmn@users.noreply.github.com)
* [harukasan](https://github.com/harukasan) * [harukasan](https://github.com/harukasan)
* [stamak](https://github.com/stamak) * [stamak](https://github.com/stamak)
* [Technowix](mailto:technowix@users.noreply.github.com)
* [Eychics](https://github.com/Eychics) * [Eychics](https://github.com/Eychics)
* [Thor Harald Johansen](mailto:thj@thj.no) * [thor-the-norseman](https://github.com/thor-the-norseman)
* [0x70b1a5](https://github.com/0x70b1a5) * [0x70b1a5](https://github.com/0x70b1a5)
* [gled-rs](https://github.com/gled-rs) * [gled-rs](https://github.com/gled-rs)
* [Valentin_NC](mailto:valentin.ouvrard@nautile.sarl)
* [R0ckweb](https://github.com/R0ckweb) * [R0ckweb](https://github.com/R0ckweb)
* [caasi](https://github.com/caasi)
* [esetomo](https://github.com/esetomo) * [esetomo](https://github.com/esetomo)
* [foxiehkins](https://github.com/foxiehkins) * [foxiehkins](https://github.com/foxiehkins)
* [hoodie](mailto:hoodiekitten@outlook.com) * [sdukhovni](https://github.com/sdukhovni)
* [luzi82](https://github.com/luzi82)
* [duxovni](https://github.com/duxovni)
* [unsmell](https://github.com/unsmell) * [unsmell](https://github.com/unsmell)
* [chriswmartin](https://github.com/chriswmartin) * [chriswmartin](https://github.com/chriswmartin)
* [vahnj](https://github.com/vahnj) * [vahnj](https://github.com/vahnj)
* [ikuradon](https://github.com/ikuradon) * [ikuradon](https://github.com/ikuradon)
* [AndreLewin](https://github.com/AndreLewin) * [AndreLewin](https://github.com/AndreLewin)
* [rinsuki](https://github.com/rinsuki)
* [redtachyons](https://github.com/redtachyons) * [redtachyons](https://github.com/redtachyons)
* [thurloat](https://github.com/thurloat) * [thurloat](https://github.com/thurloat)
* [aaribaud](https://github.com/aaribaud) * [aaribaud](https://github.com/aaribaud)
* [Andrew](mailto:andrewlchronister@gmail.com)
* [estuans](https://github.com/estuans) * [estuans](https://github.com/estuans)
* [dissolve](https://github.com/dissolve) * [dissolve](https://github.com/dissolve)
* [PurpleBooth](https://github.com/PurpleBooth) * [PurpleBooth](https://github.com/PurpleBooth)
@ -193,46 +165,36 @@ and provided thanks to the work of the following contributors:
* [farlistener](https://github.com/farlistener) * [farlistener](https://github.com/farlistener)
* [DavidLibeau](https://github.com/DavidLibeau) * [DavidLibeau](https://github.com/DavidLibeau)
* [SirCmpwn](https://github.com/SirCmpwn) * [SirCmpwn](https://github.com/SirCmpwn)
* [MasterGroosha](https://github.com/MasterGroosha)
* [Fjoerfoks](https://github.com/Fjoerfoks) * [Fjoerfoks](https://github.com/Fjoerfoks)
* [fmauNeko](https://github.com/fmauNeko) * [fmauNeko](https://github.com/fmauNeko)
* [gloaec](https://github.com/gloaec) * [gloaec](https://github.com/gloaec)
* [Gomasy](https://github.com/Gomasy) * [greysteil](https://github.com/greysteil)
* [unstabler](https://github.com/unstabler) * [unstabler](https://github.com/unstabler)
* [potato4d](https://github.com/potato4d) * [potato4d](https://github.com/potato4d)
* [h-izumi](https://github.com/h-izumi) * [h-izumi](https://github.com/h-izumi)
* [ErikXXon](https://github.com/ErikXXon) * [ErikXXon](https://github.com/ErikXXon)
* [ian-kelling](https://github.com/ian-kelling) * [ian-kelling](https://github.com/ian-kelling)
* [immae](https://github.com/immae)
* [foozmeat](https://github.com/foozmeat) * [foozmeat](https://github.com/foozmeat)
* [jasonrhodes](https://github.com/jasonrhodes) * [jasonrhodes](https://github.com/jasonrhodes)
* [Jason Snell](mailto:jason@newrelic.com) * [asm](https://github.com/asm)
* [jviide](https://github.com/jviide) * [jviide](https://github.com/jviide)
* [crakaC](https://github.com/crakaC) * [crakaC](https://github.com/crakaC)
* [tkbky](https://github.com/tkbky) * [tkbky](https://github.com/tkbky)
* [Kaylee](mailto:kaylee@codethat.sucks)
* [Kazhnuz](https://github.com/Kazhnuz) * [Kazhnuz](https://github.com/Kazhnuz)
* [connyduck](https://github.com/connyduck)
* [Lindsey Bieda](mailto:lindseyb@users.noreply.github.com)
* [Lorenz Diener](mailto:halcyon@icosahedron.website)
* [alimony](https://github.com/alimony) * [alimony](https://github.com/alimony)
* [mig5](https://github.com/mig5) * [mig5](https://github.com/mig5)
* [ndarville](https://github.com/ndarville) * [ndarville](https://github.com/ndarville)
* [Abzol](https://github.com/Abzol) * [Abzol](https://github.com/Abzol)
* [pwoolcoc](https://github.com/pwoolcoc)
* [xPaw](https://github.com/xPaw) * [xPaw](https://github.com/xPaw)
* [petzah](https://github.com/petzah)
* [ignisf](https://github.com/ignisf)
* [raymestalez](https://github.com/raymestalez) * [raymestalez](https://github.com/raymestalez)
* [sascha-sl](https://github.com/sascha-sl)
* [u1-liquid](https://github.com/u1-liquid)
* [sim6](https://github.com/sim6) * [sim6](https://github.com/sim6)
* [stemid](https://github.com/stemid) * [ekiru](https://github.com/ekiru)
* [Technowix](https://github.com/Technowix)
* [ThomasLeister](https://github.com/ThomasLeister) * [ThomasLeister](https://github.com/ThomasLeister)
* [mcat-ee](https://github.com/mcat-ee) * [mcat-ee](https://github.com/mcat-ee)
* [tototoshi](https://github.com/tototoshi) * [tototoshi](https://github.com/tototoshi)
* [TrashMacNugget](https://github.com/TrashMacNugget)
* [VirtuBox](https://github.com/VirtuBox) * [VirtuBox](https://github.com/VirtuBox)
* [Vladyslav](mailto:vaden@tuta.io)
* [kaniini](https://github.com/kaniini) * [kaniini](https://github.com/kaniini)
* [vayan](https://github.com/vayan) * [vayan](https://github.com/vayan)
* [yannicka](https://github.com/yannicka) * [yannicka](https://github.com/yannicka)
@ -240,12 +202,7 @@ and provided thanks to the work of the following contributors:
* [zacanger](https://github.com/zacanger) * [zacanger](https://github.com/zacanger)
* [amazedkoumei](https://github.com/amazedkoumei) * [amazedkoumei](https://github.com/amazedkoumei)
* [anon5r](https://github.com/anon5r) * [anon5r](https://github.com/anon5r)
* [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) * [codl](https://github.com/codl)
* [cpsdqs](https://github.com/cpsdqs)
* [barzamin](https://github.com/barzamin) * [barzamin](https://github.com/barzamin)
* [fhalna](https://github.com/fhalna) * [fhalna](https://github.com/fhalna)
* [haoyayoi](https://github.com/haoyayoi) * [haoyayoi](https://github.com/haoyayoi)
@ -258,55 +215,42 @@ and provided thanks to the work of the following contributors:
* [oliverkeeble](https://github.com/oliverkeeble) * [oliverkeeble](https://github.com/oliverkeeble)
* [pinfort](https://github.com/pinfort) * [pinfort](https://github.com/pinfort)
* [rbaumert](https://github.com/rbaumert) * [rbaumert](https://github.com/rbaumert)
* [rhoio](https://github.com/rhoio)
* [trwnh](https://github.com/trwnh)
* [usagi-f](https://github.com/usagi-f) * [usagi-f](https://github.com/usagi-f)
* [vidarlee](https://github.com/vidarlee) * [vidarlee](https://github.com/vidarlee)
* [vjackson725](https://github.com/vjackson725) * [vjackson725](https://github.com/vjackson725)
* [wxcafe](https://github.com/wxcafe) * [wxcafe](https://github.com/wxcafe)
* [新都心(Neet Shin)](mailto:nucx@dio-vox.com) * [rinsuki](https://github.com/rinsuki)
* [cygnan](https://github.com/cygnan) * [cygnan](https://github.com/cygnan)
* [Awea](https://github.com/Awea) * [Awea](https://github.com/Awea)
* [halcy](https://github.com/halcy) * [halcy](https://github.com/halcy)
* [naaaaaaaaaaaf](https://github.com/naaaaaaaaaaaf) * [bounshi](https://github.com/bounshi)
* [NecroTechno](https://github.com/NecroTechno)
* [8398a7](https://github.com/8398a7) * [8398a7](https://github.com/8398a7)
* [857b](https://github.com/857b) * [857b](https://github.com/857b)
* [insom](https://github.com/insom)
* [Aditoo17](https://github.com/Aditoo17)
* [unascribed](https://github.com/unascribed) * [unascribed](https://github.com/unascribed)
* [Aguay-val](https://github.com/Aguay-val) * [Aguay-val](https://github.com/Aguay-val)
* [Akihiko Odaki](mailto:nekomanma@pixiv.co.jp)
* [knu](https://github.com/knu) * [knu](https://github.com/knu)
* [h3poteto](https://github.com/h3poteto)
* [unleashed](https://github.com/unleashed)
* [alxrcs](https://github.com/alxrcs) * [alxrcs](https://github.com/alxrcs)
* [console-cowboy](https://github.com/console-cowboy) * [console-cowboy](https://github.com/console-cowboy)
* [pointlessone](https://github.com/pointlessone) * [pointlessone](https://github.com/pointlessone)
* [a2](https://github.com/a2) * [a2](https://github.com/a2)
* [0xa](https://github.com/0xa) * [0xa](https://github.com/0xa)
* [palindromordnilap](https://github.com/palindromordnilap)
* [virtualpain](https://github.com/virtualpain) * [virtualpain](https://github.com/virtualpain)
* [sapphirus](https://github.com/sapphirus) * [sapphirus](https://github.com/sapphirus)
* [amandavisconti](https://github.com/amandavisconti) * [amandavisconti](https://github.com/amandavisconti)
* [ameliavoncat](https://github.com/ameliavoncat) * [ameliavoncat](https://github.com/ameliavoncat)
* [ilpianista](https://github.com/ilpianista) * [ilpianista](https://github.com/ilpianista)
* [Andreas Drop](mailto:andy@remline.de) * [andydrop](https://github.com/andydrop)
* [andi1984](https://github.com/andi1984)
* [schas002](https://github.com/schas002) * [schas002](https://github.com/schas002)
* [abackstrom](https://github.com/abackstrom)
* [jumbosushi](https://github.com/jumbosushi) * [jumbosushi](https://github.com/jumbosushi)
* [ayumin](https://github.com/ayumin) * [ayumin](https://github.com/ayumin)
* [BaptisteGelez](https://github.com/BaptisteGelez) * [BaptisteGelez](https://github.com/BaptisteGelez)
* [bzg](https://github.com/bzg) * [bzg](https://github.com/bzg)
* [BenLubar](https://github.com/BenLubar)
* [benediktg](https://github.com/benediktg) * [benediktg](https://github.com/benediktg)
* [blakebarnett](https://github.com/blakebarnett) * [blakebarnett](https://github.com/blakebarnett)
* [bradj](https://github.com/bradj) * [bradj](https://github.com/bradj)
* [brycied00d](https://github.com/brycied00d) * [brycied00d](https://github.com/brycied00d)
* [carlosjs23](https://github.com/carlosjs23) * [carlosjs23](https://github.com/carlosjs23)
* [cgxxx](https://github.com/cgxxx) * [cgxxx](https://github.com/cgxxx)
* [kibitan](https://github.com/kibitan)
* [chrisheninger](https://github.com/chrisheninger) * [chrisheninger](https://github.com/chrisheninger)
* [chris-martin](https://github.com/chris-martin) * [chris-martin](https://github.com/chris-martin)
* [DoubleMalt](https://github.com/DoubleMalt) * [DoubleMalt](https://github.com/DoubleMalt)
@ -315,33 +259,22 @@ and provided thanks to the work of the following contributors:
* [chriswk](https://github.com/chriswk) * [chriswk](https://github.com/chriswk)
* [csu](https://github.com/csu) * [csu](https://github.com/csu)
* [kklleemm](https://github.com/kklleemm) * [kklleemm](https://github.com/kklleemm)
* [colindean](https://github.com/colindean) * [monsterpit-daggertooth](https://github.com/monsterpit-daggertooth)
* [dachinat](https://github.com/dachinat)
* [multiple-creatures](https://github.com/multiple-creatures)
* [watilde](https://github.com/watilde) * [watilde](https://github.com/watilde)
* [daprice](https://github.com/daprice) * [daprice](https://github.com/daprice)
* [dar5hak](https://github.com/dar5hak) * [dar5hak](https://github.com/dar5hak)
* [kant](https://github.com/kant) * [kant](https://github.com/kant)
* [maxolasersquad](https://github.com/maxolasersquad)
* [singingwolfboy](https://github.com/singingwolfboy) * [singingwolfboy](https://github.com/singingwolfboy)
* [davidcelis](https://github.com/davidcelis) * [davidcelis](https://github.com/davidcelis)
* [davefp](https://github.com/davefp)
* [yipdw](https://github.com/yipdw) * [yipdw](https://github.com/yipdw)
* [debanshuk](https://github.com/debanshuk) * [debanshuk](https://github.com/debanshuk)
* [Derek Lewis](mailto:derekcecillewis@gmail.com)
* [dblandin](https://github.com/dblandin) * [dblandin](https://github.com/dblandin)
* [Drew Gates](mailto:aranaur@users.noreply.github.com) * [aranaur](https://github.com/aranaur)
* [dtschust](https://github.com/dtschust)
* [Dryusdan](https://github.com/Dryusdan)
* [eai04191](https://github.com/eai04191)
* [d3vgru](https://github.com/d3vgru) * [d3vgru](https://github.com/d3vgru)
* [Elizafox](https://github.com/Elizafox) * [Elizafox](https://github.com/Elizafox)
* [ericblade](https://github.com/ericblade) * [ericblade](https://github.com/ericblade)
* [mikoim](https://github.com/mikoim) * [mikoim](https://github.com/mikoim)
* [espenronnevik](https://github.com/espenronnevik)
* [Finariel](https://github.com/Finariel)
* [siuying](https://github.com/siuying) * [siuying](https://github.com/siuying)
* [GenbuHase](https://github.com/GenbuHase)
* [hattori6789](https://github.com/hattori6789) * [hattori6789](https://github.com/hattori6789)
* [algernon](https://github.com/algernon) * [algernon](https://github.com/algernon)
* [Fastbyte01](https://github.com/Fastbyte01) * [Fastbyte01](https://github.com/Fastbyte01)
@ -350,62 +283,52 @@ and provided thanks to the work of the following contributors:
* [Fiaxhs](https://github.com/Fiaxhs) * [Fiaxhs](https://github.com/Fiaxhs)
* [reedcourty](https://github.com/reedcourty) * [reedcourty](https://github.com/reedcourty)
* [anneau](https://github.com/anneau) * [anneau](https://github.com/anneau)
* [lanodan](https://github.com/lanodan)
* [Harmon758](https://github.com/Harmon758)
* [HellPie](https://github.com/HellPie) * [HellPie](https://github.com/HellPie)
* [Habu-Kagumba](https://github.com/Habu-Kagumba) * [Habu-Kagumba](https://github.com/Habu-Kagumba)
* [hinaloe](https://github.com/hinaloe)
* [suzukaze](https://github.com/suzukaze) * [suzukaze](https://github.com/suzukaze)
* [Hiromi-Kai](https://github.com/Hiromi-Kai) * [Hiromi-Kai](https://github.com/Hiromi-Kai)
* [hishamhm](https://github.com/hishamhm)
* [musashino205](https://github.com/musashino205) * [musashino205](https://github.com/musashino205)
* [iwaim](https://github.com/iwaim) * [iwaim](https://github.com/iwaim)
* [valrus](https://github.com/valrus) * [valrus](https://github.com/valrus)
* [IMcD23](https://github.com/IMcD23) * [IMcD23](https://github.com/IMcD23)
* [yi0713](https://github.com/yi0713) * [yi0713](https://github.com/yi0713)
* [immae](https://github.com/immae)
* [iblech](https://github.com/iblech) * [iblech](https://github.com/iblech)
* [usbsnowcrash](https://github.com/usbsnowcrash)
* [jack-michaud](https://github.com/jack-michaud) * [jack-michaud](https://github.com/jack-michaud)
* [Floppy](https://github.com/Floppy) * [Floppy](https://github.com/Floppy)
* [loomchild](https://github.com/loomchild) * [loomchild](https://github.com/loomchild)
* [jenkr55](https://github.com/jenkr55) * [docjkl](https://github.com/docjkl)
* [press5](https://github.com/press5)
* [TrollDecker](https://github.com/TrollDecker) * [TrollDecker](https://github.com/TrollDecker)
* [jmontane](https://github.com/jmontane) * [jmontane](https://github.com/jmontane)
* [jonathanklee](https://github.com/jonathanklee) * [jonathanklee](https://github.com/jonathanklee)
* [jguerder](https://github.com/jguerder) * [jguerder](https://github.com/jguerder)
* [Jehops](https://github.com/Jehops) * [Jehops](https://github.com/Jehops)
* [joshuap](https://github.com/joshuap) * [joshuap](https://github.com/joshuap)
* [YuleZ](https://github.com/YuleZ)
* [Tiwy57](https://github.com/Tiwy57) * [Tiwy57](https://github.com/Tiwy57)
* [xuv](https://github.com/xuv) * [xuv](https://github.com/xuv)
* [Jnsll](https://github.com/Jnsll) * [Jnsll](https://github.com/Jnsll)
* [j0k3r](https://github.com/j0k3r) * [j0k3r](https://github.com/j0k3r)
* [KEINOS](https://github.com/KEINOS) * [KEINOS](https://github.com/KEINOS)
* [futoase](https://github.com/futoase) * [futoase](https://github.com/futoase)
* [Pneumaticat](https://github.com/Pneumaticat) * [abjectio](https://github.com/abjectio)
* [Kit Redgrave](mailto:qwertyitis@gmail.com)
* [Knut Erik](mailto:abjectio@users.noreply.github.com)
* [mkody](https://github.com/mkody) * [mkody](https://github.com/mkody)
* [connyduck](https://github.com/connyduck)
* [k0ta0uchi](https://github.com/k0ta0uchi) * [k0ta0uchi](https://github.com/k0ta0uchi)
* [KrzysiekJ](https://github.com/KrzysiekJ) * [KrzysiekJ](https://github.com/KrzysiekJ)
* [leowzukw](https://github.com/leowzukw) * [leowzukw](https://github.com/leowzukw)
* [lmorchard](https://github.com/lmorchard) * [lmorchard](https://github.com/lmorchard)
* [Tak](https://github.com/Tak)
* [cacheflow](https://github.com/cacheflow) * [cacheflow](https://github.com/cacheflow)
* [ldidry](https://github.com/ldidry) * [ldidry](https://github.com/ldidry)
* [jemus42](https://github.com/jemus42) * [jemus42](https://github.com/jemus42)
* [lfuelling](https://github.com/lfuelling) * [lfuelling](https://github.com/lfuelling)
* [Grabacr07](https://github.com/Grabacr07) * [Grabacr07](https://github.com/Grabacr07)
* [mistermantas](https://github.com/mistermantas) * [mistermantas](https://github.com/mistermantas)
* [mareklach](https://github.com/mareklach)
* [wirehack7](https://github.com/wirehack7) * [wirehack7](https://github.com/wirehack7)
* [martymcguire](https://github.com/martymcguire)
* [marvinkopf](https://github.com/marvinkopf) * [marvinkopf](https://github.com/marvinkopf)
* [otsune](https://github.com/otsune) * [otsune](https://github.com/otsune)
* [Mathias B](mailto:10813340+mathias-b@users.noreply.github.com) * [m-blc](https://github.com/m-blc)
* [matt-auckland](https://github.com/matt-auckland) * [matt-auckland](https://github.com/matt-auckland)
* [webroo](https://github.com/webroo)
* [matthiasbeyer](https://github.com/matthiasbeyer)
* [mattjmattj](https://github.com/mattjmattj) * [mattjmattj](https://github.com/mattjmattj)
* [mtparet](https://github.com/mtparet) * [mtparet](https://github.com/mtparet)
* [maximeborges](https://github.com/maximeborges) * [maximeborges](https://github.com/maximeborges)
@ -413,20 +336,16 @@ and provided thanks to the work of the following contributors:
* [michaeljdeeb](https://github.com/michaeljdeeb) * [michaeljdeeb](https://github.com/michaeljdeeb)
* [Themimitoof](https://github.com/Themimitoof) * [Themimitoof](https://github.com/Themimitoof)
* [cyweo](https://github.com/cyweo) * [cyweo](https://github.com/cyweo)
* [Midgard](mailto:m1dgard@users.noreply.github.com) * [M1dgard](https://github.com/M1dgard)
* [mike-burns](https://github.com/mike-burns) * [mike-burns](https://github.com/mike-burns)
* [verymilan](https://github.com/verymilan) * [verymilan](https://github.com/verymilan)
* [milmazz](https://github.com/milmazz) * [milmazz](https://github.com/milmazz)
* [premist](https://github.com/premist)
* [Mnkai](https://github.com/Mnkai) * [Mnkai](https://github.com/Mnkai)
* [mitchhentges](https://github.com/mitchhentges) * [mitchhentges](https://github.com/mitchhentges)
* [moritzheiber](https://github.com/moritzheiber) * [moritzheiber](https://github.com/moritzheiber)
* [mouse-reeve](https://github.com/mouse-reeve) * [mouse-reeve](https://github.com/mouse-reeve)
* [Mozinet-fr](https://github.com/Mozinet-fr)
* [lae](https://github.com/lae) * [lae](https://github.com/lae)
* [Nanamachi](https://github.com/Nanamachi) * [Nanamachi](https://github.com/Nanamachi)
* [orinthe](https://github.com/orinthe)
* [Dar13](https://github.com/Dar13)
* [ngerakines](https://github.com/ngerakines) * [ngerakines](https://github.com/ngerakines)
* [vonneudeck](https://github.com/vonneudeck) * [vonneudeck](https://github.com/vonneudeck)
* [Ninetailed](https://github.com/Ninetailed) * [Ninetailed](https://github.com/Ninetailed)
@ -436,23 +355,18 @@ and provided thanks to the work of the following contributors:
* [norayr](https://github.com/norayr) * [norayr](https://github.com/norayr)
* [joyeusenoelle](https://github.com/joyeusenoelle) * [joyeusenoelle](https://github.com/joyeusenoelle)
* [OlivierNicole](https://github.com/OlivierNicole) * [OlivierNicole](https://github.com/OlivierNicole)
* [noppa](https://github.com/noppa)
* [Otakan951](https://github.com/Otakan951) * [Otakan951](https://github.com/Otakan951)
* [fahy](https://github.com/fahy) * [fahy](https://github.com/fahy)
* [PatrickRWells](https://github.com/PatrickRWells)
* [Pangoraw](https://github.com/Pangoraw) * [Pangoraw](https://github.com/Pangoraw)
* [pwoolcoc](https://github.com/pwoolcoc)
* [peterkeen](https://github.com/peterkeen) * [peterkeen](https://github.com/peterkeen)
* [pgate](https://github.com/pgate) * [petzah](https://github.com/petzah)
* [remram44](https://github.com/remram44) * [ignisf](https://github.com/ignisf)
* [retokromer](https://github.com/retokromer)
* [rfwatson](https://github.com/rfwatson) * [rfwatson](https://github.com/rfwatson)
* [rfreebern](https://github.com/rfreebern) * [rfreebern](https://github.com/rfreebern)
* [Ryan Wade](mailto:ryan.wade@protonmail.com)
* [sylph01](https://github.com/sylph01) * [sylph01](https://github.com/sylph01)
* [S-H-GAMELINKS](https://github.com/S-H-GAMELINKS)
* [staticsafe](https://github.com/staticsafe) * [staticsafe](https://github.com/staticsafe)
* [snwh](https://github.com/snwh) * [snwh](https://github.com/snwh)
* [sts10](https://github.com/sts10)
* [skoji](https://github.com/skoji) * [skoji](https://github.com/skoji)
* [ScienJus](https://github.com/ScienJus) * [ScienJus](https://github.com/ScienJus)
* [larkinscott](https://github.com/larkinscott) * [larkinscott](https://github.com/larkinscott)
@ -464,103 +378,73 @@ and provided thanks to the work of the following contributors:
* [ernix](https://github.com/ernix) * [ernix](https://github.com/ernix)
* [rosylilly](https://github.com/rosylilly) * [rosylilly](https://github.com/rosylilly)
* [shouko](https://github.com/shouko) * [shouko](https://github.com/shouko)
* [Sina Mashek](mailto:sina@mashek.xyz)
* [sossii](https://github.com/sossii) * [sossii](https://github.com/sossii)
* [Spanky](mailto:2788886+spankyworks@users.noreply.github.com) * [StefOfficiel](https://github.com/StefOfficiel)
* [StefOfficiel](mailto:pichard.stephane@free.fr) * [svetlik](https://github.com/svetlik)
* [Svetlozar Todorov](mailto:svetlik@users.noreply.github.com) * [dereckson](https://github.com/dereckson)
* [Sébastien Santoro](mailto:dereckson@espace-win.org) * [theboss](https://github.com/theboss)
* [Tad Thorley](mailto:phaedryx@users.noreply.github.com) * [takp](https://github.com/takp)
* [Takayoshi Nishida](mailto:takayoshi.nishida@gmail.com) * [tkusano](https://github.com/tkusano)
* [Takayuki KUSANO](mailto:github@tkusano.jp) * [TheInventrix](https://github.com/TheInventrix)
* [TakesxiSximada](mailto:takesxi.sximada@gmail.com) * [shug0](https://github.com/shug0)
* [TheInventrix](mailto:theinventrix@users.noreply.github.com) * [Fortyseven](https://github.com/Fortyseven)
* [Thomas Alberola](mailto:thomas@needacoffee.fr) * [tobypinder](https://github.com/tobypinder)
* [Toby Deshane](mailto:fortyseven@users.noreply.github.com) * [tomosm](https://github.com/tomosm)
* [Toby Pinder](mailto:gigitrix@gmail.com) * [TomoyaShibata](https://github.com/TomoyaShibata)
* [Tomonori Murakami](mailto:crosslife777@gmail.com) * [TrashMacNugget](https://github.com/TrashMacNugget)
* [TomoyaShibata](mailto:wind.of.hometown@gmail.com) * [treyssatvincent](https://github.com/treyssatvincent)
* [Treyssat-Vincent Nino](mailto:treyssatvincent@users.noreply.github.com) * [optikfluffel](https://github.com/optikfluffel)
* [Udo Kramer](mailto:optik@fluffel.io) * [vmincev](https://github.com/vmincev)
* [Una](mailto:una@unascribed.com) * [waldyrious](https://github.com/waldyrious)
* [Ushitora Anqou](mailto:ushitora_anqou@yahoo.co.jp) * [tahnok](https://github.com/tahnok)
* [Valentin Lorentz](mailto:progval+git@progval.net) * [YDrogen](https://github.com/YDrogen)
* [Vladimir Mincev](mailto:vladimir@canicinteractive.com) * [YOSHIOKAEiichiro](https://github.com/YOSHIOKAEiichiro)
* [Waldir Pimenta](mailto:waldyrious@gmail.com) * [S-YOU](https://github.com/S-YOU)
* [Wesley Ellis](mailto:tahnok@gmail.com) * [YaQ00](https://github.com/YaQ00)
* [Wiktor](mailto:wiktor@metacode.biz) * [yanakend](https://github.com/yanakend)
* [Wonderfall](mailto:wonderfall@schrodinger.io) * [orzFly](https://github.com/orzFly)
* [YDrogen](mailto:ydrogen45@gmail.com) * [chansuke](https://github.com/chansuke)
* [YMHuang](mailto:ymhuang@fmbase.tw) * [yuntan](https://github.com/yuntan)
* [YOSHIOKA Eiichiro](mailto:yoshioka.eiichiro@gmail.com) * [LogicalDash](https://github.com/LogicalDash)
* [YOU](mailto:stackexchange.you@gmail.com) * [ZiiX](https://github.com/ZiiX)
* [YaQ](mailto:i_k_o_m_a_7@yahoo.co.jp) * [benklop](https://github.com/benklop)
* [Yanaken](mailto:yanakend@gmail.com) * [caasi](https://github.com/caasi)
* [Yann Klis](mailto:yann.klis@gmail.com) * [caesarologia](https://github.com/caesarologia)
* [Yeechan Lu](mailto:wz.bluesnow@gmail.com) * [chrolis](https://github.com/chrolis)
* [Yusuke Abe](mailto:moonset20@gmail.com) * [cormojs](https://github.com/cormojs)
* [Zachary Spector](mailto:logicaldash@gmail.com) * [cpsdqs](https://github.com/cpsdqs)
* [ZiiX](mailto:ziix@users.noreply.github.com) * [d0p1s4m4](https://github.com/d0p1s4m4)
* [asria-jp](mailto:is@alicematic.com) * [evilny0](https://github.com/evilny0)
* [ava](mailto:vladooku@users.noreply.github.com) * [febrezo](https://github.com/febrezo)
* [benklop](mailto:benklop@gmail.com) * [fsubal](https://github.com/fsubal)
* [bsky](mailto:git@imbsky.net) * [dikky1218](https://github.com/dikky1218)
* [caesarologia](mailto:lopesgemelli.1@gmail.com) * [gentarok](https://github.com/gentarok)
* [cbayerlein](mailto:c.bayerlein@gmail.com) * [hakoai](https://github.com/hakoai)
* [chrolis](mailto:chrolis@users.noreply.github.com) * [chaosbunker](https://github.com/chaosbunker)
* [cormo](mailto:cormorant2+github@gmail.com) * [isati](https://github.com/isati)
* [d0p1](mailto:dopi-sama@hush.com) * [jkap](https://github.com/jkap)
* [evilny0](mailto:evilny0@moomoocamp.net) * [jirayudech](https://github.com/jirayudech)
* [febrezo](mailto:felixbrezo@gmail.com) * [jukper](https://github.com/jukper)
* [fsubal](mailto:fsubal@users.noreply.github.com) * [karlyeurl](https://github.com/karlyeurl)
* [fusshi-](mailto:dikky1218@users.noreply.github.com) * [kedamaDQ](https://github.com/kedamaDQ)
* [gentaro](mailto:gentaroooo@gmail.com) * [kuro5hin](https://github.com/kuro5hin)
* [hakoai](mailto:hk--76@qa2.so-net.ne.jp) * [maxypy](https://github.com/maxypy)
* [haosbvnker](mailto:github@chaosbunker.com) * [marcus-herrmann](https://github.com/marcus-herrmann)
* [isati](mailto:phil@juchnowi.cz) * [mshrtkch](https://github.com/mshrtkch)
* [jacob](mailto:jacobherringtondeveloper@gmail.com) * [muan](https://github.com/muan)
* [jenn kaplan](mailto:me@jkap.io) * [rch850](https://github.com/rch850)
* [jirayudech](mailto:jirayudech@gmail.com) * [roikale](https://github.com/roikale)
* [jooops](mailto:joops@autistici.org) * [rysiekpl](https://github.com/rysiekpl)
* [jukper](mailto:jukkaperanto@gmail.com) * [saturday06](https://github.com/saturday06)
* [jumoru](mailto:jumoru@mailbox.org) * [scriptjunkie](https://github.com/scriptjunkie)
* [karlyeurl](mailto:karl.yeurl@gmail.com) * [seekr](https://github.com/seekr)
* [kedama](mailto:32974885+kedamadq@users.noreply.github.com) * [syui](https://github.com/syui)
* [kuro5hin](mailto:rusty@kuro5hin.org) * [tackeyy](https://github.com/tackeyy)
* [luzpaz](mailto:luzpaz@users.noreply.github.com) * [tmyt](https://github.com/tmyt)
* [maxypy](mailto:maxime@mpigou.fr) * [utam0k](https://github.com/utam0k)
* [mhe](mailto:mail@marcus-herrmann.com) * [vpzomtrrfrt](https://github.com/vpzomtrrfrt)
* [mimikun](mailto:dzdzble_effort_311@outlook.jp) * [walfie](https://github.com/walfie)
* [mshrtkch](mailto:mshrtkch@users.noreply.github.com) * [y-temp4](https://github.com/y-temp4)
* [muan](mailto:muan@github.com) * [ymmtmdk](https://github.com/ymmtmdk)
* [neetshin](mailto:neetshin@neetsh.in)
* [nightpool](mailto:nightpool@users.noreply.github.com)
* [rch850](mailto:rich850@gmail.com)
* [roikale](mailto:roikale@users.noreply.github.com)
* [rysiekpl](mailto:rysiek@hackerspace.pl)
* [saturday06](mailto:dyob@lunaport.net)
* [scriptjunkie](mailto:scriptjunkie@scriptjunkie.us)
* [seekr](mailto:mario.drs@gmail.com)
* [sundevour](mailto:31990469+sundevour@users.noreply.github.com)
* [syui](mailto:syui@users.noreply.github.com)
* [tackeyy](mailto:mailto.takita.yusuke@gmail.com)
* [tateisu](mailto:tateisu@gmail.com)
* [tmyt](mailto:shigure@refy.net)
* [trevDev()](mailto:trev@trevdev.ca)
* [utam0k](mailto:k0ma@utam0k.jp)
* [vpzomtrrfrt](mailto:vpzomtrrfrt@gmail.com)
* [walfie](mailto:walfington@gmail.com)
* [y-temp4](mailto:y.temp4@gmail.com)
* [ymmtmdk](mailto:ymmtmdk@gmail.com)
* [yoshipc](mailto:yoooo@yoshipc.net)
* [Özcan Zafer AYAN](mailto:ozcanzaferayan@gmail.com)
* [ばん](mailto:detteiu0321@gmail.com)
* [みたらしだんご](mailto:mitarashidango@users.noreply.github.com)
* [りんすき](mailto:6533808+rinsuki@users.noreply.github.com)
* [ヨイツの賢狼ホロ | 3rd style](mailto:horo@yoitsu.moe)
* [猫吸血鬼ディフリス / 猫ロキP](mailto:deflis@gmail.com)
* [艮 鮟鱇](mailto:ushitora_anqou@yahoo.co.jp)
* [西小倉宏信](mailto:nishiko@mindia.jp)
* [雨宮美羽](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. 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.

19
Aptfile
View File

@ -5,25 +5,6 @@ libidn11
libidn11-dev libidn11-dev
libpq-dev libpq-dev
libprotobuf-dev libprotobuf-dev
libssl-dev
libxdamage1 libxdamage1
libxfixes3 libxfixes3
protobuf-compiler protobuf-compiler
zlib1g-dev
libcairo2
libcroco3
libdatrie1
libgdk-pixbuf2.0-0
libgraphite2-3
libharfbuzz0b
libpango-1.0-0
libpangocairo-1.0-0
libpangoft2-1.0-0
libpixman-1-0
librsvg2-2
libthai-data
libthai0
libvpx5
libxcb-render0
libxcb-shm0
libxrender1

View File

@ -1,134 +0,0 @@
Changelog
=========
All notable changes to this project will be documented in this file.
## [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)
## [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)
### 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)
### 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)
### Removed
- Remove "on this device" label in column push settings (#8704)
- Remove rake tasks in favour of tootctl commands (#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)
## [2.5.2] - 2018-10-12
### Security
- Fix XSS vulnerability (#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)
### 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)

View File

@ -1,37 +1,56 @@
Contributing CONTRIBUTING
============ ============
Thank you for considering contributing to Mastodon 🐘 There are three ways in which you can contribute to this repository:
You can contribute in the following ways: 1. By improving the documentation
2. By working on the back-end application
3. By working on the front-end application
- Finding and reporting bugs Choosing what to work on in a large open source project is not easy. The list of [GitHub issues](https://github.com/tootsuite/mastodon/issues) may provide some ideas, but not every feature request has been greenlit. Likewise, not every change or feature that resolves a personal itch will be merged into the main repository. Some communication ahead of time may be wise. If your addition creates a new feature or setting, or otherwise changes how things work in some substantial way, please remember to submit a correlating pull request to document your changes in the [documentation](http://github.com/tootsuite/documentation).
- Translating the Mastodon interface into various languages
- Contributing code to Mastodon by fixing bugs or implementing features
- Improving the documentation
## Bug reports Below are the guidelines for working on pull requests:
Bug reports and feature suggestions can be submitted to [GitHub Issues](https://github.com/tootsuite/mastodon/issues). Please make sure that you are not submitting duplicates, and that a similar report or request has not already been resolved or rejected in the past using the search function. Please also use descriptive, concise titles. ## General
## Translations - 2 spaces indentation
You can submit translations via [Weblate](https://weblate.joinmastodon.org/). They are periodically merged into the codebase.
[![Mastodon translation statistics by language](https://weblate.joinmastodon.org/widgets/mastodon/-/multi-auto.svg)](https://weblate.joinmastodon.org/)
## Pull requests
Please use clean, concise titles for your pull requests. We use commit squashing, so the final commit in the master branch will carry the title of the pull request.
The smaller the set of changes in the pull request is, the quicker it can be reviewed and merged. Splitting tasks into multiple smaller pull requests is often preferable.
**Pull requests that do not pass automated checks may not be reviewed**. In particular, you need to keep in mind:
- Unit and integration tests (rspec, jest)
- Code style rules (rubocop, eslint)
- Normalization of locale files (i18n-tasks)
## Documentation ## Documentation
The [Mastodon documentation](https://docs.joinmastodon.org) is a statically generated site. You can [submit merge requests to mastodon/docs](https://source.joinmastodon.org/mastodon/docs). - No spelling mistakes
- No orthographic mistakes
- No Markdown syntax errors
## Requirements
- Ruby
- Node.js
- PostgreSQL
- Redis
- Nginx (optional)
## Back-end application
It is expected that you have a working development environment set up. The development environment includes [rubocop](https://github.com/bbatsov/rubocop), which checks your Ruby code for compliance with our style guide and best practices. Sublime Text, likely like other editors, has a [Rubocop plugin](https://github.com/pderichs/sublime_rubocop) that runs checks on files as you edit them. The codebase also has a test suite.
* The codebase is not perfect, at the time of writing, but it is expected that you do not introduce new code style violations
* The rspec test suite must pass
* To the extent that it is possible, verify your changes. In the best case, by adding new tests to the test suite. At the very least, by running the server or console and checking it manually
* If you are introducing new strings to the user interface, they must be using localization methods
If your code has syntax errors that won't let it run, it's a good sign that the pull request isn't ready for submission yet.
## Front-end application
It is expected that you have a working development environment set up (see back-end application section). This project includes an ESLint configuration file, with which you can lint your changes.
* Avoid grave ESLint violations
* Verify that your changes work
* If you are introducing new strings, they must be using localization methods
If the JavaScript or CSS assets won't compile due to a syntax error, it's a good sign that the pull request isn't ready for submission yet.
## Translate
You can contribute to translating Mastodon via Weblate at [weblate.joinmastodon.org](https://weblate.joinmastodon.org/).
[![Mastodon translation statistics by language](https://weblate.joinmastodon.org/widgets/mastodon/-/multi-auto.svg)](https://weblate.joinmastodon.org/)

View File

@ -1,5 +1,4 @@
FROM node:8.12.0-alpine as node FROM ruby:2.4.4-alpine3.6
FROM ruby:2.4.5-alpine3.8
LABEL maintainer="https://github.com/tootsuite/mastodon" \ LABEL maintainer="https://github.com/tootsuite/mastodon" \
description="Your self-hosted, globally interconnected microblogging community" description="Your self-hosted, globally interconnected microblogging community"
@ -12,6 +11,8 @@ ENV PATH=/mastodon/bin:$PATH \
RAILS_ENV=production \ RAILS_ENV=production \
NODE_ENV=production NODE_ENV=production
ARG YARN_VERSION=1.3.2
ARG YARN_DOWNLOAD_SHA256=6cfe82e530ef0837212f13e45c1565ba53f5199eec2527b85ecbcd88bf26821d
ARG LIBICONV_VERSION=1.15 ARG LIBICONV_VERSION=1.15
ARG LIBICONV_DOWNLOAD_SHA256=ccf536620a45458d26ba83887a983b96827001e92a13847b45e4925cc8913178 ARG LIBICONV_DOWNLOAD_SHA256=ccf536620a45458d26ba83887a983b96827001e92a13847b45e4925cc8913178
@ -19,11 +20,6 @@ EXPOSE 3000 4000
WORKDIR /mastodon WORKDIR /mastodon
COPY --from=node /usr/local/bin/node /usr/local/bin/node
COPY --from=node /usr/local/lib/node_modules /usr/local/lib/node_modules
COPY --from=node /usr/local/bin/npm /usr/local/bin/npm
COPY --from=node /opt/yarn-* /opt/yarn
RUN apk -U upgrade \ RUN apk -U upgrade \
&& apk add -t build-dependencies \ && apk add -t build-dependencies \
build-base \ build-base \
@ -43,13 +39,20 @@ RUN apk -U upgrade \
imagemagick \ imagemagick \
libidn \ libidn \
libpq \ libpq \
nodejs \
nodejs-npm \
protobuf \ protobuf \
tini \ tini \
tzdata \ tzdata \
&& update-ca-certificates \ && update-ca-certificates \
&& mkdir -p /tmp/src /opt \
&& wget -O yarn.tar.gz "https://github.com/yarnpkg/yarn/releases/download/v$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \
&& echo "$YARN_DOWNLOAD_SHA256 *yarn.tar.gz" | sha256sum -c - \
&& tar -xzf yarn.tar.gz -C /tmp/src \
&& rm yarn.tar.gz \
&& mv /tmp/src/yarn-v$YARN_VERSION /opt/yarn \
&& ln -s /opt/yarn/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn/bin/yarn /usr/local/bin/yarn \
&& ln -s /opt/yarn/bin/yarnpkg /usr/local/bin/yarnpkg \ && ln -s /opt/yarn/bin/yarnpkg /usr/local/bin/yarnpkg \
&& mkdir -p /tmp/src /opt \
&& wget -O libiconv.tar.gz "https://ftp.gnu.org/pub/gnu/libiconv/libiconv-$LIBICONV_VERSION.tar.gz" \ && wget -O libiconv.tar.gz "https://ftp.gnu.org/pub/gnu/libiconv/libiconv-$LIBICONV_VERSION.tar.gz" \
&& echo "$LIBICONV_DOWNLOAD_SHA256 *libiconv.tar.gz" | sha256sum -c - \ && echo "$LIBICONV_DOWNLOAD_SHA256 *libiconv.tar.gz" | sha256sum -c - \
&& tar -xzf libiconv.tar.gz -C /tmp/src \ && tar -xzf libiconv.tar.gz -C /tmp/src \
@ -66,7 +69,7 @@ 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 --with-iconv-lib=/usr/local/lib --with-iconv-include=/usr/local/include \
&& bundle install -j$(getconf _NPROCESSORS_ONLN) --deployment --without test development \ && bundle install -j$(getconf _NPROCESSORS_ONLN) --deployment --without test development \
&& yarn install --pure-lockfile --ignore-engines \ && yarn --pure-lockfile \
&& yarn cache clean && yarn cache clean
RUN addgroup -g ${GID} mastodon && adduser -h /mastodon -s /bin/sh -D -G mastodon -u ${UID} mastodon \ RUN addgroup -g ${GID} mastodon && adduser -h /mastodon -s /bin/sh -D -G mastodon -u ${UID} mastodon \
@ -77,10 +80,8 @@ COPY . /mastodon
RUN chown -R mastodon:mastodon /mastodon RUN chown -R mastodon:mastodon /mastodon
VOLUME /mastodon/public/system VOLUME /mastodon/public/system /mastodon/public/assets /mastodon/public/packs
USER mastodon USER mastodon
RUN OTP_SECRET=precompile_placeholder SECRET_KEY_BASE=precompile_placeholder bundle exec rails assets:precompile
ENTRYPOINT ["/sbin/tini", "--"] ENTRYPOINT ["/sbin/tini", "--"]

78
Gemfile
View File

@ -5,36 +5,35 @@ ruby '>= 2.3.0', '< 2.6.0'
gem 'pkg-config', '~> 1.3' gem 'pkg-config', '~> 1.3'
gem 'puma', '~> 3.12' gem 'puma', '~> 3.11'
gem 'rails', '~> 5.2.1' gem 'rails', '~> 5.2.0'
gem 'thor', '~> 0.20'
gem 'hamlit-rails', '~> 0.2' gem 'hamlit-rails', '~> 0.2'
gem 'pg', '~> 1.1' gem 'pg', '~> 1.0'
gem 'makara', '~> 0.4' gem 'pghero', '~> 2.1'
gem 'pghero', '~> 2.2' gem 'dotenv-rails', '~> 2.2', '< 2.3'
gem 'dotenv-rails', '~> 2.5'
gem 'aws-sdk-s3', '~> 1.23', require: false gem 'aws-sdk-s3', '~> 1.9', require: false
gem 'fog-core', '<= 2.1.0' gem 'fog-core', '~> 1.45'
gem 'fog-openstack', '~> 0.3', require: false gem 'fog-local', '~> 0.5', require: false
gem 'fog-openstack', '~> 0.1', require: false
gem 'paperclip', '~> 6.0' gem 'paperclip', '~> 6.0'
gem 'paperclip-av-transcoder', '~> 0.6' gem 'paperclip-av-transcoder', '~> 0.6'
gem 'streamio-ffmpeg', '~> 3.0' gem 'streamio-ffmpeg', '~> 3.0'
gem 'active_model_serializers', '~> 0.10' gem 'active_model_serializers', '~> 0.10'
gem 'addressable', '~> 2.5' gem 'addressable', '~> 2.5'
gem 'bootsnap', '~> 1.3', require: false gem 'bootsnap', '~> 1.3'
gem 'browser' gem 'browser'
gem 'charlock_holmes', '~> 0.7.6' gem 'charlock_holmes', '~> 0.7.6'
gem 'iso-639' gem 'iso-639'
gem 'chewy', '~> 5.0' gem 'chewy', '~> 5.0'
gem 'cld3', '~> 3.2.0' gem 'cld3', '~> 3.2.0'
gem 'devise', '~> 4.5' gem 'devise', '~> 4.4'
gem 'devise-two-factor', '~> 3.0' gem 'devise-two-factor', '~> 3.0'
group :pam_authentication, optional: true do group :pam_authentication, optional: true do
gem 'devise_pam_authenticatable2', '~> 9.2' gem 'devise_pam_authenticatable2', '~> 9.1'
end end
gem 'net-ldap', '~> 0.10' gem 'net-ldap', '~> 0.10'
@ -42,51 +41,52 @@ gem 'omniauth-cas', '~> 1.1'
gem 'omniauth-saml', '~> 1.10' gem 'omniauth-saml', '~> 1.10'
gem 'omniauth', '~> 1.2' gem 'omniauth', '~> 1.2'
gem 'doorkeeper', '~> 5.0' gem 'doorkeeper', '~> 4.4'
gem 'fast_blank', '~> 1.0' gem 'fast_blank', '~> 1.0'
gem 'fastimage' gem 'fastimage'
gem 'goldfinger', '~> 2.1' gem 'goldfinger', '~> 2.1'
gem 'hiredis', '~> 0.6' gem 'hiredis', '~> 0.6'
gem 'redis-namespace', '~> 1.5' gem 'redis-namespace', '~> 1.5'
gem 'htmlentities', '~> 4.3' gem 'htmlentities', '~> 4.3'
gem 'http', '~> 3.3' gem 'http', '~> 3.2'
gem 'http_accept_language', '~> 2.1' gem 'http_accept_language', '~> 2.1'
gem 'http_parser.rb', '~> 0.6', git: 'https://github.com/tmm1/http_parser.rb', ref: '54b17ba8c7d8d20a16dfc65d1775241833219cf2' gem 'http_parser.rb', '~> 0.6', git: 'https://github.com/tmm1/http_parser.rb', ref: '54b17ba8c7d8d20a16dfc65d1775241833219cf2'
gem 'httplog', '~> 1.1' gem 'httplog', '~> 1.0'
gem 'idn-ruby', require: 'idn' gem 'idn-ruby', require: 'idn'
gem 'kaminari', '~> 1.1' gem 'kaminari', '~> 1.1'
gem 'link_header', '~> 0.0' gem 'link_header', '~> 0.0'
gem 'mime-types', '~> 3.2', require: 'mime/types/columnar' gem 'mime-types', '~> 3.1', require: 'mime/types/columnar'
gem 'nokogiri', '~> 1.8' gem 'nokogiri', '~> 1.8'
gem 'nsa', '~> 0.2' gem 'nsa', '~> 0.2'
gem 'oj', '~> 3.7' gem 'oj', '~> 3.5'
gem 'ostatus2', '~> 2.0' gem 'ostatus2', '~> 2.0'
gem 'ox', '~> 2.10' gem 'ox', '~> 2.9'
gem 'posix-spawn', git: 'https://github.com/rtomayko/posix-spawn', ref: '58465d2e213991f8afb13b984854a49fcdcc980c' gem 'posix-spawn', git: 'https://github.com/rtomayko/posix-spawn', ref: '58465d2e213991f8afb13b984854a49fcdcc980c'
gem 'pundit', '~> 2.0' gem 'pundit', '~> 1.1'
gem 'premailer-rails' gem 'premailer-rails'
gem 'rack-attack', '~> 5.4' gem 'rack-attack', '~> 5.2'
gem 'rack-cors', '~> 1.0', require: 'rack/cors' gem 'rack-cors', '~> 1.0', require: 'rack/cors'
gem 'rails-i18n', '~> 5.1' gem 'rails-i18n', '~> 5.1'
gem 'rails-settings-cached', '~> 0.6' gem 'rails-settings-cached', '~> 0.6'
gem 'redis', '~> 4.0', require: ['redis', 'redis/connection/hiredis'] gem 'redis', '~> 4.0', require: ['redis', 'redis/connection/hiredis']
gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock' gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
gem 'rqrcode', '~> 0.10' gem 'rqrcode', '~> 0.10'
gem 'sanitize', '~> 5.0' gem 'ruby-progressbar', '~> 1.4'
gem 'sidekiq', '~> 5.2' gem 'sanitize', '~> 4.6'
gem 'sidekiq-scheduler', '~> 3.0' gem 'sidekiq', '~> 5.1'
gem 'sidekiq-scheduler', '~> 2.2'
gem 'sidekiq-unique-jobs', '~> 5.0' gem 'sidekiq-unique-jobs', '~> 5.0'
gem 'sidekiq-bulk', '~>0.1.1' gem 'sidekiq-bulk', '~>0.1.1'
gem 'simple-navigation', '~> 4.0' gem 'simple-navigation', '~> 4.0'
gem 'simple_form', '~> 4.0' gem 'simple_form', '~> 4.0'
gem 'sprockets-rails', '~> 3.2', require: 'sprockets/railtie' gem 'sprockets-rails', '~> 3.2', require: 'sprockets/railtie'
gem 'stoplight', '~> 2.1.3' gem 'stoplight', '~> 2.1.3'
gem 'strong_migrations', '~> 0.3' gem 'strong_migrations', '~> 0.2'
gem 'tty-command', '~> 0.8', require: false gem 'tty-command', '~> 0.8', require: false
gem 'tty-prompt', '~> 0.17', require: false gem 'tty-prompt', '~> 0.16', require: false
gem 'twitter-text', '~> 1.14' gem 'twitter-text', '~> 1.14'
gem 'tzinfo-data', '~> 1.2018' gem 'tzinfo-data', '~> 1.2018'
gem 'webpacker', '~> 3.5' gem 'webpacker', '~> 3.4'
gem 'webpush' gem 'webpush'
gem 'json-ld', '~> 2.2' gem 'json-ld', '~> 2.2'
@ -94,45 +94,45 @@ gem 'rdf-normalize', '~> 0.3'
group :development, :test do group :development, :test do
gem 'fabrication', '~> 2.20' gem 'fabrication', '~> 2.20'
gem 'fuubar', '~> 2.3' gem 'fuubar', '~> 2.2'
gem 'i18n-tasks', '~> 0.9', require: false gem 'i18n-tasks', '~> 0.9', require: false
gem 'pry-byebug', '~> 3.6' gem 'pry-byebug', '~> 3.6'
gem 'pry-rails', '~> 0.3' gem 'pry-rails', '~> 0.3'
gem 'rspec-rails', '~> 3.8' gem 'rspec-rails', '~> 3.7'
end end
group :production, :test do group :production, :test do
gem 'private_address_check', '~> 0.5' gem 'private_address_check', '~> 0.4.1'
end end
group :test do group :test do
gem 'capybara', '~> 3.10' gem 'capybara', '~> 2.18'
gem 'climate_control', '~> 0.2' gem 'climate_control', '~> 0.2'
gem 'faker', '~> 1.9' gem 'faker', '~> 1.8'
gem 'microformats', '~> 4.0' gem 'microformats', '~> 4.0'
gem 'rails-controller-testing', '~> 1.0' gem 'rails-controller-testing', '~> 1.0'
gem 'rspec-sidekiq', '~> 3.0' gem 'rspec-sidekiq', '~> 3.0'
gem 'simplecov', '~> 0.16', require: false gem 'simplecov', '~> 0.16', require: false
gem 'webmock', '~> 3.4' gem 'webmock', '~> 3.3'
gem 'parallel_tests', '~> 2.26' gem 'parallel_tests', '~> 2.21'
end end
group :development do group :development do
gem 'active_record_query_trace', '~> 1.5' gem 'active_record_query_trace', '~> 1.5'
gem 'annotate', '~> 2.7' gem 'annotate', '~> 2.7'
gem 'better_errors', '~> 2.5' gem 'better_errors', '~> 2.4'
gem 'binding_of_caller', '~> 0.7' gem 'binding_of_caller', '~> 0.7'
gem 'bullet', '~> 5.7' gem 'bullet', '~> 5.7'
gem 'letter_opener', '~> 1.4' gem 'letter_opener', '~> 1.4'
gem 'letter_opener_web', '~> 1.3' gem 'letter_opener_web', '~> 1.3'
gem 'memory_profiler' gem 'memory_profiler'
gem 'rubocop', '~> 0.60', require: false gem 'rubocop', '~> 0.55', require: false
gem 'brakeman', '~> 4.3', require: false gem 'brakeman', '~> 4.2', require: false
gem 'bundler-audit', '~> 0.6', require: false gem 'bundler-audit', '~> 0.6', require: false
gem 'scss_lint', '~> 0.57', require: false gem 'scss_lint', '~> 0.57', require: false
gem 'capistrano', '~> 3.11' gem 'capistrano', '~> 3.10'
gem 'capistrano-rails', '~> 1.4' gem 'capistrano-rails', '~> 1.3'
gem 'capistrano-rbenv', '~> 2.1' gem 'capistrano-rbenv', '~> 2.1'
gem 'capistrano-yarn', '~> 2.0' gem 'capistrano-yarn', '~> 2.0'

View File

@ -15,25 +15,25 @@ GIT
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
actioncable (5.2.1) actioncable (5.2.0)
actionpack (= 5.2.1) actionpack (= 5.2.0)
nio4r (~> 2.0) nio4r (~> 2.0)
websocket-driver (>= 0.6.1) websocket-driver (>= 0.6.1)
actionmailer (5.2.1) actionmailer (5.2.0)
actionpack (= 5.2.1) actionpack (= 5.2.0)
actionview (= 5.2.1) actionview (= 5.2.0)
activejob (= 5.2.1) activejob (= 5.2.0)
mail (~> 2.5, >= 2.5.4) mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
actionpack (5.2.1) actionpack (5.2.0)
actionview (= 5.2.1) actionview (= 5.2.0)
activesupport (= 5.2.1) activesupport (= 5.2.0)
rack (~> 2.0) rack (~> 2.0)
rack-test (>= 0.6.3) rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2) rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (5.2.1) actionview (5.2.0)
activesupport (= 5.2.1) activesupport (= 5.2.0)
builder (~> 3.1) builder (~> 3.1)
erubi (~> 1.4) erubi (~> 1.4)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
@ -44,20 +44,20 @@ GEM
case_transform (>= 0.2) case_transform (>= 0.2)
jsonapi-renderer (>= 0.1.1.beta1, < 0.3) jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
active_record_query_trace (1.5.4) active_record_query_trace (1.5.4)
activejob (5.2.1) activejob (5.2.0)
activesupport (= 5.2.1) activesupport (= 5.2.0)
globalid (>= 0.3.6) globalid (>= 0.3.6)
activemodel (5.2.1) activemodel (5.2.0)
activesupport (= 5.2.1) activesupport (= 5.2.0)
activerecord (5.2.1) activerecord (5.2.0)
activemodel (= 5.2.1) activemodel (= 5.2.0)
activesupport (= 5.2.1) activesupport (= 5.2.0)
arel (>= 9.0) arel (>= 9.0)
activestorage (5.2.1) activestorage (5.2.0)
actionpack (= 5.2.1) actionpack (= 5.2.0)
activerecord (= 5.2.1) activerecord (= 5.2.0)
marcel (~> 0.3.1) marcel (~> 0.3.1)
activesupport (5.2.1) activesupport (5.2.0)
concurrent-ruby (~> 1.0, >= 1.0.2) concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2) i18n (>= 0.7, < 2)
minitest (~> 5.1) minitest (~> 5.1)
@ -66,7 +66,7 @@ GEM
public_suffix (>= 2.0.2, < 4.0) public_suffix (>= 2.0.2, < 4.0)
airbrussh (1.3.0) airbrussh (1.3.0)
sshkit (>= 1.6.1, != 1.7.0) sshkit (>= 1.6.1, != 1.7.0)
annotate (2.7.4) annotate (2.7.3)
activerecord (>= 3.2, < 6.0) activerecord (>= 3.2, < 6.0)
rake (>= 10.4, < 13.0) rake (>= 10.4, < 13.0)
arel (9.0.0) arel (9.0.0)
@ -75,42 +75,40 @@ GEM
encryptor (~> 3.0.0) encryptor (~> 3.0.0)
av (0.9.0) av (0.9.0)
cocaine (~> 0.5.3) cocaine (~> 0.5.3)
aws-eventstream (1.0.1) aws-partitions (1.80.0)
aws-partitions (1.106.0) aws-sdk-core (3.19.0)
aws-sdk-core (3.35.0)
aws-eventstream (~> 1.0)
aws-partitions (~> 1.0) aws-partitions (~> 1.0)
aws-sigv4 (~> 1.0) aws-sigv4 (~> 1.0)
jmespath (~> 1.0) jmespath (~> 1.0)
aws-sdk-kms (1.11.0) aws-sdk-kms (1.5.0)
aws-sdk-core (~> 3, >= 3.26.0) aws-sdk-core (~> 3)
aws-sigv4 (~> 1.0) aws-sigv4 (~> 1.0)
aws-sdk-s3 (1.23.0) aws-sdk-s3 (1.9.1)
aws-sdk-core (~> 3, >= 3.26.0) aws-sdk-core (~> 3)
aws-sdk-kms (~> 1) aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.0) aws-sigv4 (~> 1.0)
aws-sigv4 (1.0.3) aws-sigv4 (1.0.2)
bcrypt (3.1.12) bcrypt (3.1.12)
benchmark-ips (2.7.2) benchmark-ips (2.7.2)
better_errors (2.5.0) better_errors (2.4.0)
coderay (>= 1.0.0) coderay (>= 1.0.0)
erubi (>= 1.0.0) erubi (>= 1.0.0)
rack (>= 0.9.0) rack (>= 0.9.0)
binding_of_caller (0.8.0) binding_of_caller (0.8.0)
debug_inspector (>= 0.0.1) debug_inspector (>= 0.0.1)
bootsnap (1.3.2) bootsnap (1.3.0)
msgpack (~> 1.0) msgpack (~> 1.0)
brakeman (4.3.1) brakeman (4.2.1)
browser (2.5.3) browser (2.5.3)
builder (3.2.3) builder (3.2.3)
bullet (5.7.6) bullet (5.7.5)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
uniform_notifier (~> 1.11.0) uniform_notifier (~> 1.11.0)
bundler-audit (0.6.0) bundler-audit (0.6.0)
bundler (~> 1.2) bundler (~> 1.2)
thor (~> 0.18) thor (~> 0.18)
byebug (10.0.2) byebug (10.0.2)
capistrano (3.11.0) capistrano (3.10.2)
airbrussh (>= 1.0.0) airbrussh (>= 1.0.0)
i18n i18n
rake (>= 10.0.0) rake (>= 10.0.0)
@ -118,22 +116,21 @@ GEM
capistrano-bundler (1.3.0) capistrano-bundler (1.3.0)
capistrano (~> 3.1) capistrano (~> 3.1)
sshkit (~> 1.2) sshkit (~> 1.2)
capistrano-rails (1.4.0) capistrano-rails (1.3.1)
capistrano (~> 3.1) capistrano (~> 3.1)
capistrano-bundler (~> 1.1) capistrano-bundler (~> 1.1)
capistrano-rbenv (2.1.4) capistrano-rbenv (2.1.3)
capistrano (~> 3.1) capistrano (~> 3.1)
sshkit (~> 1.3) sshkit (~> 1.3)
capistrano-yarn (2.0.2) capistrano-yarn (2.0.2)
capistrano (~> 3.0) capistrano (~> 3.0)
capybara (3.10.0) capybara (2.18.0)
addressable addressable
mini_mime (>= 0.1.3) mini_mime (>= 0.1.3)
nokogiri (~> 1.8) nokogiri (>= 1.3.3)
rack (>= 1.6.0) rack (>= 1.0.0)
rack-test (>= 0.6.3) rack-test (>= 0.5.4)
regexp_parser (~> 1.2) xpath (>= 2.0, < 4.0)
xpath (~> 3.2)
case_transform (0.2) case_transform (0.2)
activesupport activesupport
charlock_holmes (0.7.6) charlock_holmes (0.7.6)
@ -148,15 +145,16 @@ GEM
cocaine (0.5.8) cocaine (0.5.8)
climate_control (>= 0.0.3, < 1.0) climate_control (>= 0.0.3, < 1.0)
coderay (1.1.2) coderay (1.1.2)
colorize (0.8.1)
concurrent-ruby (1.0.5) concurrent-ruby (1.0.5)
connection_pool (2.2.2) connection_pool (2.2.1)
crack (0.4.3) crack (0.4.3)
safe_yaml (~> 1.0.0) safe_yaml (~> 1.0.0)
crass (1.0.4) crass (1.0.4)
css_parser (1.6.0) css_parser (1.6.0)
addressable addressable
debug_inspector (0.0.3) debug_inspector (0.0.3)
derailed_benchmarks (1.3.5) derailed_benchmarks (1.3.4)
benchmark-ips (~> 2) benchmark-ips (~> 2)
get_process_mem (~> 0) get_process_mem (~> 0)
heapy (~> 0) heapy (~> 0)
@ -164,7 +162,7 @@ GEM
rack (>= 1) rack (>= 1)
rake (> 10, < 13) rake (> 10, < 13)
thor (~> 0.19) thor (~> 0.19)
devise (4.5.0) devise (4.4.3)
bcrypt (~> 3.0) bcrypt (~> 3.0)
orm_adapter (~> 0.1) orm_adapter (~> 0.1)
railties (>= 4.1.0, < 6.0) railties (>= 4.1.0, < 6.0)
@ -176,19 +174,22 @@ GEM
devise (~> 4.0) devise (~> 4.0)
railties (< 5.3) railties (< 5.3)
rotp (~> 2.0) rotp (~> 2.0)
devise_pam_authenticatable2 (9.2.0) devise_pam_authenticatable2 (9.1.0)
devise (>= 4.0.0) devise (>= 4.0.0)
rpam2 (~> 4.0) rpam2 (~> 4.0)
diff-lcs (1.3) diff-lcs (1.3)
docile (1.3.0) docile (1.3.0)
domain_name (0.5.20180417) domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0) unf (>= 0.0.5, < 1.0.0)
doorkeeper (5.0.2) doorkeeper (4.4.2)
railties (>= 4.2) railties (>= 4.2)
dotenv (2.5.0) dotenv (2.2.2)
dotenv-rails (2.5.0) dotenv-rails (2.2.2)
dotenv (= 2.5.0) dotenv (= 2.2.2)
railties (>= 3.2, < 6.0) railties (>= 3.2, < 6.0)
easy_translate (0.5.1)
thread
thread_safe
elasticsearch (6.0.2) elasticsearch (6.0.2)
elasticsearch-api (= 6.0.2) elasticsearch-api (= 6.0.2)
elasticsearch-transport (= 6.0.2) elasticsearch-transport (= 6.0.2)
@ -201,37 +202,35 @@ GEM
encryptor (3.0.0) encryptor (3.0.0)
equatable (0.5.0) equatable (0.5.0)
erubi (1.7.1) erubi (1.7.1)
et-orbi (1.1.6) et-orbi (1.1.0)
tzinfo tzinfo
excon (0.62.0) excon (0.62.0)
fabrication (2.20.1) fabrication (2.20.1)
faker (1.9.1) faker (1.8.7)
i18n (>= 0.7) i18n (>= 0.7)
faraday (0.15.0) faraday (0.15.0)
multipart-post (>= 1.2, < 3) multipart-post (>= 1.2, < 3)
fast_blank (1.0.0) fast_blank (1.0.0)
fastimage (2.1.4) fastimage (2.1.1)
ffi (1.9.25) ffi (1.9.23)
fog-core (2.1.0) fog-core (1.45.0)
builder builder
excon (~> 0.58) excon (~> 0.58)
formatador (~> 0.2) formatador (~> 0.2)
mime-types fog-json (1.0.2)
fog-json (1.2.0) fog-core (~> 1.0)
fog-core
multi_json (~> 1.10) multi_json (~> 1.10)
fog-openstack (0.3.7) fog-local (0.5.0)
fog-core (>= 1.45, <= 2.1.0) fog-core (>= 1.27, < 3.0)
fog-openstack (0.1.25)
fog-core (~> 1.40)
fog-json (>= 1.0) fog-json (>= 1.0)
ipaddress (>= 0.8) ipaddress (>= 0.8)
formatador (0.2.5) formatador (0.2.5)
fugit (1.1.6) fuubar (2.3.1)
et-orbi (~> 1.1, >= 1.1.6)
raabro (~> 1.1)
fuubar (2.3.2)
rspec-core (~> 3.0) rspec-core (~> 3.0)
ruby-progressbar (~> 1.4) ruby-progressbar (~> 1.4)
get_process_mem (0.2.2) get_process_mem (0.2.1)
globalid (0.4.1) globalid (0.4.1)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
goldfinger (2.1.0) goldfinger (2.1.0)
@ -252,40 +251,39 @@ GEM
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
hashdiff (0.3.7) hashdiff (0.3.7)
hashie (3.5.7) hashie (3.5.7)
heapy (0.1.4) heapy (0.1.3)
highline (2.0.0) highline (1.7.10)
hiredis (0.6.1) hiredis (0.6.1)
hitimes (1.3.0) hitimes (1.2.6)
hkdf (0.3.0) hkdf (0.3.0)
htmlentities (4.3.4) htmlentities (4.3.4)
http (3.3.0) http (3.2.0)
addressable (~> 2.3) addressable (~> 2.3)
http-cookie (~> 1.0) http-cookie (~> 1.0)
http-form_data (~> 2.0) http-form_data (~> 2.0)
http_parser.rb (~> 0.6.0) http_parser.rb (~> 0.6.0)
http-cookie (1.0.3) http-cookie (1.0.3)
domain_name (~> 0.5) domain_name (~> 0.5)
http-form_data (2.1.1) http-form_data (2.1.0)
http_accept_language (2.1.1) http_accept_language (2.1.1)
httplog (1.1.1) httplog (1.0.2)
colorize (~> 0.8)
rack (>= 1.0) rack (>= 1.0)
rainbow (>= 2.0.0) i18n (1.1.0)
i18n (1.1.1)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
i18n-tasks (0.9.28) i18n-tasks (0.9.21)
activesupport (>= 4.0.2) activesupport (>= 4.0.2)
ast (>= 2.1.0) ast (>= 2.1.0)
easy_translate (>= 0.5.1)
erubi erubi
highline (>= 2.0.0) highline (>= 1.7.3)
i18n i18n
parser (>= 2.2.3.0) parser (>= 2.2.3.0)
rails-i18n
rainbow (>= 2.2.2, < 4.0) rainbow (>= 2.2.2, < 4.0)
terminal-table (>= 1.5.1) terminal-table (>= 1.5.1)
idn-ruby (0.1.0) idn-ruby (0.1.0)
ipaddress (0.8.3) ipaddress (0.8.3)
iso-639 (0.2.8) iso-639 (0.2.8)
jaro_winkler (1.5.1)
jmespath (1.4.0) jmespath (1.4.0)
json (2.1.0) json (2.1.0)
json-ld (2.2.1) json-ld (2.2.1)
@ -319,27 +317,25 @@ GEM
activesupport (>= 4) activesupport (>= 4)
railties (>= 4) railties (>= 4)
request_store (~> 1.0) request_store (~> 1.0)
loofah (2.2.3) loofah (2.2.2)
crass (~> 1.0.2) crass (~> 1.0.2)
nokogiri (>= 1.5.9) nokogiri (>= 1.5.9)
mail (2.7.0) mail (2.7.0)
mini_mime (>= 0.1.1) mini_mime (>= 0.1.1)
makara (0.4.0)
activerecord (>= 3.0.0)
marcel (0.3.2) marcel (0.3.2)
mimemagic (~> 0.3.2) mimemagic (~> 0.3.2)
mario-redis-lock (1.2.1) mario-redis-lock (1.2.1)
redis (>= 3.0.5) redis (>= 3.0.5)
memory_profiler (0.9.12) memory_profiler (0.9.10)
method_source (0.9.0) method_source (0.9.0)
microformats (4.0.7) microformats (4.0.7)
json json
nokogiri nokogiri
mime-types (3.2.2) mime-types (3.1)
mime-types-data (~> 3.2015) mime-types-data (~> 3.2015)
mime-types-data (3.2018.0812) mime-types-data (3.2016.0521)
mimemagic (0.3.2) mimemagic (0.3.2)
mini_mime (1.0.1) mini_mime (1.0.0)
mini_portile2 (2.3.0) mini_portile2 (2.3.0)
minitest (5.11.3) minitest (5.11.3)
msgpack (1.2.4) msgpack (1.2.4)
@ -349,18 +345,18 @@ GEM
net-ldap (0.16.1) net-ldap (0.16.1)
net-scp (1.2.1) net-scp (1.2.1)
net-ssh (>= 2.6.5) net-ssh (>= 2.6.5)
net-ssh (5.0.2) net-ssh (4.2.0)
nio4r (2.3.1) nio4r (2.3.0)
nokogiri (1.8.5) nokogiri (1.8.4)
mini_portile2 (~> 2.3.0) mini_portile2 (~> 2.3.0)
nokogumbo (2.0.0) nokogumbo (1.5.0)
nokogiri (~> 1.8, >= 1.8.4) nokogiri
nsa (0.2.4) nsa (0.2.4)
activesupport (>= 4.2, < 6) activesupport (>= 4.2, < 6)
concurrent-ruby (~> 1.0.0) concurrent-ruby (~> 1.0.0)
sidekiq (>= 3.5.0) sidekiq (>= 3.5.0)
statsd-ruby (~> 1.2.0) statsd-ruby (~> 1.2.0)
oj (3.7.0) oj (3.5.1)
omniauth (1.8.1) omniauth (1.8.1)
hashie (>= 3.4.6, < 3.6.0) hashie (>= 3.4.6, < 3.6.0)
rack (>= 1.6.2, < 3) rack (>= 1.6.2, < 3)
@ -368,7 +364,7 @@ GEM
addressable (~> 2.3) addressable (~> 2.3)
nokogiri (~> 1.5) nokogiri (~> 1.5)
omniauth (~> 1.2) omniauth (~> 1.2)
omniauth-saml (1.10.1) omniauth-saml (1.10.0)
omniauth (~> 1.3, >= 1.3.2) omniauth (~> 1.3, >= 1.3.2)
ruby-saml (~> 1.7) ruby-saml (~> 1.7)
orm_adapter (0.5.0) orm_adapter (0.5.0)
@ -376,7 +372,7 @@ GEM
addressable (~> 2.5) addressable (~> 2.5)
http (~> 3.0) http (~> 3.0)
nokogiri (~> 1.8) nokogiri (~> 1.8)
ox (2.10.0) ox (2.9.2)
paperclip (6.0.0) paperclip (6.0.0)
activemodel (>= 4.2.0) activemodel (>= 4.2.0)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
@ -387,18 +383,18 @@ GEM
av (~> 0.9.0) av (~> 0.9.0)
paperclip (>= 2.5.2) paperclip (>= 2.5.2)
parallel (1.12.1) parallel (1.12.1)
parallel_tests (2.26.0) parallel_tests (2.21.3)
parallel parallel
parser (2.5.3.0) parser (2.5.1.0)
ast (~> 2.4.0) ast (~> 2.4.0)
pastel (0.7.2) pastel (0.7.2)
equatable (~> 0.5.0) equatable (~> 0.5.0)
tty-color (~> 0.4.0) tty-color (~> 0.4.0)
pg (1.1.3) pg (1.0.0)
pghero (2.2.0) pghero (2.1.0)
activerecord activerecord
pkg-config (1.3.1) pkg-config (1.3.0)
powerpack (0.1.2) powerpack (0.1.1)
premailer (1.11.1) premailer (1.11.1)
addressable addressable
css_parser (>= 1.6.0) css_parser (>= 1.6.0)
@ -406,7 +402,7 @@ GEM
premailer-rails (1.10.2) premailer-rails (1.10.2)
actionmailer (>= 3, < 6) actionmailer (>= 3, < 6)
premailer (~> 1.7, >= 1.7.9) premailer (~> 1.7, >= 1.7.9)
private_address_check (0.5.0) private_address_check (0.4.1)
pry (0.11.3) pry (0.11.3)
coderay (~> 1.1.0) coderay (~> 1.1.0)
method_source (~> 0.9.0) method_source (~> 0.9.0)
@ -415,33 +411,32 @@ GEM
pry (~> 0.10) pry (~> 0.10)
pry-rails (0.3.6) pry-rails (0.3.6)
pry (>= 0.10.4) pry (>= 0.10.4)
public_suffix (3.0.3) public_suffix (3.0.2)
puma (3.12.0) puma (3.11.4)
pundit (2.0.0) pundit (1.1.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
raabro (1.1.6)
rack (2.0.5) rack (2.0.5)
rack-attack (5.4.1) rack-attack (5.2.0)
rack (>= 1.0, < 3) rack
rack-cors (1.0.2) rack-cors (1.0.2)
rack-protection (2.0.4) rack-protection (2.0.1)
rack rack
rack-proxy (0.6.4) rack-proxy (0.6.4)
rack rack
rack-test (1.1.0) rack-test (1.1.0)
rack (>= 1.0, < 3) rack (>= 1.0, < 3)
rails (5.2.1) rails (5.2.0)
actioncable (= 5.2.1) actioncable (= 5.2.0)
actionmailer (= 5.2.1) actionmailer (= 5.2.0)
actionpack (= 5.2.1) actionpack (= 5.2.0)
actionview (= 5.2.1) actionview (= 5.2.0)
activejob (= 5.2.1) activejob (= 5.2.0)
activemodel (= 5.2.1) activemodel (= 5.2.0)
activerecord (= 5.2.1) activerecord (= 5.2.0)
activestorage (= 5.2.1) activestorage (= 5.2.0)
activesupport (= 5.2.1) activesupport (= 5.2.0)
bundler (>= 1.3.0) bundler (>= 1.3.0)
railties (= 5.2.1) railties (= 5.2.0)
sprockets-rails (>= 2.0.0) sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.2) rails-controller-testing (1.0.2)
actionpack (~> 5.x, >= 5.0.1) actionpack (~> 5.x, >= 5.0.1)
@ -452,17 +447,17 @@ GEM
nokogiri (>= 1.6) nokogiri (>= 1.6)
rails-html-sanitizer (1.0.4) rails-html-sanitizer (1.0.4)
loofah (~> 2.2, >= 2.2.2) loofah (~> 2.2, >= 2.2.2)
rails-i18n (5.1.2) rails-i18n (5.1.1)
i18n (>= 0.7, < 2) i18n (>= 0.7, < 2)
railties (>= 5.0, < 6) railties (>= 5.0, < 6)
rails-settings-cached (0.6.6) rails-settings-cached (0.6.6)
rails (>= 4.2.0) rails (>= 4.2.0)
railties (5.2.1) railties (5.2.0)
actionpack (= 5.2.1) actionpack (= 5.2.0)
activesupport (= 5.2.1) activesupport (= 5.2.0)
method_source method_source
rake (>= 0.8.7) rake (>= 0.8.7)
thor (>= 0.19.0, < 2.0) thor (>= 0.18.1, < 2.0)
rainbow (3.0.0) rainbow (3.0.0)
rake (12.3.1) rake (12.3.1)
rb-fsevent (0.10.3) rb-fsevent (0.10.3)
@ -473,7 +468,7 @@ GEM
link_header (~> 0.0, >= 0.0.8) link_header (~> 0.0, >= 0.0.8)
rdf-normalize (0.3.3) rdf-normalize (0.3.3)
rdf (>= 2.2, < 4.0) rdf (>= 2.2, < 4.0)
redis (4.0.2) redis (4.0.1)
redis-actionpack (5.0.2) redis-actionpack (5.0.2)
actionpack (>= 4.0, < 6) actionpack (>= 4.0, < 6)
redis-rack (>= 1, < 3) redis-rack (>= 1, < 3)
@ -492,7 +487,6 @@ GEM
redis-store (>= 1.2, < 2) redis-store (>= 1.2, < 2)
redis-store (1.5.0) redis-store (1.5.0)
redis (>= 2.2, < 5) redis (>= 2.2, < 5)
regexp_parser (1.2.0)
request_store (1.4.1) request_store (1.4.1)
rack (>= 1.4) rack (>= 1.4)
responders (2.4.0) responders (2.4.0)
@ -502,60 +496,60 @@ GEM
rpam2 (4.0.2) rpam2 (4.0.2)
rqrcode (0.10.1) rqrcode (0.10.1)
chunky_png (~> 1.0) chunky_png (~> 1.0)
rspec-core (3.8.0) rspec-core (3.7.1)
rspec-support (~> 3.8.0) rspec-support (~> 3.7.0)
rspec-expectations (3.8.2) rspec-expectations (3.7.0)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0) rspec-support (~> 3.7.0)
rspec-mocks (3.8.0) rspec-mocks (3.7.0)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0) rspec-support (~> 3.7.0)
rspec-rails (3.8.1) rspec-rails (3.7.2)
actionpack (>= 3.0) actionpack (>= 3.0)
activesupport (>= 3.0) activesupport (>= 3.0)
railties (>= 3.0) railties (>= 3.0)
rspec-core (~> 3.8.0) rspec-core (~> 3.7.0)
rspec-expectations (~> 3.8.0) rspec-expectations (~> 3.7.0)
rspec-mocks (~> 3.8.0) rspec-mocks (~> 3.7.0)
rspec-support (~> 3.8.0) rspec-support (~> 3.7.0)
rspec-sidekiq (3.0.3) rspec-sidekiq (3.0.3)
rspec-core (~> 3.0, >= 3.0.0) rspec-core (~> 3.0, >= 3.0.0)
sidekiq (>= 2.4.0) sidekiq (>= 2.4.0)
rspec-support (3.8.0) rspec-support (3.7.1)
rubocop (0.60.0) rubocop (0.55.0)
jaro_winkler (~> 1.5.1)
parallel (~> 1.10) parallel (~> 1.10)
parser (>= 2.5, != 2.5.1.1) parser (>= 2.5)
powerpack (~> 0.1) powerpack (~> 0.1)
rainbow (>= 2.2.2, < 4.0) rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.7) ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.4.0) unicode-display_width (~> 1.0, >= 1.0.1)
ruby-progressbar (1.10.0) ruby-progressbar (1.9.0)
ruby-saml (1.9.0) ruby-saml (1.7.2)
nokogiri (>= 1.5.10) nokogiri (>= 1.5.10)
rufus-scheduler (3.5.2) rufus-scheduler (3.4.2)
fugit (~> 1.1, >= 1.1.5) et-orbi (~> 1.0)
safe_yaml (1.0.4) safe_yaml (1.0.4)
sanitize (5.0.0) sanitize (4.6.4)
crass (~> 1.0.2) crass (~> 1.0.2)
nokogiri (>= 1.8.0) nokogiri (>= 1.4.4)
nokogumbo (~> 2.0) nokogumbo (~> 1.4)
sass (3.6.0) sass (3.5.6)
sass-listen (~> 4.0.0) sass-listen (~> 4.0.0)
sass-listen (4.0.0) sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4) rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7) rb-inotify (~> 0.9, >= 0.9.7)
scss_lint (0.57.1) scss_lint (0.57.0)
rake (>= 0.9, < 13) rake (>= 0.9, < 13)
sass (~> 3.5, >= 3.5.5) sass (~> 3.5.5)
sidekiq (5.2.2) sidekiq (5.1.3)
connection_pool (~> 2.2, >= 2.2.2) concurrent-ruby (~> 1.0)
connection_pool (~> 2.2, >= 2.2.0)
rack-protection (>= 1.5.0) rack-protection (>= 1.5.0)
redis (>= 3.3.5, < 5) redis (>= 3.3.5, < 5)
sidekiq-bulk (0.1.1) sidekiq-bulk (0.1.1)
activesupport activesupport
sidekiq sidekiq
sidekiq-scheduler (3.0.0) sidekiq-scheduler (2.2.1)
redis (>= 3, < 5) redis (>= 3, < 5)
rufus-scheduler (~> 3.2) rufus-scheduler (~> 3.2)
sidekiq (>= 3) sidekiq (>= 3)
@ -565,9 +559,9 @@ GEM
thor (~> 0) thor (~> 0)
simple-navigation (4.0.5) simple-navigation (4.0.5)
activesupport (>= 2.3.2) activesupport (>= 2.3.2)
simple_form (4.0.1) simple_form (4.0.0)
actionpack (>= 5.0) actionpack (> 4)
activemodel (>= 5.0) activemodel (> 4)
simplecov (0.16.1) simplecov (0.16.1)
docile (~> 1.1) docile (~> 1.1)
json (>= 1.8, < 3) json (>= 1.8, < 3)
@ -580,15 +574,15 @@ GEM
actionpack (>= 4.0) actionpack (>= 4.0)
activesupport (>= 4.0) activesupport (>= 4.0)
sprockets (>= 3.0.0) sprockets (>= 3.0.0)
sshkit (1.17.0) sshkit (1.16.0)
net-scp (>= 1.1.2) net-scp (>= 1.1.2)
net-ssh (>= 2.8.0) net-ssh (>= 2.8.0)
stackprof (0.2.12) stackprof (0.2.11)
statsd-ruby (1.2.1) statsd-ruby (1.2.1)
stoplight (2.1.3) stoplight (2.1.3)
streamio-ffmpeg (3.0.2) streamio-ffmpeg (3.0.2)
multi_json (~> 1.8) multi_json (~> 1.8)
strong_migrations (0.3.1) strong_migrations (0.2.2)
activerecord (>= 3.2.0) activerecord (>= 3.2.0)
temple (0.8.0) temple (0.8.0)
terminal-table (1.8.0) terminal-table (1.8.0)
@ -596,54 +590,55 @@ GEM
terrapin (0.6.0) terrapin (0.6.0)
climate_control (>= 0.0.3, < 1.0) climate_control (>= 0.0.3, < 1.0)
thor (0.20.0) thor (0.20.0)
thread (0.2.2)
thread_safe (0.3.6) thread_safe (0.3.6)
tilt (2.0.8) tilt (2.0.8)
timers (4.1.2) timers (4.1.2)
hitimes hitimes
tty-color (0.4.3) tty-color (0.4.2)
tty-command (0.8.2) tty-command (0.8.0)
pastel (~> 0.7.0) pastel (~> 0.7.0)
tty-cursor (0.6.0) tty-cursor (0.5.0)
tty-prompt (0.17.1) tty-prompt (0.16.0)
necromancer (~> 0.4.0) necromancer (~> 0.4.0)
pastel (~> 0.7.0) pastel (~> 0.7.0)
timers (~> 4.0) timers (~> 4.0)
tty-cursor (~> 0.6.0) tty-cursor (~> 0.5.0)
tty-reader (~> 0.4.0) tty-reader (~> 0.2.0)
tty-reader (0.4.0) tty-reader (0.2.0)
tty-cursor (~> 0.6.0) tty-cursor (~> 0.5.0)
tty-screen (~> 0.6.4) tty-screen (~> 0.6.4)
wisper (~> 2.0.0) wisper (~> 2.0.0)
tty-screen (0.6.5) tty-screen (0.6.4)
twitter-text (1.14.7) twitter-text (1.14.7)
unf (~> 0.1.0) unf (~> 0.1.0)
tzinfo (1.2.5) tzinfo (1.2.5)
thread_safe (~> 0.1) thread_safe (~> 0.1)
tzinfo-data (1.2018.7) tzinfo-data (1.2018.4)
tzinfo (>= 1.0.0) tzinfo (>= 1.0.0)
unf (0.1.4) unf (0.1.4)
unf_ext unf_ext
unf_ext (0.0.7.5) unf_ext (0.0.7.5)
unicode-display_width (1.4.0) unicode-display_width (1.3.2)
uniform_notifier (1.11.0) uniform_notifier (1.11.0)
warden (1.2.7) warden (1.2.7)
rack (>= 1.0) rack (>= 1.0)
webmock (3.4.2) webmock (3.3.0)
addressable (>= 2.3.6) addressable (>= 2.3.6)
crack (>= 0.3.2) crack (>= 0.3.2)
hashdiff hashdiff
webpacker (3.5.5) webpacker (3.4.3)
activesupport (>= 4.2) activesupport (>= 4.2)
rack-proxy (>= 0.6.1) rack-proxy (>= 0.6.1)
railties (>= 4.2) railties (>= 4.2)
webpush (0.3.4) webpush (0.3.3)
hkdf (~> 0.2) hkdf (~> 0.2)
jwt (~> 2.0) jwt (~> 2.0)
websocket-driver (0.7.0) websocket-driver (0.7.0)
websocket-extensions (>= 0.1.0) websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.3) websocket-extensions (0.1.3)
wisper (2.0.0) wisper (2.0.0)
xpath (3.2.0) xpath (3.0.0)
nokogiri (~> 1.8) nokogiri (~> 1.8)
PLATFORMS PLATFORMS
@ -654,44 +649,45 @@ DEPENDENCIES
active_record_query_trace (~> 1.5) active_record_query_trace (~> 1.5)
addressable (~> 2.5) addressable (~> 2.5)
annotate (~> 2.7) annotate (~> 2.7)
aws-sdk-s3 (~> 1.23) aws-sdk-s3 (~> 1.9)
better_errors (~> 2.5) better_errors (~> 2.4)
binding_of_caller (~> 0.7) binding_of_caller (~> 0.7)
bootsnap (~> 1.3) bootsnap (~> 1.3)
brakeman (~> 4.3) brakeman (~> 4.2)
browser browser
bullet (~> 5.7) bullet (~> 5.7)
bundler-audit (~> 0.6) bundler-audit (~> 0.6)
capistrano (~> 3.11) capistrano (~> 3.10)
capistrano-rails (~> 1.4) capistrano-rails (~> 1.3)
capistrano-rbenv (~> 2.1) capistrano-rbenv (~> 2.1)
capistrano-yarn (~> 2.0) capistrano-yarn (~> 2.0)
capybara (~> 3.10) capybara (~> 2.18)
charlock_holmes (~> 0.7.6) charlock_holmes (~> 0.7.6)
chewy (~> 5.0) chewy (~> 5.0)
cld3 (~> 3.2.0) cld3 (~> 3.2.0)
climate_control (~> 0.2) climate_control (~> 0.2)
derailed_benchmarks derailed_benchmarks
devise (~> 4.5) devise (~> 4.4)
devise-two-factor (~> 3.0) devise-two-factor (~> 3.0)
devise_pam_authenticatable2 (~> 9.2) devise_pam_authenticatable2 (~> 9.1)
doorkeeper (~> 5.0) doorkeeper (~> 4.4)
dotenv-rails (~> 2.5) dotenv-rails (~> 2.2, < 2.3)
fabrication (~> 2.20) fabrication (~> 2.20)
faker (~> 1.9) faker (~> 1.8)
fast_blank (~> 1.0) fast_blank (~> 1.0)
fastimage fastimage
fog-core (<= 2.1.0) fog-core (~> 1.45)
fog-openstack (~> 0.3) fog-local (~> 0.5)
fuubar (~> 2.3) fog-openstack (~> 0.1)
fuubar (~> 2.2)
goldfinger (~> 2.1) goldfinger (~> 2.1)
hamlit-rails (~> 0.2) hamlit-rails (~> 0.2)
hiredis (~> 0.6) hiredis (~> 0.6)
htmlentities (~> 4.3) htmlentities (~> 4.3)
http (~> 3.3) http (~> 3.2)
http_accept_language (~> 2.1) http_accept_language (~> 2.1)
http_parser.rb (~> 0.6)! http_parser.rb (~> 0.6)!
httplog (~> 1.1) httplog (~> 1.0)
i18n-tasks (~> 0.9) i18n-tasks (~> 0.9)
idn-ruby idn-ruby
iso-639 iso-639
@ -701,36 +697,35 @@ DEPENDENCIES
letter_opener_web (~> 1.3) letter_opener_web (~> 1.3)
link_header (~> 0.0) link_header (~> 0.0)
lograge (~> 0.10) lograge (~> 0.10)
makara (~> 0.4)
mario-redis-lock (~> 1.2) mario-redis-lock (~> 1.2)
memory_profiler memory_profiler
microformats (~> 4.0) microformats (~> 4.0)
mime-types (~> 3.2) mime-types (~> 3.1)
net-ldap (~> 0.10) net-ldap (~> 0.10)
nokogiri (~> 1.8) nokogiri (~> 1.8)
nsa (~> 0.2) nsa (~> 0.2)
oj (~> 3.7) oj (~> 3.5)
omniauth (~> 1.2) omniauth (~> 1.2)
omniauth-cas (~> 1.1) omniauth-cas (~> 1.1)
omniauth-saml (~> 1.10) omniauth-saml (~> 1.10)
ostatus2 (~> 2.0) ostatus2 (~> 2.0)
ox (~> 2.10) ox (~> 2.9)
paperclip (~> 6.0) paperclip (~> 6.0)
paperclip-av-transcoder (~> 0.6) paperclip-av-transcoder (~> 0.6)
parallel_tests (~> 2.26) parallel_tests (~> 2.21)
pg (~> 1.1) pg (~> 1.0)
pghero (~> 2.2) pghero (~> 2.1)
pkg-config (~> 1.3) pkg-config (~> 1.3)
posix-spawn! posix-spawn!
premailer-rails premailer-rails
private_address_check (~> 0.5) private_address_check (~> 0.4.1)
pry-byebug (~> 3.6) pry-byebug (~> 3.6)
pry-rails (~> 0.3) pry-rails (~> 0.3)
puma (~> 3.12) puma (~> 3.11)
pundit (~> 2.0) pundit (~> 1.1)
rack-attack (~> 5.4) rack-attack (~> 5.2)
rack-cors (~> 1.0) rack-cors (~> 1.0)
rails (~> 5.2.1) rails (~> 5.2.0)
rails-controller-testing (~> 1.0) rails-controller-testing (~> 1.0)
rails-i18n (~> 5.1) rails-i18n (~> 5.1)
rails-settings-cached (~> 0.6) rails-settings-cached (~> 0.6)
@ -739,14 +734,15 @@ DEPENDENCIES
redis-namespace (~> 1.5) redis-namespace (~> 1.5)
redis-rails (~> 5.0) redis-rails (~> 5.0)
rqrcode (~> 0.10) rqrcode (~> 0.10)
rspec-rails (~> 3.8) rspec-rails (~> 3.7)
rspec-sidekiq (~> 3.0) rspec-sidekiq (~> 3.0)
rubocop (~> 0.60) rubocop (~> 0.55)
sanitize (~> 5.0) ruby-progressbar (~> 1.4)
sanitize (~> 4.6)
scss_lint (~> 0.57) scss_lint (~> 0.57)
sidekiq (~> 5.2) sidekiq (~> 5.1)
sidekiq-bulk (~> 0.1.1) sidekiq-bulk (~> 0.1.1)
sidekiq-scheduler (~> 3.0) sidekiq-scheduler (~> 2.2)
sidekiq-unique-jobs (~> 5.0) sidekiq-unique-jobs (~> 5.0)
simple-navigation (~> 4.0) simple-navigation (~> 4.0)
simple_form (~> 4.0) simple_form (~> 4.0)
@ -755,18 +751,17 @@ DEPENDENCIES
stackprof stackprof
stoplight (~> 2.1.3) stoplight (~> 2.1.3)
streamio-ffmpeg (~> 3.0) streamio-ffmpeg (~> 3.0)
strong_migrations (~> 0.3) strong_migrations (~> 0.2)
thor (~> 0.20)
tty-command (~> 0.8) tty-command (~> 0.8)
tty-prompt (~> 0.17) tty-prompt (~> 0.16)
twitter-text (~> 1.14) twitter-text (~> 1.14)
tzinfo-data (~> 1.2018) tzinfo-data (~> 1.2018)
webmock (~> 3.4) webmock (~> 3.3)
webpacker (~> 3.5) webpacker (~> 3.4)
webpush webpush
RUBY VERSION RUBY VERSION
ruby 2.5.3p105 ruby 2.5.0p0
BUNDLED WITH BUNDLED WITH
1.16.6 1.16.3

View File

@ -1,95 +1,96 @@
![Mastodon](https://i.imgur.com/NhZc40l.png) ![Mastodon](https://i.imgur.com/NhZc40l.png)
======== ========
[![GitHub release](https://img.shields.io/github/release/tootsuite/mastodon.svg)][releases]
[![Build Status](https://img.shields.io/circleci/project/github/tootsuite/mastodon.svg)][circleci] [![Build Status](https://img.shields.io/circleci/project/github/tootsuite/mastodon.svg)][circleci]
[![Code Climate](https://img.shields.io/codeclimate/maintainability/tootsuite/mastodon.svg)][code_climate] [![Code Climate](https://img.shields.io/codeclimate/maintainability/tootsuite/mastodon.svg)][code_climate]
[![Translation status](https://weblate.joinmastodon.org/widgets/mastodon/-/svg-badge.svg)][weblate]
[![Docker Pulls](https://img.shields.io/docker/pulls/tootsuite/mastodon.svg)][docker]
[releases]: https://github.com/tootsuite/mastodon/releases
[circleci]: https://circleci.com/gh/tootsuite/mastodon [circleci]: https://circleci.com/gh/tootsuite/mastodon
[code_climate]: https://codeclimate.com/github/tootsuite/mastodon [code_climate]: https://codeclimate.com/github/tootsuite/mastodon
[weblate]: https://weblate.joinmastodon.org/engage/mastodon/
[docker]: https://hub.docker.com/r/tootsuite/mastodon/
Mastodon is a **free, open-source social network server** based on ActivityPub. Follow friends and discover new ones. Publish anything you want: links, pictures, text, video. All servers of Mastodon are interoperable as a federated network, i.e. users on one server can seamlessly communicate with users from another one. This includes non-Mastodon software that also implements ActivityPub! Mastodon is a **free, open-source social network server** based on **open web protocols** like ActivityPub and OStatus. The social focus of the project is a viable decentralized alternative to commercial social media silos that returns the control of the content distribution channels to the people. The technical focus of the project is a good user interface, a clean REST API for 3rd party apps and robust anti-abuse tools.
Click below to **learn more** in a video: Click on the screenshot below to watch a demo of the UI:
[![Screenshot](https://blog.joinmastodon.org/2018/06/why-activitypub-is-the-future/ezgif-2-60f1b00403.gif)][youtube_demo] [![Screenshot](https://i.imgur.com/qrNOiSp.png)][youtube_demo]
[youtube_demo]: https://www.youtube.com/watch?v=IPSbNdBmWKE [youtube_demo]: https://www.youtube.com/watch?v=IPSbNdBmWKE
## Navigation **Ruby on Rails** is used for the back-end, while **React.js** and Redux are used for the dynamic front-end. A static front-end for public resources (profiles and statuses) is also provided.
- [Project homepage 🐘](https://joinmastodon.org) If you would like, you can [support the development of this project on Patreon][patreon] or [Liberapay][liberapay].
- [Support the development via Patreon][patreon]
- [View sponsors](https://joinmastodon.org/sponsors)
- [Blog](https://blog.joinmastodon.org)
- [Documentation](https://docs.joinmastodon.org)
- [Browse Mastodon servers](https://joinmastodon.org/#getting-started)
- [Browse Mastodon apps](https://joinmastodon.org/apps)
[patreon]: https://www.patreon.com/mastodon [patreon]: https://www.patreon.com/user?u=619786
[liberapay]: https://liberapay.com/Mastodon/
---
## Resources
- [Frequently Asked Questions](https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/FAQ.md)
- [Use this tool to find Twitter friends on Mastodon](https://bridge.joinmastodon.org)
- [API overview](https://github.com/tootsuite/documentation/blob/master/Using-the-API/API.md)
- [List of Mastodon instances](https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/List-of-Mastodon-instances.md)
- [List of apps](https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/Apps.md)
- [List of sponsors](https://joinmastodon.org/sponsors)
## Features ## Features
<img src="https://docs.joinmastodon.org/elephant.svg" align="right" width="30%" />
**No vendor lock-in: Fully interoperable with any conforming platform** **No vendor lock-in: Fully interoperable with any conforming platform**
It doesn't have to be Mastodon, whatever implements ActivityPub is part of the social network! [Learn more](https://blog.joinmastodon.org/2018/06/why-activitypub-is-the-future/) It doesn't have to be Mastodon, whatever implements ActivityPub or OStatus is part of the social network!
**Real-time, chronological timeline updates** **Real-time timeline updates**
See the updates of people you're following appear in real-time in the UI via WebSockets. There's a firehose view as well! See the updates of people you're following appear in real-time in the UI via WebSockets. There's a firehose view as well!
**Federated thread resolving**
If someone you follow replies to a user unknown to the server, the server fetches the full thread so you can view it without leaving the UI
**Media attachments like images and short videos** **Media attachments like images and short videos**
Upload and view images and WebM/MP4 videos attached to the updates. Videos with no audio track are treated like GIFs; normal videos are looped - like vines! Upload and view images and WebM/MP4 videos attached to the updates. Videos with no audio track are treated like GIFs; normal videos are looped - like vines!
**Safety and moderation tools**
Private posts, locked accounts, phrase filtering, muting, blocking and all sorts of other features, along with a reporting and moderation system. [Learn more](https://blog.joinmastodon.org/2018/07/cage-the-mastodon/)
**OAuth2 and a straightforward REST API** **OAuth2 and a straightforward REST API**
Mastodon acts as an OAuth2 provider so 3rd party apps can use the REST and Streaming APIs, resulting in a rich app ecosystem with a lot of choice! Mastodon acts as an OAuth2 provider so 3rd party apps can use the API
**Fast response times**
Mastodon tries to be as fast and responsive as possible, so all long-running tasks are delegated to background processing
**Deployable via Docker**
You don't need to mess with dependencies and configuration if you want to try Mastodon, if you have Docker and Docker Compose the deployment is extremely easy
---
## Development
Please follow the [development guide](https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Development-guide.md) from the documentation repository.
## Deployment ## Deployment
**Tech stack:** There are guides in the documentation repository for [deploying on various platforms](https://github.com/tootsuite/documentation#running-mastodon).
- **Ruby on Rails** powers the REST API and other web pages
- **React.js** and Redux are used for the dynamic parts of the interface
- **Node.js** powers the streaming API
**Requirements:**
- **PostgreSQL** 9.5+
- **Redis**
- **Ruby** 2.4+
- **Node.js** 8+
The repository includes deployment configurations for **Docker and docker-compose**, but also a few specific platforms like **Heroku**, **Scalingo**, and **Nanobox**. The [**stand-alone** installation guide](https://docs.joinmastodon.org/administration/installation/) is available in the documentation.
A **Vagrant** configuration is included for development purposes.
## Contributing ## Contributing
Mastodon is **free, open source software** licensed under **AGPLv3**. You can open issues for bugs you've found or features you think are missing. You can also submit pull requests to this repository. [Here are the guidelines for code contributions](CONTRIBUTING.md)
You can open issues for bugs you've found or features you think are missing. You can also submit pull requests to this repository, or submit translations using Weblate. To get started, take a look at [CONTRIBUTING.md](CONTRIBUTING.md)
**IRC channel**: #mastodon on irc.freenode.net **IRC channel**: #mastodon on irc.freenode.net
## License ## License
Copyright (C) 2016-2018 Eugen Rochko & other Mastodon contributors (see [AUTHORS.md](AUTHORS.md)) Copyright (C) 2016-2018 Eugen Rochko & other Mastodon contributors (see AUTHORS.md)
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
---
## Extra credits
The elephant friend illustrations are created by [Dopatwo](https://mastodon.social/@dopatwo)

16
Vagrantfile vendored
View File

@ -12,7 +12,7 @@ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
sudo apt-add-repository 'deb https://dl.yarnpkg.com/debian/ stable main' sudo apt-add-repository 'deb https://dl.yarnpkg.com/debian/ stable main'
# Add repo for NodeJS # Add repo for NodeJS
curl -sL https://deb.nodesource.com/setup_8.x | sudo bash - curl -sL https://deb.nodesource.com/setup_6.x | sudo bash -
# Add firewall rule to redirect 80 to PORT and save # Add firewall rule to redirect 80 to PORT and save
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{ENV["PORT"]} sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{ENV["PORT"]}
@ -85,9 +85,6 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.provider :virtualbox do |vb| config.vm.provider :virtualbox do |vb|
vb.name = "mastodon" vb.name = "mastodon"
vb.customize ["modifyvm", :id, "--memory", "2048"] vb.customize ["modifyvm", :id, "--memory", "2048"]
# Increase the number of CPUs. Uncomment and adjust to
# increase performance
# vb.customize ["modifyvm", :id, "--cpus", "3"]
# Disable VirtualBox DNS proxy to skip long-delay IPv6 resolutions. # Disable VirtualBox DNS proxy to skip long-delay IPv6 resolutions.
# https://github.com/mitchellh/vagrant/issues/1172 # https://github.com/mitchellh/vagrant/issues/1172
@ -100,22 +97,19 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
end end
config.vm.hostname = "mastodon.dev"
# This uses the vagrant-hostsupdater plugin, and lets you # This uses the vagrant-hostsupdater plugin, and lets you
# access the development site at http://mastodon.local. # access the development site at http://mastodon.dev.
# If you change it, also change it in .env.vagrant before provisioning
# the vagrant server to update the development build.
#
# To install: # To install:
# $ vagrant plugin install vagrant-hostsupdater # $ vagrant plugin install vagrant-hostsupdater
config.vm.hostname = "mastodon.local"
if defined?(VagrantPlugins::HostsUpdater) if defined?(VagrantPlugins::HostsUpdater)
config.vm.network :private_network, ip: "192.168.42.42", nictype: "virtio" config.vm.network :private_network, ip: "192.168.42.42", nictype: "virtio"
config.hostsupdater.remove_on_suspend = false config.hostsupdater.remove_on_suspend = false
end end
if config.vm.networks.any? { |type, options| type == :private_network } if config.vm.networks.any? { |type, options| type == :private_network }
config.vm.synced_folder ".", "/vagrant", type: "nfs", mount_options: ['rw', 'vers=3', 'tcp', 'actimeo=1'] config.vm.synced_folder ".", "/vagrant", type: "nfs", mount_options: ['rw', 'vers=3', 'tcp']
else else
config.vm.synced_folder ".", "/vagrant" config.vm.synced_folder ".", "/vagrant"
end end

View File

@ -31,7 +31,7 @@ class StatusesIndex < Chewy::Index
}, },
} }
define_type ::Status.unscoped.without_reblogs do define_type ::Status.without_reblogs do
crutch :mentions do |collection| crutch :mentions do |collection|
data = ::Mention.where(status_id: collection.map(&:id)).pluck(:status_id, :account_id) data = ::Mention.where(status_id: collection.map(&:id)).pluck(:status_id, :account_id)
data.each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) } data.each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) }

View File

@ -9,13 +9,9 @@ class AboutController < ApplicationController
@initial_state_json = serializable_resource.to_json @initial_state_json = serializable_resource.to_json
end end
def more def more; end
render layout: 'public'
end
def terms def terms; end
render layout: 'public'
end
private private
@ -30,7 +26,7 @@ class AboutController < ApplicationController
end end
def set_body_classes def set_body_classes
@body_classes = 'with-modals' @body_classes = 'about-body'
end end
def initial_state_params def initial_state_params

View File

@ -10,9 +10,7 @@ class AccountsController < ApplicationController
def show def show
respond_to do |format| respond_to do |format|
format.html do format.html do
@body_classes = 'with-modals' @pinned_statuses = []
@pinned_statuses = []
@endorsed_accounts = @account.endorsed_accounts.to_a.sample(4)
if current_account && @account.blocking?(current_account) if current_account && @account.blocking?(current_account)
@statuses = [] @statuses = []
@ -42,7 +40,7 @@ class AccountsController < ApplicationController
format.json do format.json do
skip_session! skip_session!
render_cached_json(['activitypub', 'actor', @account], content_type: 'application/activity+json') do render_cached_json(['activitypub', 'actor', @account.cache_key], content_type: 'application/activity+json') do
ActiveModelSerializers::SerializableResource.new(@account, serializer: ActivityPub::ActorSerializer, adapter: ActivityPub::Adapter) ActiveModelSerializers::SerializableResource.new(@account, serializer: ActivityPub::ActorSerializer, adapter: ActivityPub::Adapter)
end end
end end
@ -52,7 +50,7 @@ class AccountsController < ApplicationController
private private
def show_pinned_statuses? def show_pinned_statuses?
[replies_requested?, media_requested?, params[:max_id].present?, params[:min_id].present?].none? [replies_requested?, media_requested?, params[:max_id].present?, params[:since_id].present?].none?
end end
def filtered_statuses def filtered_statuses

View File

@ -36,6 +36,6 @@ class ActivityPub::InboxesController < Api::BaseController
end end
def process_payload def process_payload
ActivityPub::ProcessingWorker.perform_async(signed_request_account.id, body.force_encoding('UTF-8'), @account&.id) ActivityPub::ProcessingWorker.perform_async(signed_request_account.id, body.force_encoding('UTF-8'))
end end
end end

View File

@ -95,7 +95,7 @@ module Admin
:remote, :remote,
:by_domain, :by_domain,
:silenced, :silenced,
:alphabetic, :recent,
:suspended, :suspended,
:username, :username,
:display_name, :display_name,

View File

@ -5,15 +5,8 @@ module Admin
include Authorization include Authorization
include AccountableConcern include AccountableConcern
layout 'admin'
before_action :require_staff! before_action :require_staff!
before_action :set_body_classes
private layout 'admin'
def set_body_classes
@body_classes = 'admin'
end
end end
end end

View File

@ -1,43 +0,0 @@
# frozen_string_literal: true
require 'sidekiq/api'
module Admin
class DashboardController < BaseController
def index
@users_count = User.count
@registrations_week = Redis.current.get("activity:accounts:local:#{current_week}") || 0
@logins_week = Redis.current.pfcount("activity:logins:#{current_week}")
@interactions_week = Redis.current.get("activity:interactions:#{current_week}") || 0
@relay_enabled = Relay.enabled.exists?
@single_user_mode = Rails.configuration.x.single_user_mode
@registrations_enabled = Setting.open_registrations
@deletions_enabled = Setting.open_deletion
@invites_enabled = Setting.min_invite_role == 'user'
@search_enabled = Chewy.enabled?
@version = Mastodon::Version.to_s
@database_version = ActiveRecord::Base.connection.execute('SELECT VERSION()').first['version'].match(/\A(?:PostgreSQL |)([^\s]+).*\z/)[1]
@redis_version = redis_info['redis_version']
@reports_count = Report.unresolved.count
@queue_backlog = Sidekiq::Stats.new.enqueued
@recent_users = User.confirmed.recent.includes(:account).limit(4)
@database_size = ActiveRecord::Base.connection.execute('SELECT pg_database_size(current_database())').first['pg_database_size']
@redis_size = redis_info['used_memory']
@ldap_enabled = ENV['LDAP_ENABLED'] == 'true'
@cas_enabled = ENV['CAS_ENABLED'] == 'true'
@saml_enabled = ENV['SAML_ENABLED'] == 'true'
@pam_enabled = ENV['PAM_ENABLED'] == 'true'
@hidden_service = ENV['ALLOW_ACCESS_TO_HIDDEN_SERVICE'] == 'true'
@trending_hashtags = TrendingTags.get(7)
end
private
def current_week
@current_week ||= Time.now.utc.to_date.cweek
end
def redis_info
@redis_info ||= Redis.current.info
end
end
end

View File

@ -46,7 +46,7 @@ module Admin
end end
def resource_params def resource_params
params.require(:domain_block).permit(:domain, :severity, :reject_media, :reject_reports, :retroactive) params.require(:domain_block).permit(:domain, :severity, :reject_media, :retroactive)
end end
def retroactive_unblock? def retroactive_unblock?

View File

@ -30,12 +30,6 @@ module Admin
redirect_to admin_invites_path redirect_to admin_invites_path
end end
def deactivate_all
authorize :invite, :deactivate_all?
Invite.available.in_batches.update_all(expires_at: Time.now.utc)
redirect_to admin_invites_path
end
private private
def resource_params def resource_params

View File

@ -1,58 +0,0 @@
# frozen_string_literal: true
module Admin
class RelaysController < BaseController
before_action :set_relay, except: [:index, :new, :create]
def index
authorize :relay, :update?
@relays = Relay.all
end
def new
authorize :relay, :update?
@relay = Relay.new(inbox_url: Relay::PRESET_RELAY)
end
def create
authorize :relay, :update?
@relay = Relay.new(resource_params)
if @relay.save
@relay.enable!
redirect_to admin_relays_path
else
render action: :new
end
end
def destroy
authorize :relay, :update?
@relay.destroy
redirect_to admin_relays_path
end
def enable
authorize :relay, :update?
@relay.enable!
redirect_to admin_relays_path
end
def disable
authorize :relay, :update?
@relay.disable!
redirect_to admin_relays_path
end
private
def set_relay
@relay = Relay.find(params[:id])
end
def resource_params
params.require(:relay).permit(:inbox_url)
end
end
end

View File

@ -44,16 +44,14 @@ module Admin
when 'resolve' when 'resolve'
@report.resolve!(current_account) @report.resolve!(current_account)
log_action :resolve, @report log_action :resolve, @report
when 'disable' when 'suspend'
@report.resolve!(current_account) Admin::SuspensionWorker.perform_async(@report.target_account.id)
@report.target_account.user.disable!
log_action :resolve, @report log_action :resolve, @report
log_action :disable, @report.target_account.user log_action :suspend, @report.target_account
resolve_all_target_account_reports resolve_all_target_account_reports
when 'silence' when 'silence'
@report.resolve!(current_account)
@report.target_account.update!(silenced: true) @report.target_account.update!(silenced: true)
log_action :resolve, @report log_action :resolve, @report
@ -63,7 +61,6 @@ module Admin
else else
raise ActiveRecord::RecordNotFound raise ActiveRecord::RecordNotFound
end end
@report.reload @report.reload
end end

View File

@ -6,7 +6,6 @@ module Admin
site_contact_username site_contact_username
site_contact_email site_contact_email
site_title site_title
site_short_description
site_description site_description
site_extended_description site_extended_description
site_terms site_terms
@ -16,16 +15,13 @@ module Admin
timeline_preview timeline_preview
show_staff_badge show_staff_badge
bootstrap_timeline_accounts bootstrap_timeline_accounts
theme
thumbnail thumbnail
hero hero
mascot
min_invite_role min_invite_role
activity_api_enabled activity_api_enabled
peers_api_enabled peers_api_enabled
show_known_fediverse_at_about_page show_known_fediverse_at_about_page
preview_sensitive_media preview_sensitive_media
custom_css
).freeze ).freeze
BOOLEAN_SETTINGS = %w( BOOLEAN_SETTINGS = %w(
@ -42,7 +38,6 @@ module Admin
UPLOAD_SETTINGS = %w( UPLOAD_SETTINGS = %w(
thumbnail thumbnail
hero hero
mascot
).freeze ).freeze
def edit def edit

View File

@ -28,10 +28,6 @@ module Admin
@form = Form::StatusBatch.new(form_status_batch_params.merge(current_account: current_account, action: action_from_button)) @form = Form::StatusBatch.new(form_status_batch_params.merge(current_account: current_account, action: action_from_button))
flash[:alert] = I18n.t('admin.statuses.failed_to_execute') unless @form.save flash[:alert] = I18n.t('admin.statuses.failed_to_execute') unless @form.save
redirect_to admin_account_statuses_path(@account.id, current_params)
rescue ActionController::ParameterMissing
flash[:alert] = I18n.t('admin.statuses.no_status_selected')
redirect_to admin_account_statuses_path(@account.id, current_params) redirect_to admin_account_statuses_path(@account.id, current_params)
end end

View File

@ -4,24 +4,11 @@ module Admin
class SuspensionsController < BaseController class SuspensionsController < BaseController
before_action :set_account before_action :set_account
def new
@suspension = Form::AdminSuspensionConfirmation.new(report_id: params[:report_id])
end
def create def create
authorize @account, :suspend? authorize @account, :suspend?
Admin::SuspensionWorker.perform_async(@account.id)
@suspension = Form::AdminSuspensionConfirmation.new(suspension_params) log_action :suspend, @account
redirect_to admin_accounts_path
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 end
def destroy def destroy
@ -36,25 +23,5 @@ module Admin
def set_account def set_account
@account = Account.find(params[:account_id]) @account = Account.find(params[:account_id])
end 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
end end

View File

@ -7,8 +7,6 @@ class Api::BaseController < ApplicationController
include RateLimitHeaders include RateLimitHeaders
skip_before_action :store_current_location skip_before_action :store_current_location
skip_before_action :check_user_permissions
protect_from_forgery with: :null_session protect_from_forgery with: :null_session
rescue_from ActiveRecord::RecordInvalid, Mastodon::ValidationError do |e| rescue_from ActiveRecord::RecordInvalid, Mastodon::ValidationError do |e|
@ -53,8 +51,8 @@ class Api::BaseController < ApplicationController
[params[:limit].to_i.abs, default_limit * 2].min [params[:limit].to_i.abs, default_limit * 2].min
end end
def params_slice(*keys) def truthy_param?(key)
params.slice(*keys).permit(*keys) ActiveModel::Type::Boolean.new.cast(params[key])
end end
def current_resource_owner def current_resource_owner

View File

@ -1,32 +0,0 @@
# frozen_string_literal: true
class Api::V1::Accounts::PinsController < Api::BaseController
include Authorization
before_action -> { doorkeeper_authorize! :write, :'write:accounts' }
before_action :require_user!
before_action :set_account
respond_to :json
def create
AccountPin.create!(account: current_account, target_account: @account)
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships_presenter
end
def destroy
pin = AccountPin.find_by(account: current_account, target_account: @account)
pin&.destroy!
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships_presenter
end
private
def set_account
@account = Account.find(params[:account_id])
end
def relationships_presenter
AccountRelationshipsPresenter.new([@account.id], current_user.account_id)
end
end

View File

@ -28,9 +28,10 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
def account_statuses def account_statuses
statuses = truthy_param?(:pinned) ? pinned_scope : permitted_account_statuses statuses = truthy_param?(:pinned) ? pinned_scope : permitted_account_statuses
statuses = statuses.paginate_by_id( statuses = statuses.paginate_by_max_id(
limit_param(DEFAULT_STATUSES_LIMIT), limit_param(DEFAULT_STATUSES_LIMIT),
params_slice(:max_id, :since_id, :min_id) params[:max_id],
params[:since_id]
) )
statuses.merge!(only_media_scope) if truthy_param?(:only_media) statuses.merge!(only_media_scope) if truthy_param?(:only_media)
@ -81,7 +82,7 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
def prev_path def prev_path
unless @statuses.empty? unless @statuses.empty?
api_v1_account_statuses_url pagination_params(min_id: pagination_since_id) api_v1_account_statuses_url pagination_params(since_id: pagination_since_id)
end end
end end

View File

@ -1,71 +0,0 @@
# frozen_string_literal: true
class Api::V1::ConversationsController < Api::BaseController
LIMIT = 20
before_action -> { doorkeeper_authorize! :read, :'read:statuses' }, only: :index
before_action -> { doorkeeper_authorize! :write, :'write:conversations' }, except: :index
before_action :require_user!
before_action :set_conversation, except: :index
after_action :insert_pagination_headers, only: :index
respond_to :json
def index
@conversations = paginated_conversations
render json: @conversations, each_serializer: REST::ConversationSerializer
end
def read
@conversation.update!(unread: false)
render json: @conversation, serializer: REST::ConversationSerializer
end
def destroy
@conversation.destroy!
render_empty
end
private
def set_conversation
@conversation = AccountConversation.where(account: current_account).find(params[:id])
end
def paginated_conversations
AccountConversation.where(account: current_account)
.paginate_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def next_path
if records_continue?
api_v1_conversations_url pagination_params(max_id: pagination_max_id)
end
end
def prev_path
unless @conversations.empty?
api_v1_conversations_url pagination_params(min_id: pagination_since_id)
end
end
def pagination_max_id
@conversations.last.last_status_id
end
def pagination_since_id
@conversations.first.last_status_id
end
def records_continue?
@conversations.size == limit_param(LIMIT)
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
end

View File

@ -1,72 +0,0 @@
# frozen_string_literal: true
class Api::V1::EndorsementsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:accounts' }
before_action :require_user!
after_action :insert_pagination_headers
respond_to :json
def index
@accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
end
private
def load_accounts
if unlimited?
endorsed_accounts.all
else
endorsed_accounts.paginate_by_max_id(
limit_param(DEFAULT_ACCOUNTS_LIMIT),
params[:max_id],
params[:since_id]
)
end
end
def endorsed_accounts
current_account.endorsed_accounts
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def next_path
return if unlimited?
if records_continue?
api_v1_endorsements_url pagination_params(max_id: pagination_max_id)
end
end
def prev_path
return if unlimited?
unless @accounts.empty?
api_v1_endorsements_url pagination_params(since_id: pagination_since_id)
end
end
def pagination_max_id
@accounts.last.id
end
def pagination_since_id
@accounts.first.id
end
def records_continue?
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
def unlimited?
params[:limit] == '0'
end
end

View File

@ -26,9 +26,10 @@ class Api::V1::FavouritesController < Api::BaseController
end end
def results def results
@_results ||= account_favourites.paginate_by_id( @_results ||= account_favourites.paginate_by_max_id(
limit_param(DEFAULT_STATUSES_LIMIT), limit_param(DEFAULT_STATUSES_LIMIT),
params_slice(:max_id, :since_id, :min_id) params[:max_id],
params[:since_id]
) )
end end
@ -48,7 +49,7 @@ class Api::V1::FavouritesController < Api::BaseController
def prev_path def prev_path
unless results.empty? unless results.empty?
api_v1_favourites_url pagination_params(min_id: pagination_since_id) api_v1_favourites_url pagination_params(since_id: pagination_since_id)
end end
end end

View File

@ -13,7 +13,6 @@ class Api::V1::FollowRequestsController < Api::BaseController
def authorize def authorize
AuthorizeFollowService.new.call(account, current_account) AuthorizeFollowService.new.call(account, current_account)
NotifyService.new.call(current_account, Follow.find_by(account: account, target_account: current_account))
render_empty render_empty
end end

View File

@ -4,8 +4,6 @@ class Api::V1::InstancesController < Api::BaseController
respond_to :json respond_to :json
def show def show
render_cached_json('api:v1:instances', expires_in: 5.minutes) do render json: {}, serializer: REST::InstanceSerializer
ActiveModelSerializers::SerializableResource.new({}, serializer: REST::InstanceSerializer)
end
end end
end end

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Lists::AccountsController < Api::BaseController class Api::V1::Lists::AccountsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:lists' }, only: [:show] before_action -> { doorkeeper_authorize! :read, :'read:lists' }, only: [:show]
before_action -> { doorkeeper_authorize! :write, :'write:lists' }, except: [:show] before_action -> { doorkeeper_authorize! :write, :'write:lists' }, except: [:show]
before_action :require_user! before_action :require_user!

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::ListsController < Api::BaseController class Api::V1::ListsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:lists' }, only: [:index, :show] before_action -> { doorkeeper_authorize! :read, :'read:lists' }, only: [:index, :show]
before_action -> { doorkeeper_authorize! :write, :'write:lists' }, except: [:index, :show] before_action -> { doorkeeper_authorize! :write, :'write:lists' }, except: [:index, :show]
before_action :require_user! before_action :require_user!

View File

@ -15,17 +15,19 @@ class Api::V1::MutesController < Api::BaseController
private private
def load_accounts def load_accounts
paginated_mutes.map(&:target_account) default_accounts.merge(paginated_mutes).to_a
end
def default_accounts
Account.includes(:muted_by).references(:muted_by)
end end
def paginated_mutes def paginated_mutes
@paginated_mutes ||= Mute.eager_load(:target_account) Mute.where(account: current_account).paginate_by_max_id(
.where(account: current_account) limit_param(DEFAULT_ACCOUNTS_LIMIT),
.paginate_by_max_id( params[:max_id],
limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:since_id]
params[:max_id], )
params[:since_id]
)
end end
def insert_pagination_headers def insert_pagination_headers
@ -39,21 +41,21 @@ class Api::V1::MutesController < Api::BaseController
end end
def prev_path def prev_path
unless paginated_mutes.empty? unless @accounts.empty?
api_v1_mutes_url pagination_params(since_id: pagination_since_id) api_v1_mutes_url pagination_params(since_id: pagination_since_id)
end end
end end
def pagination_max_id def pagination_max_id
paginated_mutes.last.id @accounts.last.muted_by_ids.last
end end
def pagination_since_id def pagination_since_id
paginated_mutes.first.id @accounts.first.muted_by_ids.first
end end
def records_continue? def records_continue?
paginated_mutes.size == limit_param(DEFAULT_ACCOUNTS_LIMIT) @accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
end end
def pagination_params(core_params) def pagination_params(core_params)

View File

@ -37,9 +37,10 @@ class Api::V1::NotificationsController < Api::BaseController
end end
def paginated_notifications def paginated_notifications
browserable_account_notifications.paginate_by_id( browserable_account_notifications.paginate_by_max_id(
limit_param(DEFAULT_NOTIFICATIONS_LIMIT), limit_param(DEFAULT_NOTIFICATIONS_LIMIT),
params_slice(:max_id, :since_id, :min_id) params[:max_id],
params[:since_id]
) )
end end
@ -63,7 +64,7 @@ class Api::V1::NotificationsController < Api::BaseController
def prev_path def prev_path
unless @notifications.empty? unless @notifications.empty?
api_v1_notifications_url pagination_params(min_id: pagination_since_id) api_v1_notifications_url pagination_params(since_id: pagination_since_id)
end end
end end

View File

@ -1,11 +1,17 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::ReportsController < Api::BaseController class Api::V1::ReportsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:reports' }, except: [:create]
before_action -> { doorkeeper_authorize! :write, :'write:reports' }, only: [:create] before_action -> { doorkeeper_authorize! :write, :'write:reports' }, only: [:create]
before_action :require_user! before_action :require_user!
respond_to :json respond_to :json
def index
@reports = current_account.reports
render json: @reports, each_serializer: REST::ReportSerializer
end
def create def create
@report = ReportService.new.call( @report = ReportService.new.call(
current_account, current_account,
@ -21,7 +27,7 @@ class Api::V1::ReportsController < Api::BaseController
private private
def reported_status_ids def reported_status_ids
reported_account.statuses.find(status_ids).pluck(:id) Status.find(status_ids).pluck(:id)
end end
def status_ids def status_ids

View File

@ -17,7 +17,8 @@ class Api::V1::StatusesController < Api::BaseController
CONTEXT_LIMIT = 4_096 CONTEXT_LIMIT = 4_096
def show def show
@status = cache_collection([@status], Status).first cached = Rails.cache.read(@status.cache_key)
@status = cached unless cached.nil?
render json: @status, serializer: REST::StatusSerializer render json: @status, serializer: REST::StatusSerializer
end end

View File

@ -30,8 +30,7 @@ class Api::V1::Timelines::HomeController < Api::BaseController
account_home_feed.get( account_home_feed.get(
limit_param(DEFAULT_STATUSES_LIMIT), limit_param(DEFAULT_STATUSES_LIMIT),
params[:max_id], params[:max_id],
params[:since_id], params[:since_id]
params[:min_id]
) )
end end
@ -52,7 +51,7 @@ class Api::V1::Timelines::HomeController < Api::BaseController
end end
def prev_path def prev_path
api_v1_timelines_home_url pagination_params(min_id: pagination_since_id) api_v1_timelines_home_url pagination_params(since_id: pagination_since_id)
end end
def pagination_max_id def pagination_max_id

View File

@ -32,8 +32,7 @@ class Api::V1::Timelines::ListController < Api::BaseController
list_feed.get( list_feed.get(
limit_param(DEFAULT_STATUSES_LIMIT), limit_param(DEFAULT_STATUSES_LIMIT),
params[:max_id], params[:max_id],
params[:since_id], params[:since_id]
params[:min_id]
) )
end end
@ -54,7 +53,7 @@ class Api::V1::Timelines::ListController < Api::BaseController
end end
def prev_path def prev_path
api_v1_timelines_list_url params[:id], pagination_params(min_id: pagination_since_id) api_v1_timelines_list_url params[:id], pagination_params(since_id: pagination_since_id)
end end
def pagination_max_id def pagination_max_id

View File

@ -21,9 +21,10 @@ class Api::V1::Timelines::PublicController < Api::BaseController
end end
def public_statuses def public_statuses
statuses = public_timeline_statuses.paginate_by_id( statuses = public_timeline_statuses.paginate_by_max_id(
limit_param(DEFAULT_STATUSES_LIMIT), limit_param(DEFAULT_STATUSES_LIMIT),
params_slice(:max_id, :since_id, :min_id) params[:max_id],
params[:since_id]
) )
if truthy_param?(:only_media) if truthy_param?(:only_media)
@ -52,7 +53,7 @@ class Api::V1::Timelines::PublicController < Api::BaseController
end end
def prev_path def prev_path
api_v1_timelines_public_url pagination_params(min_id: pagination_since_id) api_v1_timelines_public_url pagination_params(since_id: pagination_since_id)
end end
def pagination_max_id def pagination_max_id

View File

@ -29,9 +29,10 @@ class Api::V1::Timelines::TagController < Api::BaseController
if @tag.nil? if @tag.nil?
[] []
else else
statuses = tag_timeline_statuses.paginate_by_id( statuses = tag_timeline_statuses.paginate_by_max_id(
limit_param(DEFAULT_STATUSES_LIMIT), limit_param(DEFAULT_STATUSES_LIMIT),
params_slice(:max_id, :since_id, :min_id) params[:max_id],
params[:since_id]
) )
if truthy_param?(:only_media) if truthy_param?(:only_media)
@ -61,7 +62,7 @@ class Api::V1::Timelines::TagController < Api::BaseController
end end
def prev_path def prev_path
api_v1_timelines_tag_url params[:id], pagination_params(min_id: pagination_since_id) api_v1_timelines_tag_url params[:id], pagination_params(since_id: pagination_since_id)
end end
def pagination_max_id def pagination_max_id

View File

@ -24,7 +24,7 @@ class ApplicationController < ActionController::Base
rescue_from Mastodon::NotPermittedError, with: :forbidden rescue_from Mastodon::NotPermittedError, with: :forbidden
before_action :store_current_location, except: :raise_not_found, unless: :devise_controller? before_action :store_current_location, except: :raise_not_found, unless: :devise_controller?
before_action :check_user_permissions, if: :user_signed_in? before_action :check_suspension, if: :user_signed_in?
def raise_not_found def raise_not_found
raise ActionController::RoutingError, "No route matches #{params[:unmatched_route]}" raise ActionController::RoutingError, "No route matches #{params[:unmatched_route]}"
@ -48,8 +48,8 @@ class ApplicationController < ActionController::Base
forbidden unless current_user&.staff? forbidden unless current_user&.staff?
end end
def check_user_permissions def check_suspension
forbidden if current_user.disabled? || current_user.account.suspended? forbidden if current_user.account.suspended?
end end
def after_sign_out_path_for(_resource_or_scope) def after_sign_out_path_for(_resource_or_scope)
@ -58,10 +58,6 @@ class ApplicationController < ActionController::Base
protected protected
def truthy_param?(key)
ActiveModel::Type::Boolean.new.cast(params[key])
end
def forbidden def forbidden
respond_with_error(403) respond_with_error(403)
end end
@ -99,7 +95,7 @@ class ApplicationController < ActionController::Base
end end
def current_theme def current_theme
return Setting.theme unless Themes.instance.names.include? current_user&.setting_theme return Setting.default_settings['theme'] unless Themes.instance.names.include? current_user&.setting_theme
current_user.setting_theme current_user.setting_theme
end end
@ -107,8 +103,12 @@ class ApplicationController < ActionController::Base
return raw unless klass.respond_to?(:with_includes) return raw unless klass.respond_to?(:with_includes)
raw = raw.cache_ids.to_a if raw.is_a?(ActiveRecord::Relation) raw = raw.cache_ids.to_a if raw.is_a?(ActiveRecord::Relation)
cached_keys_with_value = Rails.cache.read_multi(*raw).transform_keys(&:id) uncached_ids = []
uncached_ids = raw.map(&:id) - cached_keys_with_value.keys cached_keys_with_value = Rails.cache.read_multi(*raw.map(&:cache_key))
raw.each do |item|
uncached_ids << item.id unless cached_keys_with_value.key?(item.cache_key)
end
klass.reload_stale_associations!(cached_keys_with_value.values) if klass.respond_to?(:reload_stale_associations!) klass.reload_stale_associations!(cached_keys_with_value.values) if klass.respond_to?(:reload_stale_associations!)
@ -116,17 +116,16 @@ class ApplicationController < ActionController::Base
uncached = klass.where(id: uncached_ids).with_includes.map { |item| [item.id, item] }.to_h uncached = klass.where(id: uncached_ids).with_includes.map { |item| [item.id, item] }.to_h
uncached.each_value do |item| uncached.each_value do |item|
Rails.cache.write(item, item) Rails.cache.write(item.cache_key, item)
end end
end end
raw.map { |item| cached_keys_with_value[item.id] || uncached[item.id] }.compact raw.map { |item| cached_keys_with_value[item.cache_key] || uncached[item.id] }.compact
end end
def respond_with_error(code) def respond_with_error(code)
respond_to do |format| respond_to do |format|
format.any { head code } format.any { head code }
format.html do format.html do
set_locale set_locale
render "errors/#{code}", layout: 'error', status: code render "errors/#{code}", layout: 'error', status: code
@ -136,6 +135,7 @@ class ApplicationController < ActionController::Base
def render_cached_json(cache_key, **options) def render_cached_json(cache_key, **options)
options[:expires_in] ||= 3.minutes options[:expires_in] ||= 3.minutes
cache_key = cache_key.join(':') if cache_key.is_a?(Enumerable)
cache_public = options.key?(:public) ? options.delete(:public) : true cache_public = options.key?(:public) ? options.delete(:public) : true
content_type = options.delete(:content_type) || 'application/json' content_type = options.delete(:content_type) || 'application/json'

View File

@ -3,7 +3,6 @@
class Auth::ConfirmationsController < Devise::ConfirmationsController class Auth::ConfirmationsController < Devise::ConfirmationsController
layout 'auth' layout 'auth'
before_action :set_body_classes
before_action :set_user, only: [:finish_signup] before_action :set_user, only: [:finish_signup]
# GET/PATCH /users/:id/finish_signup # GET/PATCH /users/:id/finish_signup
@ -24,10 +23,6 @@ class Auth::ConfirmationsController < Devise::ConfirmationsController
@user = current_user @user = current_user
end end
def set_body_classes
@body_classes = 'lighter'
end
def user_params def user_params
params.require(:user).permit(:email) params.require(:user).permit(:email)
end end

View File

@ -2,7 +2,6 @@
class Auth::PasswordsController < Devise::PasswordsController class Auth::PasswordsController < Devise::PasswordsController
before_action :check_validity_of_reset_password_token, only: :edit before_action :check_validity_of_reset_password_token, only: :edit
before_action :set_body_classes
layout 'auth' layout 'auth'
@ -15,10 +14,6 @@ class Auth::PasswordsController < Devise::PasswordsController
end end
end end
def set_body_classes
@body_classes = 'lighter'
end
def reset_password_token_is_valid? def reset_password_token_is_valid?
resource_class.with_reset_password_token(params[:reset_password_token]).present? resource_class.with_reset_password_token(params[:reset_password_token]).present?
end end

View File

@ -8,7 +8,6 @@ class Auth::RegistrationsController < Devise::RegistrationsController
before_action :configure_sign_up_params, only: [:create] before_action :configure_sign_up_params, only: [:create]
before_action :set_sessions, only: [:edit, :update] before_action :set_sessions, only: [:edit, :update]
before_action :set_instance_presenter, only: [:new, :create, :update] before_action :set_instance_presenter, only: [:new, :create, :update]
before_action :set_body_classes, only: [:new, :create, :edit, :update]
def destroy def destroy
not_found not_found
@ -80,10 +79,6 @@ class Auth::RegistrationsController < Devise::RegistrationsController
@instance_presenter = InstancePresenter.new @instance_presenter = InstancePresenter.new
end end
def set_body_classes
@body_classes = %w(edit update).include?(action_name) ? 'admin' : 'lighter'
end
def set_invite def set_invite
@invite = invite_code.present? ? Invite.find_by(code: invite_code) : nil @invite = invite_code.present? ? Invite.find_by(code: invite_code) : nil
end end

View File

@ -6,10 +6,9 @@ class Auth::SessionsController < Devise::SessionsController
layout 'auth' layout 'auth'
skip_before_action :require_no_authentication, only: [:create] skip_before_action :require_no_authentication, only: [:create]
skip_before_action :check_user_permissions, only: [:destroy] skip_before_action :check_suspension, only: [:destroy]
prepend_before_action :authenticate_with_two_factor, if: :two_factor_enabled?, only: [:create] prepend_before_action :authenticate_with_two_factor, if: :two_factor_enabled?, only: [:create]
before_action :set_instance_presenter, only: [:new] before_action :set_instance_presenter, only: [:new]
before_action :set_body_classes
def new def new
Devise.omniauth_configs.each do |provider, config| Devise.omniauth_configs.each do |provider, config|
@ -27,10 +26,8 @@ class Auth::SessionsController < Devise::SessionsController
end end
def destroy def destroy
tmp_stored_location = stored_location_for(:user)
super super
flash.delete(:notice) flash.delete(:notice)
store_location_for(:user, tmp_stored_location) if continue_after?
end end
protected protected
@ -112,10 +109,6 @@ class Auth::SessionsController < Devise::SessionsController
@instance_presenter = InstancePresenter.new @instance_presenter = InstancePresenter.new
end end
def set_body_classes
@body_classes = 'lighter'
end
def home_paths(resource) def home_paths(resource)
paths = [about_path] paths = [about_path]
if single_user_mode? && resource.is_a?(User) if single_user_mode? && resource.is_a?(User)
@ -123,8 +116,4 @@ class Auth::SessionsController < Devise::SessionsController
end end
paths paths
end end
def continue_after?
truthy_param?(:continue)
end
end end

View File

@ -0,0 +1,66 @@
# frozen_string_literal: true
class AuthorizeFollowsController < ApplicationController
layout 'modal'
before_action :authenticate_user!
before_action :set_body_classes
def show
@account = located_account || render(:error)
end
def create
@account = follow_attempt.try(:target_account)
if @account.nil?
render :error
else
render :success
end
rescue ActiveRecord::RecordNotFound, Mastodon::NotPermittedError
render :error
end
private
def follow_attempt
FollowService.new.call(current_account, acct_without_prefix)
end
def located_account
if acct_param_is_url?
account_from_remote_fetch
else
account_from_remote_follow
end
end
def account_from_remote_fetch
FetchRemoteAccountService.new.call(acct_without_prefix)
end
def account_from_remote_follow
ResolveAccountService.new.call(acct_without_prefix)
end
def acct_param_is_url?
parsed_uri.path && %w(http https).include?(parsed_uri.scheme)
end
def parsed_uri
Addressable::URI.parse(acct_without_prefix).normalize
end
def acct_without_prefix
acct_params.gsub(/\Aacct:/, '')
end
def acct_params
params.fetch(:acct, '')
end
def set_body_classes
@body_classes = 'modal-layout'
end
end

View File

@ -1,66 +0,0 @@
# frozen_string_literal: true
class AuthorizeInteractionsController < ApplicationController
include Authorization
layout 'modal'
before_action :authenticate_user!
before_action :set_body_classes
before_action :set_resource
def show
if @resource.is_a?(Account)
render :show
elsif @resource.is_a?(Status)
redirect_to web_url("statuses/#{@resource.id}")
else
render :error
end
end
def create
if @resource.is_a?(Account) && FollowService.new.call(current_account, @resource)
render :success
else
render :error
end
rescue ActiveRecord::RecordNotFound, Mastodon::NotPermittedError
render :error
end
private
def set_resource
@resource = located_resource || render(:error)
authorize(@resource, :show?) if @resource.is_a?(Status)
end
def located_resource
if uri_param_is_url?
ResolveURLService.new.call(uri_param)
else
account_from_remote_follow
end
end
def account_from_remote_follow
ResolveAccountService.new.call(uri_param)
end
def uri_param_is_url?
parsed_uri.path && %w(http https).include?(parsed_uri.scheme)
end
def parsed_uri
Addressable::URI.parse(uri_param).normalize
end
def uri_param
params[:uri] || params.fetch(:acct, '').gsub(/\Aacct:/, '')
end
def set_body_classes
@body_classes = 'modal-layout'
end
end

View File

@ -8,7 +8,6 @@ module AccountControllerConcern
included do included do
layout 'public' layout 'public'
before_action :set_account before_action :set_account
before_action :set_instance_presenter
before_action :set_link_headers before_action :set_link_headers
before_action :check_account_suspension before_action :check_account_suspension
end end
@ -19,10 +18,6 @@ module AccountControllerConcern
@account = Account.find_local!(params[:account_username]) @account = Account.find_local!(params[:account_username])
end end
def set_instance_presenter
@instance_presenter = InstancePresenter.new
end
def set_link_headers def set_link_headers
response.headers['Link'] = LinkHeader.new( response.headers['Link'] = LinkHeader.new(
[ [

View File

@ -22,12 +22,6 @@ module SignatureVerification
return return
end end
if request.headers['Date'].present? && !matches_time_window?
@signature_verification_failure_reason = 'Signed request date outside acceptable time window'
@signed_request_account = nil
return
end
raw_signature = request.headers['Signature'] raw_signature = request.headers['Signature']
signature_params = {} signature_params = {}
@ -82,7 +76,7 @@ module SignatureVerification
def build_signed_string(signed_headers) def build_signed_string(signed_headers)
signed_headers = 'date' if signed_headers.blank? signed_headers = 'date' if signed_headers.blank?
signed_headers.downcase.split(' ').map do |signed_header| signed_headers.split(' ').map do |signed_header|
if signed_header == Request::REQUEST_TARGET if signed_header == Request::REQUEST_TARGET
"#{Request::REQUEST_TARGET}: #{request.method.downcase} #{request.path}" "#{Request::REQUEST_TARGET}: #{request.method.downcase} #{request.path}"
elsif signed_header == 'digest' elsif signed_header == 'digest'
@ -95,12 +89,12 @@ module SignatureVerification
def matches_time_window? def matches_time_window?
begin begin
time_sent = Time.httpdate(request.headers['Date']) time_sent = DateTime.httpdate(request.headers['Date'])
rescue ArgumentError rescue ArgumentError
return false return false
end end
(Time.now.utc - time_sent).abs <= 12.hours (Time.now.utc - time_sent).abs <= 30
end end
def body_digest def body_digest

View File

@ -1,10 +0,0 @@
# frozen_string_literal: true
class CustomCssController < ApplicationController
before_action :set_cache_headers
def show
skip_session!
render plain: Setting.custom_css || '', content_type: 'text/css'
end
end

View File

@ -9,7 +9,7 @@ class EmojisController < ApplicationController
format.json do format.json do
skip_session! skip_session!
render_cached_json(['activitypub', 'emoji', @emoji], content_type: 'application/activity+json') do render_cached_json(['activitypub', 'emoji', @emoji.cache_key], content_type: 'application/activity+json') do
ActiveModelSerializers::SerializableResource.new(@emoji, serializer: ActivityPub::EmojiSerializer, adapter: ActivityPub::Adapter) ActiveModelSerializers::SerializableResource.new(@emoji, serializer: ActivityPub::EmojiSerializer, adapter: ActivityPub::Adapter)
end end
end end

View File

@ -7,7 +7,6 @@ class FiltersController < ApplicationController
before_action :set_filters, only: :index before_action :set_filters, only: :index
before_action :set_filter, only: [:edit, :update, :destroy] before_action :set_filter, only: [:edit, :update, :destroy]
before_action :set_body_classes
def index def index
@filters = current_account.custom_filters @filters = current_account.custom_filters
@ -53,10 +52,6 @@ class FiltersController < ApplicationController
end end
def resource_params def resource_params
params.require(:custom_filter).permit(:phrase, :expires_in, :irreversible, :whole_word, context: []) params.require(:custom_filter).permit(:phrase, :expires_in, :irreversible, context: [])
end
def set_body_classes
@body_classes = 'admin'
end end
end end

View File

@ -58,7 +58,7 @@ class HomeController < ApplicationController
if request.path.start_with?('/web') if request.path.start_with?('/web')
new_user_session_path new_user_session_path
elsif single_user_mode? elsif single_user_mode?
short_account_path(Account.local.where(suspended: false).first) short_account_path(Account.first)
else else
about_path about_path
end end

View File

@ -8,7 +8,7 @@ class IntentsController < ApplicationController
if uri.scheme == 'web+mastodon' if uri.scheme == 'web+mastodon'
case uri.host case uri.host
when 'follow' when 'follow'
return redirect_to authorize_interaction_path(uri: uri.query_values['uri'].gsub(/\Aacct:/, '')) return redirect_to authorize_follow_path(acct: uri.query_values['uri'].gsub(/\Aacct:/, ''))
when 'share' when 'share'
return redirect_to share_path(text: uri.query_values['text']) return redirect_to share_path(text: uri.query_values['text'])
end end

View File

@ -6,7 +6,6 @@ class InvitesController < ApplicationController
layout 'admin' layout 'admin'
before_action :authenticate_user! before_action :authenticate_user!
before_action :set_body_classes
def index def index
authorize :invite, :create? authorize :invite, :create?
@ -39,14 +38,10 @@ class InvitesController < ApplicationController
private private
def invites def invites
Invite.where(user: current_user).order(id: :desc) Invite.where(user: current_user)
end end
def resource_params def resource_params
params.require(:invite).permit(:max_uses, :expires_in, :autofollow) params.require(:invite).permit(:max_uses, :expires_in, :autofollow)
end end
def set_body_classes
@body_classes = 'admin'
end
end end

View File

@ -13,18 +13,4 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
def store_current_location def store_current_location
store_location_for(:user, request.url) store_location_for(:user, request.url)
end end
def render_success
if skip_authorization? || (matching_token? && !truthy_param?('force_login'))
redirect_or_render authorize_response
elsif Doorkeeper.configuration.api_only
render json: pre_auth
else
render :new
end
end
def truthy_param?(key)
ActiveModel::Type::Boolean.new.cast(params[key])
end
end end

View File

@ -42,6 +42,5 @@ class RemoteFollowController < ApplicationController
def set_body_classes def set_body_classes
@body_classes = 'modal-layout' @body_classes = 'modal-layout'
@hide_header = true
end end
end end

View File

@ -1,48 +0,0 @@
# frozen_string_literal: true
class RemoteInteractionController < ApplicationController
include Authorization
layout 'modal'
before_action :set_status
before_action :set_body_classes
def new
@remote_follow = RemoteFollow.new(session_params)
end
def create
@remote_follow = RemoteFollow.new(resource_params)
if @remote_follow.valid?
session[:remote_follow] = @remote_follow.acct
redirect_to @remote_follow.interact_address_for(@status)
else
render :new
end
end
private
def resource_params
params.require(:remote_follow).permit(:acct)
end
def session_params
{ acct: session[:remote_follow] }
end
def set_status
@status = Status.find(params[:id])
authorize @status, :show?
rescue Mastodon::NotPermittedError
# Reraise in order to get a 404
raise ActiveRecord::RecordNotFound
end
def set_body_classes
@body_classes = 'modal-layout'
@hide_header = true
end
end

View File

@ -6,7 +6,6 @@ class Settings::ApplicationsController < ApplicationController
before_action :authenticate_user! before_action :authenticate_user!
before_action :set_application, only: [:show, :update, :destroy, :regenerate] before_action :set_application, only: [:show, :update, :destroy, :regenerate]
before_action :prepare_scopes, only: [:create, :update] before_action :prepare_scopes, only: [:create, :update]
before_action :set_body_classes
def index def index
@applications = current_user.applications.order(id: :desc).page(params[:page]) @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) scopes = params.fetch(:doorkeeper_application, {}).fetch(:scopes, nil)
params[:doorkeeper_application][:scopes] = scopes.join(' ') if scopes.is_a? Array params[:doorkeeper_application][:scopes] = scopes.join(' ') if scopes.is_a? Array
end end
def set_body_classes
@body_classes = 'admin'
end
end end

View File

@ -5,7 +5,6 @@ class Settings::DeletesController < ApplicationController
before_action :check_enabled_deletion before_action :check_enabled_deletion
before_action :authenticate_user! before_action :authenticate_user!
before_action :set_body_classes
def show def show
@confirmation = Form::DeleteConfirmation.new @confirmation = Form::DeleteConfirmation.new
@ -30,8 +29,4 @@ class Settings::DeletesController < ApplicationController
def delete_params def delete_params
params.require(:form_delete_confirmation).permit(:password) params.require(:form_delete_confirmation).permit(:password)
end end
def set_body_classes
@body_classes = 'admin'
end
end end

View File

@ -6,7 +6,6 @@ class Settings::ExportsController < ApplicationController
layout 'admin' layout 'admin'
before_action :authenticate_user! before_action :authenticate_user!
before_action :set_body_classes
def show def show
@export = Export.new(current_account) @export = Export.new(current_account)
@ -21,10 +20,4 @@ class Settings::ExportsController < ApplicationController
redirect_to settings_export_path redirect_to settings_export_path
end end
private
def set_body_classes
@body_classes = 'admin'
end
end end

View File

@ -4,7 +4,6 @@ class Settings::FollowerDomainsController < ApplicationController
layout 'admin' layout 'admin'
before_action :authenticate_user! before_action :authenticate_user!
before_action :set_body_classes
def show def show
@account = current_account @account = current_account
@ -26,8 +25,4 @@ class Settings::FollowerDomainsController < ApplicationController
def bulk_params def bulk_params
params.permit(select: []) params.permit(select: [])
end end
def set_body_classes
@body_classes = 'admin'
end
end end

View File

@ -5,7 +5,6 @@ class Settings::ImportsController < ApplicationController
before_action :authenticate_user! before_action :authenticate_user!
before_action :set_account before_action :set_account
before_action :set_body_classes
def show def show
@import = Import.new @import = Import.new
@ -32,8 +31,4 @@ class Settings::ImportsController < ApplicationController
def import_params def import_params
params.require(:import).permit(:data, :type) params.require(:import).permit(:data, :type)
end end
def set_body_classes
@body_classes = 'admin'
end
end end

View File

@ -4,7 +4,6 @@ class Settings::MigrationsController < ApplicationController
layout 'admin' layout 'admin'
before_action :authenticate_user! before_action :authenticate_user!
before_action :set_body_classes
def show def show
@migration = Form::Migration.new(account: current_account.moved_to_account) @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.moved_to_account_id != @migration.account&.id &&
current_account.id != @migration.account&.id current_account.id != @migration.account&.id
end end
def set_body_classes
@body_classes = 'admin'
end
end end

View File

@ -4,7 +4,6 @@ class Settings::NotificationsController < ApplicationController
layout 'admin' layout 'admin'
before_action :authenticate_user! before_action :authenticate_user!
before_action :set_body_classes
def show; end def show; end
@ -26,12 +25,8 @@ class Settings::NotificationsController < ApplicationController
def user_settings_params def user_settings_params
params.require(:user).permit( params.require(:user).permit(
notification_emails: %i(follow follow_request reblog favourite mention digest report), notification_emails: %i(follow follow_request reblog favourite mention digest),
interactions: %i(must_be_follower must_be_following must_be_following_dm) interactions: %i(must_be_follower must_be_following must_be_following_dm)
) )
end end
def set_body_classes
@body_classes = 'admin'
end
end end

View File

@ -4,7 +4,6 @@ class Settings::PreferencesController < ApplicationController
layout 'admin' layout 'admin'
before_action :authenticate_user! before_action :authenticate_user!
before_action :set_body_classes
def show; end def show; end
@ -41,19 +40,14 @@ class Settings::PreferencesController < ApplicationController
:setting_boost_modal, :setting_boost_modal,
:setting_delete_modal, :setting_delete_modal,
:setting_auto_play_gif, :setting_auto_play_gif,
:setting_display_media, :setting_display_sensitive_media,
:setting_expand_spoilers,
:setting_reduce_motion, :setting_reduce_motion,
:setting_system_font_ui, :setting_system_font_ui,
:setting_noindex, :setting_noindex,
:setting_theme, :setting_theme,
:setting_hide_network, :setting_hide_network,
notification_emails: %i(follow follow_request reblog favourite mention digest report), notification_emails: %i(follow follow_request reblog favourite mention digest),
interactions: %i(must_be_follower must_be_following) interactions: %i(must_be_follower must_be_following)
) )
end end
def set_body_classes
@body_classes = 'admin'
end
end end

View File

@ -7,7 +7,6 @@ class Settings::ProfilesController < ApplicationController
before_action :authenticate_user! before_action :authenticate_user!
before_action :set_account before_action :set_account
before_action :set_body_classes
obfuscate_filename [:account, :avatar] obfuscate_filename [:account, :avatar]
obfuscate_filename [:account, :header] obfuscate_filename [:account, :header]
@ -35,8 +34,4 @@ class Settings::ProfilesController < ApplicationController
def set_account def set_account
@account = current_user.account @account = current_user.account
end end
def set_body_classes
@body_classes = 'admin'
end
end end

View File

@ -2,7 +2,6 @@
class Settings::SessionsController < ApplicationController class Settings::SessionsController < ApplicationController
before_action :set_session, only: :destroy before_action :set_session, only: :destroy
before_action :set_body_classes
def destroy def destroy
@session.destroy! @session.destroy!
@ -15,8 +14,4 @@ class Settings::SessionsController < ApplicationController
def set_session def set_session
@session = current_user.session_activations.find(params[:id]) @session = current_user.session_activations.find(params[:id])
end end
def set_body_classes
@body_classes = 'admin'
end
end end

View File

@ -7,7 +7,6 @@ module Settings
before_action :authenticate_user! before_action :authenticate_user!
before_action :ensure_otp_secret before_action :ensure_otp_secret
before_action :set_body_classes
def new def new
prepare_two_factor_form prepare_two_factor_form
@ -44,10 +43,6 @@ module Settings
def ensure_otp_secret def ensure_otp_secret
redirect_to settings_two_factor_authentication_path unless current_user.otp_secret redirect_to settings_two_factor_authentication_path unless current_user.otp_secret
end end
def set_body_classes
@body_classes = 'admin'
end
end end
end end
end end

View File

@ -6,7 +6,6 @@ module Settings
layout 'admin' layout 'admin'
before_action :authenticate_user! before_action :authenticate_user!
before_action :set_body_classes
def create def create
@recovery_codes = current_user.generate_otp_backup_codes! @recovery_codes = current_user.generate_otp_backup_codes!
@ -14,12 +13,6 @@ module Settings
flash[:notice] = I18n.t('two_factor_authentication.recovery_codes_regenerated') flash[:notice] = I18n.t('two_factor_authentication.recovery_codes_regenerated')
render :index render :index
end end
private
def set_body_classes
@body_classes = 'admin'
end
end end
end end
end end

View File

@ -6,7 +6,6 @@ module Settings
before_action :authenticate_user! before_action :authenticate_user!
before_action :verify_otp_required, only: [:create] before_action :verify_otp_required, only: [:create]
before_action :set_body_classes
def show def show
@confirmation = Form::TwoFactorConfirmation.new @confirmation = Form::TwoFactorConfirmation.new
@ -44,9 +43,5 @@ module Settings
current_user.validate_and_consume_otp!(confirmation_params[:code]) || current_user.validate_and_consume_otp!(confirmation_params[:code]) ||
current_user.invalidate_otp_backup_code!(confirmation_params[:code]) current_user.invalidate_otp_backup_code!(confirmation_params[:code])
end end
def set_body_classes
@body_classes = 'admin'
end
end end
end end

View File

@ -12,22 +12,15 @@ class StatusesController < ApplicationController
before_action :set_account before_action :set_account
before_action :set_status before_action :set_status
before_action :set_instance_presenter
before_action :set_link_headers before_action :set_link_headers
before_action :check_account_suspension before_action :check_account_suspension
before_action :redirect_to_original, only: [:show] before_action :redirect_to_original, only: [:show]
before_action :set_referrer_policy_header, only: [:show] before_action :set_referrer_policy_header, only: [:show]
before_action :set_cache_headers before_action :set_cache_headers
content_security_policy only: :embed do |p|
p.frame_ancestors(false)
end
def show def show
respond_to do |format| respond_to do |format|
format.html do format.html do
@body_classes = 'with-modals'
set_ancestors set_ancestors
set_descendants set_descendants
@ -37,7 +30,7 @@ class StatusesController < ApplicationController
format.json do format.json do
skip_session! unless @stream_entry.hidden? skip_session! unless @stream_entry.hidden?
render_cached_json(['activitypub', 'note', @status], content_type: 'application/activity+json', public: !@stream_entry.hidden?) do render_cached_json(['activitypub', 'note', @status.cache_key], content_type: 'application/activity+json', public: !@stream_entry.hidden?) do
ActiveModelSerializers::SerializableResource.new(@status, serializer: ActivityPub::NoteSerializer, adapter: ActivityPub::Adapter) ActiveModelSerializers::SerializableResource.new(@status, serializer: ActivityPub::NoteSerializer, adapter: ActivityPub::Adapter)
end end
end end
@ -47,7 +40,7 @@ class StatusesController < ApplicationController
def activity def activity
skip_session! skip_session!
render_cached_json(['activitypub', 'activity', @status], content_type: 'application/activity+json', public: !@stream_entry.hidden?) do render_cached_json(['activitypub', 'activity', @status.cache_key], content_type: 'application/activity+json', public: !@stream_entry.hidden?) do
ActiveModelSerializers::SerializableResource.new(@status, serializer: ActivityPub::ActivitySerializer, adapter: ActivityPub::Adapter) ActiveModelSerializers::SerializableResource.new(@status, serializer: ActivityPub::ActivitySerializer, adapter: ActivityPub::Adapter)
end end
end end
@ -58,7 +51,6 @@ class StatusesController < ApplicationController
skip_session! skip_session!
expires_in 180, public: true expires_in 180, public: true
response.headers['X-Frame-Options'] = 'ALLOWALL' response.headers['X-Frame-Options'] = 'ALLOWALL'
@autoplay = ActiveModel::Type::Boolean.new.cast(params[:autoplay])
render 'stream_entries/embed', layout: 'embedded' render 'stream_entries/embed', layout: 'embedded'
end end
@ -156,10 +148,6 @@ class StatusesController < ApplicationController
raise ActiveRecord::RecordNotFound raise ActiveRecord::RecordNotFound
end end
def set_instance_presenter
@instance_presenter = InstancePresenter.new
end
def check_account_suspension def check_account_suspension
gone if @account.suspended? gone if @account.suspended?
end end

View File

@ -37,7 +37,7 @@ class TagsController < ApplicationController
private private
def set_body_classes def set_body_classes
@body_classes = 'with-modals' @body_classes = 'tag-body'
end end
def set_instance_presenter def set_instance_presenter

View File

@ -2,9 +2,7 @@
module Admin::AccountModerationNotesHelper module Admin::AccountModerationNotesHelper
def admin_account_link_to(account) def admin_account_link_to(account)
return if account.nil? link_to admin_account_path(account.id), class: name_tag_classes(account) do
link_to admin_account_path(account.id), class: name_tag_classes(account), title: account.acct do
safe_join([ safe_join([
image_tag(account.avatar.url, width: 15, height: 15, alt: display_name(account), class: 'avatar'), image_tag(account.avatar.url, width: 15, height: 15, alt: display_name(account), class: 'avatar'),
content_tag(:span, account.acct, class: 'username'), content_tag(:span, account.acct, class: 'username'),
@ -13,9 +11,7 @@ module Admin::AccountModerationNotesHelper
end end
def admin_account_inline_link_to(account) def admin_account_inline_link_to(account)
return if account.nil? link_to admin_account_path(account.id), class: name_tag_classes(account, true) do
link_to admin_account_path(account.id), class: name_tag_classes(account, true), title: account.acct do
content_tag(:span, account.acct, class: 'username') content_tag(:span, account.acct, class: 'username')
end end
end end

View File

@ -33,12 +33,8 @@ module Admin::ActionLogsHelper
when 'DomainBlock', 'EmailDomainBlock' when 'DomainBlock', 'EmailDomainBlock'
link_to attributes['domain'], "https://#{attributes['domain']}" link_to attributes['domain'], "https://#{attributes['domain']}"
when 'Status' when 'Status'
tmp_status = Status.new(attributes.except('reblogs_count', 'favourites_count')) tmp_status = Status.new(attributes)
if tmp_status.account link_to tmp_status.account&.acct || "##{tmp_status.account_id}", TagManager.instance.url_for(tmp_status)
link_to tmp_status.account&.acct || "##{tmp_status.account_id}", admin_account_path(tmp_status.account_id)
else
I18n.t('admin.action_logs.deleted_status')
end
end end
end end

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module Admin::FilterHelper 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 silenced suspended recent username display_name email ip staff).freeze
REPORT_FILTERS = %i(resolved account_id target_account_id).freeze REPORT_FILTERS = %i(resolved account_id target_account_id).freeze
INVITE_FILTER = %i(available expired).freeze INVITE_FILTER = %i(available expired).freeze
CUSTOM_EMOJI_FILTERS = %i(local remote by_domain shortcode).freeze CUSTOM_EMOJI_FILTERS = %i(local remote by_domain shortcode).freeze

View File

@ -7,8 +7,8 @@ module ApplicationHelper
follow follow
).freeze ).freeze
def active_nav_class(*paths) def active_nav_class(path)
paths.any? { |path| current_page?(path) } ? 'active' : '' current_page?(path) ? 'active' : ''
end end
def active_link_to(label, path, **options) def active_link_to(label, path, **options)
@ -27,6 +27,11 @@ module ApplicationHelper
Setting.open_deletion Setting.open_deletion
end end
def add_rtl_body_class(other_classes)
other_classes = "#{other_classes} rtl" if locale_direction == 'rtl'
other_classes
end
def locale_direction def locale_direction
if [:ar, :fa, :he].include?(I18n.locale) if [:ar, :fa, :he].include?(I18n.locale)
'rtl' 'rtl'
@ -72,29 +77,4 @@ module ApplicationHelper
def react_component(name, props = {}) def react_component(name, props = {})
content_tag(:div, nil, data: { component: name.to_s.camelcase, props: Oj.dump(props) }) content_tag(:div, nil, data: { component: name.to_s.camelcase, props: Oj.dump(props) })
end end
def body_classes
output = (@body_classes || '').split(' ')
output << "theme-#{current_theme.parameterize}"
output << 'system-font' if current_account&.user&.setting_system_font_ui
output << (current_account&.user&.setting_reduce_motion ? 'reduce-motion' : 'no-reduce-motion')
output << 'rtl' if locale_direction == 'rtl'
output.reject(&:blank?).join(' ')
end
def cdn_host
Rails.configuration.action_controller.asset_host
end
def cdn_host?
cdn_host.present?
end
def storage_host
"https://#{ENV['S3_ALIAS_HOST'].presence || ENV['S3_CLOUDFRONT_HOST']}"
end
def storage_host?
ENV['S3_ALIAS_HOST'].present? || ENV['S3_CLOUDFRONT_HOST'].present?
end
end end

View File

@ -6,54 +6,4 @@ module HomeHelper
locale: I18n.locale, locale: I18n.locale,
} }
end end
def account_link_to(account, button = '', size: 36, path: nil)
content_tag(:div, class: 'account') do
content_tag(:div, class: 'account__wrapper') do
section = if account.nil?
content_tag(:div, 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(#{full_asset_url('avatars/original/missing.png', skip_pipeline: true)})")
end +
content_tag(:span, class: 'display-name') do
content_tag(:strong, t('about.contact_missing')) +
content_tag(:span, t('about.contact_unavailable'), class: 'display-name__account')
end
end
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})")
end +
content_tag(:span, class: 'display-name') do
content_tag(:bdi) do
content_tag(:strong, display_name(account, custom_emojify: true), class: 'display-name__html emojify')
end +
content_tag(:span, "@#{account.acct}", class: 'display-name__account')
end
end
end
section + button
end
end
end
def obscured_counter(count)
if count <= 0
0
elsif count == 1
1
else
'1+'
end
end
def custom_field_classes(field)
if field.verified?
'verified'
else
'emojify'
end
end
end end

View File

@ -5,12 +5,9 @@ module SettingsHelper
en: 'English', en: 'English',
'en-CY': 'English (Cybre)', 'en-CY': 'English (Cybre)',
ar: 'العربية', ar: 'العربية',
ast: 'l\'asturianu',
bg: 'Български', bg: 'Български',
ca: 'Català', ca: 'Català',
co: 'Corsu', co: 'Corsu',
cs: 'Čeština',
cy: 'Cymraeg',
da: 'Dansk', da: 'Dansk',
de: 'Deutsch', de: 'Deutsch',
el: 'Ελληνικά', el: 'Ελληνικά',
@ -29,7 +26,6 @@ module SettingsHelper
io: 'Ido', io: 'Ido',
it: 'Italiano', it: 'Italiano',
ja: '日本語', ja: '日本語',
ka: 'ქართული',
ko: '한국어', ko: '한국어',
nl: 'Nederlands', nl: 'Nederlands',
no: 'Norsk', no: 'Norsk',
@ -37,14 +33,12 @@ module SettingsHelper
pl: 'Polszczyzna', pl: 'Polszczyzna',
pt: 'Português', pt: 'Português',
'pt-BR': 'Português do Brasil', 'pt-BR': 'Português do Brasil',
ro: 'Limba română',
ru: 'Русский', ru: 'Русский',
sk: 'Slovenčina', sk: 'Slovensky',
sl: 'Slovenščina', sl: 'Slovenščina',
sr: 'Српски', sr: 'Српски',
'sr-Latn': 'Srpski (latinica)', 'sr-Latn': 'Srpski (latinica)',
sv: 'Svenska', sv: 'Svenska',
ta: 'தமிழ்',
te: 'తెలుగు', te: 'తెలుగు',
th: 'ภาษาไทย', th: 'ภาษาไทย',
tr: 'Türkçe', tr: 'Türkçe',

View File

@ -12,67 +12,21 @@ module StreamEntriesHelper
end end
end end
def account_action_button(account)
if user_signed_in?
if account.id == current_user.account_id
link_to settings_profile_url, class: 'button logo-button' do
safe_join([render(file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')), t('settings.edit_profile')])
end
elsif current_account.following?(account) || current_account.requested?(account)
link_to account_unfollow_path(account), class: 'button logo-button button--destructive', data: { method: :post } do
safe_join([render(file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')), t('accounts.unfollow')])
end
elsif !(account.memorial? || account.moved?)
link_to account_follow_path(account), class: 'button logo-button', data: { method: :post } do
safe_join([render(file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')), t('accounts.follow')])
end
end
elsif !(account.memorial? || account.moved?)
link_to account_remote_follow_path(account), class: 'button logo-button modal-button', target: '_new' do
safe_join([render(file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')), t('accounts.follow')])
end
end
end
def account_badge(account)
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?
content_tag(:div, class: 'roles') do
if 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')
end
end
end
end
def link_to_more(url)
link_to t('statuses.show_more'), url, class: 'load-more load-gap'
end
def nothing_here(extra_classes = '')
content_tag(:div, class: "nothing-here #{extra_classes}") do
t('accounts.nothing_here')
end
end
def account_description(account) def account_description(account)
prepend_str = [ prepend_str = [
[ [
number_to_human(account.statuses_count, strip_insignificant_zeros: true), number_to_human(account.statuses_count, strip_insignificant_zeros: true),
I18n.t('accounts.posts', count: account.statuses_count), I18n.t('accounts.posts'),
].join(' '), ].join(' '),
[ [
number_to_human(account.following_count, strip_insignificant_zeros: true), number_to_human(account.following_count, strip_insignificant_zeros: true),
I18n.t('accounts.following', count: account.following_count), I18n.t('accounts.following'),
].join(' '), ].join(' '),
[ [
number_to_human(account.followers_count, strip_insignificant_zeros: true), number_to_human(account.followers_count, strip_insignificant_zeros: true),
I18n.t('accounts.followers', count: account.followers_count), I18n.t('accounts.followers'),
].join(' '), ].join(' '),
].join(', ') ].join(', ')
@ -113,7 +67,7 @@ module StreamEntriesHelper
end end
def acct(account) def acct(account)
if account.local? if embedded_view? && account.local?
"@#{account.acct}@#{Rails.configuration.x.local_domain}" "@#{account.acct}@#{Rails.configuration.x.local_domain}"
else else
"@#{account.acct}" "@#{account.acct}"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 423 B

After

Width:  |  Height:  |  Size: 582 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 253 B

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 387 B

After

Width:  |  Height:  |  Size: 520 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 225 B

After

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 412 B

After

Width:  |  Height:  |  Size: 541 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 387 B

After

Width:  |  Height:  |  Size: 550 B

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