Compare commits

..

19 Commits

Author SHA1 Message Date
kibigo!
da2b6dda6a This is a better way of detecting frontends 2017-06-22 21:10:02 -07:00
kibigo!
ed82421870 Forgot to delete a debugging thing sry 😰 2017-06-22 20:38:08 -07:00
kibigo!
b3904c2553 MORE FRONTENDS (EASY MODE) WIN!!! 2017-06-22 20:15:11 -07:00
beatrix
101a4c6913 glitch the getting started image 2017-06-22 13:04:56 -04:00
kibigo!
11da74dbb7 Very minor styling improvements to toot-collapsing 2017-06-22 00:54:33 -07:00
kibigo!
51a86b32c3 Updates height upon collapsing 2017-06-21 20:17:12 -07:00
kibigo!
51b783cdbc Minor collapsing button improvements~ 2017-06-21 19:54:41 -07:00
kibigo!
3915f06b02 Collapsable toots [1/??] 2017-06-21 19:40:53 -07:00
kibigo!
07b1171c73 Profile Metadata HACK 😈 2017-06-20 19:44:43 -07:00
Go Shoemake
571576d6f7 Fixes drawer so stuff doesn't overflow 2017-06-20 23:46:17 +00:00
Charlotte Fields
7151ec7680 cybre cleanup 2017-06-20 23:46:17 +00:00
Chronister
a4b3009c1c cybrespace to 1.4.2 2017-06-20 23:46:17 +00:00
Chronister
ef30a92c71 All cybrespace changes through 5/28 2017-06-20 23:46:17 +00:00
Charlotte Fields
613aa55e03 adding cybre changes 2017-06-20 23:46:17 +00:00
beatrix-bitrot
88a08d54b6 update local modifications for cors and cp 2017-06-20 23:46:17 +00:00
beatrix-bitrot
3a69d70eae silly readme update to test automated deploys 2017-06-20 23:46:17 +00:00
beatrix-bitrot
9c778f4abf update README.md 2017-06-20 23:46:17 +00:00
beatrix
ac61ce5826 Update README.md 2017-06-20 23:46:17 +00:00
Beatrix Bitrot
73d6da32be CORS tweaks 2017-06-20 23:46:17 +00:00
6444 changed files with 24478 additions and 107724 deletions

View File

@@ -15,15 +15,13 @@
"plugins": [ "plugins": [
"syntax-dynamic-import", "syntax-dynamic-import",
["transform-object-rest-spread", { "useBuiltIns": true }], ["transform-object-rest-spread", { "useBuiltIns": true }],
"transform-decorators-legacy",
"transform-class-properties", "transform-class-properties",
[ [
"react-intl", "react-intl",
{ {
"messagesDir": "./build/messages" "messagesDir": "./build/messages"
} }
], ]
"preval"
], ],
"env": { "env": {
"development": { "development": {
@@ -45,7 +43,6 @@
] ]
} }
], ],
"transform-react-inline-elements",
[ [
"transform-runtime", "transform-runtime",
{ {

View File

@@ -1,36 +1,21 @@
version: "2" engines:
checks:
argument-count:
enabled: false
complex-logic:
enabled: false
file-lines:
enabled: false
method-complexity:
enabled: false
method-count:
enabled: false
method-lines:
enabled: false
nested-control-flow:
enabled: false
return-statements:
enabled: false
similar-code:
enabled: false
identical-code:
enabled: false
plugins:
brakeman: brakeman:
enabled: true enabled: true
bundler-audit: bundler-audit:
enabled: true enabled: true
duplication:
enabled: false
eslint: eslint:
enabled: true enabled: true
rubocop: rubocop:
enabled: true enabled: true
scss-lint: scss-lint:
enabled: true enabled: true
exclude_patterns: ratings:
paths:
- "**.rb"
- "**.js"
- "**.scss"
exclude_paths:
- spec/ - spec/
- vendor/asset - vendor/asset

View File

@@ -4,6 +4,7 @@ public/system
public/assets public/assets
public/packs public/packs
node_modules node_modules
storybook
neo4j neo4j
vendor/bundle vendor/bundle
.DS_Store .DS_Store

View File

@@ -35,17 +35,6 @@ PAPERCLIP_SECRET=$PAPERCLIP_SECRET
SECRET_KEY_BASE=$SECRET_KEY_BASE SECRET_KEY_BASE=$SECRET_KEY_BASE
OTP_SECRET=$OTP_SECRET OTP_SECRET=$OTP_SECRET
# VAPID keys (used for push notifications)
# You can generate the keys using the following command (first is the private key, second is the public one)
# You should only generate this once per instance. If you later decide to change it, all push subscription will
# be invalidated, requiring the users to access the website again to resubscribe.
#
# Generate with `rake mastodon:webpush:generate_vapid_key` task (`nanobox run bundle exec rake mastodon:webpush:generate_vapid_key`)
#
# For more information visit https://rossta.net/blog/using-the-web-push-api-with-vapid.html
VAPID_PRIVATE_KEY=$VAPID_PRIVATE_KEY
VAPID_PUBLIC_KEY=$VAPID_PUBLIC_KEY
# Registrations # Registrations
# Single user mode will disable registrations and redirect frontpage to the first profile # Single user mode will disable registrations and redirect frontpage to the first profile
# SINGLE_USER_MODE=true # SINGLE_USER_MODE=true
@@ -73,14 +62,14 @@ SMTP_FROM_ADDRESS=notifications@${APP_NAME}.nanoapp.io
#SMTP_CA_FILE=/etc/ssl/certs/ca-certificates.crt #SMTP_CA_FILE=/etc/ssl/certs/ca-certificates.crt
#SMTP_OPENSSL_VERIFY_MODE=peer #SMTP_OPENSSL_VERIFY_MODE=peer
#SMTP_ENABLE_STARTTLS_AUTO=true #SMTP_ENABLE_STARTTLS_AUTO=true
#SMTP_TLS=true
# Optional user upload path and URL (images, avatars). Default is :rails_root/public/system. If you set this variable, you are responsible for making your HTTP server (eg. nginx) serve these files. # Optional user upload path and URL (images, avatars). Default is :rails_root/public/system. If you set this variable, you are responsible for making your HTTP server (eg. nginx) serve these files.
# PAPERCLIP_ROOT_PATH=/var/lib/mastodon/public-system # PAPERCLIP_ROOT_PATH=/var/lib/mastodon/public-system
# PAPERCLIP_ROOT_URL=/system # PAPERCLIP_ROOT_URL=/system
# Optional asset host for multi-server setups # Optional asset host for multi-server setups
# CDN_HOST=https://assets.example.com # CDN_HOST=assets.example.com
# S3 (optional) # S3 (optional)
# S3_ENABLED=true # S3_ENABLED=true
@@ -102,23 +91,6 @@ SMTP_FROM_ADDRESS=notifications@${APP_NAME}.nanoapp.io
# S3_ENDPOINT= # S3_ENDPOINT=
# S3_SIGNATURE_VERSION= # S3_SIGNATURE_VERSION=
# Swift (optional)
# SWIFT_ENABLED=true
# SWIFT_USERNAME=
# For Keystone V3, the value for SWIFT_TENANT should be the project name
# SWIFT_TENANT=
# SWIFT_PASSWORD=
# Keystone V2 and V3 URLs are supported. Use a V3 URL if possible to avoid
# issues with token rate-limiting during high load.
# SWIFT_AUTH_URL=
# SWIFT_CONTAINER=
# SWIFT_OBJECT_URL=
# SWIFT_REGION=
# Defaults to 'default'
# SWIFT_DOMAIN_NAME=
# Defaults to 60 seconds. Set to 0 to disable
# SWIFT_CACHE_TTL=
# Optional alias for S3 if you want to use Cloudfront or Cloudflare in front # Optional alias for S3 if you want to use Cloudfront or Cloudflare in front
# S3_CLOUDFRONT_HOST= # S3_CLOUDFRONT_HOST=

View File

@@ -1,6 +1,5 @@
# Service dependencies # Service dependencies
# You may set REDIS_URL instead for more advanced options # You may set REDIS_URL instead for more advanced options
# You may also set REDIS_NAMESPACE to share Redis between multiple Mastodon servers
REDIS_HOST=redis REDIS_HOST=redis
REDIS_PORT=6379 REDIS_PORT=6379
# You may set DATABASE_URL instead for more advanced options # You may set DATABASE_URL instead for more advanced options
@@ -11,11 +10,10 @@ DB_PASS=
DB_PORT=5432 DB_PORT=5432
# Federation # Federation
# Note: Changing LOCAL_DOMAIN at a later time will cause unwanted side effects, including breaking all existing federation. # Note: Changing LOCAL_DOMAIN or LOCAL_HTTPS at a later time will cause unwanted side effects.
# LOCAL_DOMAIN should *NOT* contain the protocol part of the domain e.g https://example.com. # LOCAL_DOMAIN should *NOT* contain the protocol part of the domain e.g https://example.com.
LOCAL_DOMAIN=example.com LOCAL_DOMAIN=example.com
LOCAL_HTTPS=true
# Changing LOCAL_HTTPS in production is no longer supported. (Mastodon will always serve https:// links)
# Use this only if you need to run mastodon on a different domain than the one used for federation. # Use this only if you need to run mastodon on a different domain than the one used for federation.
# You can read more about this option on https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Serving_a_different_domain.md # You can read more about this option on https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Serving_a_different_domain.md
@@ -28,22 +26,11 @@ LOCAL_DOMAIN=example.com
# ALTERNATE_DOMAINS=example1.com,example2.com # ALTERNATE_DOMAINS=example1.com,example2.com
# Application secrets # Application secrets
# Generate each with the `RAILS_ENV=production bundle exec rake secret` task (`docker-compose run --rm web rake secret` if you use docker compose) # Generate each with the `rake secret` task (`docker-compose run --rm web rake secret` if you use docker compose)
PAPERCLIP_SECRET= PAPERCLIP_SECRET=
SECRET_KEY_BASE= SECRET_KEY_BASE=
OTP_SECRET= OTP_SECRET=
# VAPID keys (used for push notifications
# You can generate the keys using the following command (first is the private key, second is the public one)
# You should only generate this once per instance. If you later decide to change it, all push subscription will
# be invalidated, requiring the users to access the website again to resubscribe.
#
# Generate with `RAILS_ENV=production bundle exec rake mastodon:webpush:generate_vapid_key` task (`docker-compose run --rm web rake mastodon:webpush:generate_vapid_key` if you use docker compose)
#
# For more information visit https://rossta.net/blog/using-the-web-push-api-with-vapid.html
VAPID_PRIVATE_KEY=
VAPID_PUBLIC_KEY=
# Registrations # Registrations
# Single user mode will disable registrations and redirect frontpage to the first profile # Single user mode will disable registrations and redirect frontpage to the first profile
# SINGLE_USER_MODE=true # SINGLE_USER_MODE=true
@@ -71,7 +58,7 @@ SMTP_FROM_ADDRESS=notifications@example.com
#SMTP_CA_FILE=/etc/ssl/certs/ca-certificates.crt #SMTP_CA_FILE=/etc/ssl/certs/ca-certificates.crt
#SMTP_OPENSSL_VERIFY_MODE=peer #SMTP_OPENSSL_VERIFY_MODE=peer
#SMTP_ENABLE_STARTTLS_AUTO=true #SMTP_ENABLE_STARTTLS_AUTO=true
#SMTP_TLS=true
# Optional user upload path and URL (images, avatars). Default is :rails_root/public/system. If you set this variable, you are responsible for making your HTTP server (eg. nginx) serve these files. # Optional user upload path and URL (images, avatars). Default is :rails_root/public/system. If you set this variable, you are responsible for making your HTTP server (eg. nginx) serve these files.
# PAPERCLIP_ROOT_PATH=/var/lib/mastodon/public-system # PAPERCLIP_ROOT_PATH=/var/lib/mastodon/public-system
@@ -100,23 +87,6 @@ SMTP_FROM_ADDRESS=notifications@example.com
# S3_ENDPOINT= # S3_ENDPOINT=
# S3_SIGNATURE_VERSION= # S3_SIGNATURE_VERSION=
# Swift (optional)
# SWIFT_ENABLED=true
# SWIFT_USERNAME=
# For Keystone V3, the value for SWIFT_TENANT should be the project name
# SWIFT_TENANT=
# SWIFT_PASSWORD=
# Keystone V2 and V3 URLs are supported. Use a V3 URL if possible to avoid
# issues with token rate-limiting during high load.
# SWIFT_AUTH_URL=
# SWIFT_CONTAINER=
# SWIFT_OBJECT_URL=
# SWIFT_REGION=
# Defaults to 'default'
# SWIFT_DOMAIN_NAME=
# Defaults to 60 seconds. Set to 0 to disable
# SWIFT_CACHE_TTL=
# Optional alias for S3 if you want to use Cloudfront or Cloudflare in front # Optional alias for S3 if you want to use Cloudfront or Cloudflare in front
# S3_CLOUDFRONT_HOST= # S3_CLOUDFRONT_HOST=
@@ -135,6 +105,3 @@ STREAMING_CLUSTER_NUM=1
# If you use Docker, you may want to assign UID/GID manually. # If you use Docker, you may want to assign UID/GID manually.
# UID=1000 # UID=1000
# GID=1000 # GID=1000
# Maximum allowed character count
# MAX_TOOT_CHARS=500

View File

@@ -1,18 +1,14 @@
--- ---
root: true
env: env:
browser: true browser: true
node: true node: false
es6: true es6: true
jest: true
parser: babel-eslint parser: babel-eslint
plugins: plugins:
- react - react
- jsx-a11y - jsx-a11y
- import
parserOptions: parserOptions:
sourceType: module sourceType: module
@@ -23,19 +19,8 @@ parserOptions:
modules: true modules: true
spread: true spread: true
settings:
import/extensions:
- .js
import/ignore:
- node_modules
- \\.(css|scss|json)$
import/resolver:
node:
moduleDirectory:
- node_modules
- app/javascript
rules: rules:
brace-style: warn brace-style: warn
comma-dangle: comma-dangle:
- error - error
@@ -62,20 +47,13 @@ rules:
- warn - warn
- allow: - allow:
- error - error
- warn
no-fallthrough: error no-fallthrough: error
no-irregular-whitespace: error no-irregular-whitespace: error
no-mixed-spaces-and-tabs: warn no-mixed-spaces-and-tabs: warn
no-nested-ternary: warn no-nested-ternary: warn
no-trailing-spaces: warn no-trailing-spaces: warn
no-undef: error
no-unreachable: error no-unreachable: error
no-unused-expressions: error no-unused-expressions: error
no-unused-vars:
- error
- vars: all
args: after-used
ignoreRestSiblings: true
object-curly-spacing: object-curly-spacing:
- error - error
- always - always
@@ -103,10 +81,7 @@ rules:
- 2 - 2
react/jsx-no-bind: error react/jsx-no-bind: error
react/jsx-no-duplicate-props: error react/jsx-no-duplicate-props: error
react/jsx-no-undef: error
react/jsx-tag-spacing: error react/jsx-tag-spacing: error
react/jsx-uses-react: error
react/jsx-uses-vars: error
react/jsx-wrap-multilines: error react/jsx-wrap-multilines: error
react/no-multi-comp: off react/no-multi-comp: off
react/no-string-refs: error react/no-string-refs: error
@@ -126,7 +101,7 @@ rules:
jsx-a11y/iframe-has-title: warn jsx-a11y/iframe-has-title: warn
jsx-a11y/img-has-alt: warn jsx-a11y/img-has-alt: warn
jsx-a11y/img-redundant-alt: warn jsx-a11y/img-redundant-alt: warn
jsx-a11y/label-has-for: off jsx-a11y/label-has-for: warn
jsx-a11y/mouse-events-have-key-events: warn jsx-a11y/mouse-events-have-key-events: warn
jsx-a11y/no-access-key: warn jsx-a11y/no-access-key: warn
jsx-a11y/no-distracting-elements: warn jsx-a11y/no-distracting-elements: warn
@@ -135,20 +110,6 @@ rules:
jsx-a11y/onclick-has-focus: warn jsx-a11y/onclick-has-focus: warn
jsx-a11y/onclick-has-role: warn jsx-a11y/onclick-has-role: warn
jsx-a11y/role-has-required-aria-props: warn jsx-a11y/role-has-required-aria-props: warn
jsx-a11y/role-supports-aria-props: off jsx-a11y/role-supports-aria-props: warn
jsx-a11y/scope: warn jsx-a11y/scope: warn
jsx-a11y/tabindex-no-positive: warn jsx-a11y/tabindex-no-positive: warn
import/extensions:
- error
- always
- js: never
import/newline-after-import: error
import/no-extraneous-dependencies:
- error
- devDependencies:
- "config/webpack/**"
- "app/javascript/mastodon/test_setup.js"
- "app/javascript/**/__tests__/**"
import/no-unresolved: error
import/no-webpack-loader-syntax: error

14
.gitattributes vendored
View File

@@ -1,14 +0,0 @@
* text=auto eol=lf
*.eot -text
*.gif -text
*.gz -text
*.ico -text
*.jpg -text
*.mp3 -text
*.ogg -text
*.png -text
*.ttf -text
*.webm -text
*.woff -text
*.woff2 -text
spec/fixtures/requests/** -text !eol

32
.github/CODEOWNERS vendored
View File

@@ -1,32 +0,0 @@
# CODEOWNERS for tootsuite/mastodon
# Translators
# To add translator, copy these lines, replace `fr` with appropriate language code and replace `@żelipapą` with user's GitHub nickname preceded by `@` sign or e-mail address.
# /app/javascript/mastodon/locales/fr.json @żelipapą
# /app/views/user_mailer/*.fr.html.erb @żelipapą
# /app/views/user_mailer/*.fr.text.erb @żelipapą
# /config/locales/*.fr.yml @żelipapą
# /config/locales/fr.yml @żelipapą
# Polish
/app/javascript/mastodon/locales/pl.json @m4sk1n
/app/views/user_mailer/*.pl.html.erb @m4sk1n
/app/views/user_mailer/*.pl.text.erb @m4sk1n
/config/locales/*.pl.yml @m4sk1n
/config/locales/pl.yml @m4sk1n
# French
/app/javascript/mastodon/locales/fr.json @aldarone
/app/javascript/mastodon/locales/whitelist_fr.json @aldarone
/app/views/user_mailer/*.fr.html.erb @aldarone
/app/views/user_mailer/*.fr.text.erb @aldarone
/config/locales/*.fr.yml @aldarone
/config/locales/fr.yml @aldarone
# Dutch
/app/javascript/mastodon/locales/nl.json @jeroenpraat
/app/javascript/mastodon/locales/whitelist_nl.json @jeroenpraat
/app/views/user_mailer/*.nl.html.erb @jeroenpraat
/app/views/user_mailer/*.nl.text.erb @jeroenpraat
/config/locales/*.nl.yml @jeroenpraat
/config/locales/nl.yml @jeroenpraat

View File

@@ -14,6 +14,7 @@ node_modules/
public/assets/ public/assets/
public/system/ public/system/
spec/ spec/
storybook/
tmp/ tmp/
.vagrant/ .vagrant/
vendor/bundle/ vendor/bundle/

View File

@@ -6,4 +6,3 @@ plugins:
- last 2 versions - last 2 versions
- IE >= 11 - IE >= 11
- iOS >= 9 - iOS >= 9
postcss-object-fit-images: {}

View File

@@ -10,7 +10,6 @@ AllCops:
- 'node_modules/**/*' - 'node_modules/**/*'
- 'Vagrantfile' - 'Vagrantfile'
- 'vendor/**/*' - 'vendor/**/*'
- 'lib/json_ld/*'
Bundler/OrderedGems: Bundler/OrderedGems:
Enabled: false Enabled: false
@@ -28,7 +27,6 @@ Metrics/AbcSize:
Max: 100 Max: 100
Metrics/BlockLength: Metrics/BlockLength:
Max: 35
Exclude: Exclude:
- 'lib/tasks/**/*' - 'lib/tasks/**/*'
@@ -37,10 +35,10 @@ Metrics/BlockNesting:
Metrics/ClassLength: Metrics/ClassLength:
CountComments: false CountComments: false
Max: 300 Max: 200
Metrics/CyclomaticComplexity: Metrics/CyclomaticComplexity:
Max: 25 Max: 15
Metrics/LineLength: Metrics/LineLength:
AllowURI: true AllowURI: true
@@ -55,11 +53,11 @@ Metrics/ModuleLength:
Max: 200 Max: 200
Metrics/ParameterLists: Metrics/ParameterLists:
Max: 5 Max: 4
CountKeywordArgs: true CountKeywordArgs: true
Metrics/PerceivedComplexity: Metrics/PerceivedComplexity:
Max: 20 Max: 10
Rails: Rails:
Enabled: true Enabled: true

View File

@@ -1 +1 @@
2.4.2 2.4.1

View File

@@ -2,3 +2,4 @@ node_modules/
.cache/ .cache/
docs/ docs/
spec/ spec/
storybook/

View File

@@ -6,9 +6,8 @@ cache:
- node_modules - node_modules
- public/assets - public/assets
- public/packs-test - public/packs-test
- tmp/cache/babel-loader
dist: trusty dist: trusty
sudo: required sudo: false
notifications: notifications:
email: false email: false
@@ -26,25 +25,24 @@ addons:
postgresql: 9.4 postgresql: 9.4
apt: apt:
sources: sources:
- ubuntu-toolchain-r-test
- trusty-media - trusty-media
- sourceline: deb https://dl.yarnpkg.com/debian/ stable main
key_url: https://dl.yarnpkg.com/debian/pubkey.gpg
packages: packages:
- ffmpeg - ffmpeg
- libicu-dev - g++-6
- libprotobuf-dev - libprotobuf-dev
- protobuf-compiler - protobuf-compiler
- yarn
rvm: rvm:
- 2.3.4 - 2.3.4
- 2.4.2 - 2.4.1
services: services:
- redis-server - redis-server
install: install:
- nvm install - nvm install
- npm install -g yarn
- bundle install --path=vendor/bundle --without development production --retry=3 --jobs=16 - bundle install --path=vendor/bundle --without development production --retry=3 --jobs=16
- yarn install - yarn install
@@ -55,5 +53,5 @@ before_script:
script: script:
- travis_retry bundle exec parallel_test spec/ --group-by filesize --type rspec - travis_retry bundle exec parallel_test spec/ --group-by filesize --type rspec
- yarn test - npm test
- bundle exec i18n-tasks check-normalized && bundle exec i18n-tasks unused - bundle exec i18n-tasks unused

View File

@@ -1,46 +0,0 @@
# test directories
__tests__
test
tests
powered-test
# asset directories
docs
doc
website
images
# assets
# examples
example
examples
# code coverage directories
coverage
.nyc_output
# build scripts
Makefile
Gulpfile.js
Gruntfile.js
# configs
.tern-project
.gitattributes
.editorconfig
.*ignore
.eslintrc
.jshintrc
.flowconfig
.documentup.json
.yarn-metadata.json
.*.yml
*.yml
# misc
*.gz
*.md
# for specific ignore
!.svgo.yml

View File

@@ -1,10 +1,5 @@
ffmpeg protobuf-compiler
libicu[0-9][0-9]
libicu-dev
libidn11
libidn11-dev
libpq-dev
libprotobuf-dev libprotobuf-dev
ffmpeg
libxdamage1 libxdamage1
libxfixes3 libxfixes3
protobuf-compiler

View File

@@ -1,46 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at beatrix.bitrot@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

View File

@@ -1,36 +1,3 @@
# Contributing to Mastodon Glitch Edition #
Thank you for your interest in contributing to the `glitch-soc` project!
Here are some guidelines, and ways you can help.
> (This document is a bit of a work-in-progress, so please bear with us.
> If you don't see what you're looking for here, please don't hesitate to reach out!)
## Planning ##
Right now a lot of the planning for this project takes place in our development Discord, or through GitHub Issues and Projects.
We're working on ways to improve the planning structure and better solicit feedback, and if you feel like you can help in this respect, feel free to give us a holler.
## Documentation ##
The documentation for this repository is available at [`glitch-soc/docs`](https://github.com/glitch-soc/docs) (online at [glitch-soc.github.io/docs/](https://glitch-soc.github.io/docs/)).
Right now, we've mostly focused on the features that make this fork different from upstream in some manner.
Adding screenshots, improving descriptions, and so forth are all ways to help contribute to the project even if you don't know any code.
## Frontend Development ##
Check out [the documentation here](https://glitch-soc.github.io/docs/contributing/frontend/) for more information.
## Backend Development ##
See the guidelines below.
- - -
You should also try to follow the guidelines set out in the original `CONTRIBUTING.md` from `tootsuite/mastodon`, reproduced below.
<blockquote>
CONTRIBUTING CONTRIBUTING
============ ============
@@ -82,5 +49,3 @@ It is expected that you have a working development environment set up (see back-
* If you are introducing new strings, they must be using localization methods * 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. 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.
</blockquote>

View File

@@ -1,4 +1,4 @@
FROM ruby:2.4.2-alpine3.6 FROM ruby:2.4.1-alpine
LABEL maintainer="https://github.com/tootsuite/mastodon" \ LABEL maintainer="https://github.com/tootsuite/mastodon" \
description="A GNU Social-compatible microblogging server" description="A GNU Social-compatible microblogging server"
@@ -7,22 +7,16 @@ ENV UID=991 GID=991 \
RAILS_SERVE_STATIC_FILES=true \ RAILS_SERVE_STATIC_FILES=true \
RAILS_ENV=production NODE_ENV=production RAILS_ENV=production NODE_ENV=production
ARG YARN_VERSION=1.3.2
ARG YARN_DOWNLOAD_SHA256=6cfe82e530ef0837212f13e45c1565ba53f5199eec2527b85ecbcd88bf26821d
ARG LIBICONV_VERSION=1.15
ARG LIBICONV_DOWNLOAD_SHA256=ccf536620a45458d26ba83887a983b96827001e92a13847b45e4925cc8913178
EXPOSE 3000 4000 EXPOSE 3000 4000
WORKDIR /mastodon WORKDIR /mastodon
RUN apk -U upgrade \ RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories \
&& apk -U upgrade \
&& apk add -t build-dependencies \ && apk add -t build-dependencies \
build-base \ build-base \
icu-dev \ libxml2-dev \
libidn-dev \ libxslt-dev \
libressl \
libtool \
postgresql-dev \ postgresql-dev \
protobuf-dev \ protobuf-dev \
python \ python \
@@ -31,44 +25,23 @@ RUN apk -U upgrade \
ffmpeg \ ffmpeg \
file \ file \
git \ git \
icu-libs \ imagemagick@edge \
imagemagick \
libidn \
libpq \ libpq \
nodejs \ libxml2 \
nodejs-npm \ libxslt \
nodejs-npm@edge \
nodejs@edge \
protobuf \ protobuf \
su-exec \ su-exec \
tini \ tini \
&& npm install -g npm@3 && npm install -g yarn \
&& 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 \
&& 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 - \
&& tar -xzf libiconv.tar.gz -C /tmp/src \
&& rm libiconv.tar.gz \
&& cd /tmp/src/libiconv-$LIBICONV_VERSION \
&& ./configure --prefix=/usr/local \
&& make -j$(getconf _NPROCESSORS_ONLN)\
&& make install \
&& libtool --finish /usr/local/lib \
&& cd /mastodon \
&& rm -rf /tmp/* /var/cache/apk/* && rm -rf /tmp/* /var/cache/apk/*
COPY Gemfile Gemfile.lock package.json yarn.lock .yarnclean /mastodon/ COPY Gemfile Gemfile.lock package.json yarn.lock /mastodon/
COPY stack-fix.c /lib
RUN gcc -shared -fPIC /lib/stack-fix.c -o /lib/stack-fix.so
RUN rm /lib/stack-fix.c
RUN bundle config build.nokogiri --with-iconv-lib=/usr/local/lib --with-iconv-include=/usr/local/include \ RUN bundle install --deployment --without test development \
&& bundle install -j$(getconf _NPROCESSORS_ONLN) --deployment --without test development \ && yarn --ignore-optional --pure-lockfile
&& yarn --pure-lockfile \
&& yarn cache clean
COPY . /mastodon COPY . /mastodon

66
Gemfile
View File

@@ -5,8 +5,8 @@ ruby '>= 2.3.0', '< 2.5.0'
gem 'pkg-config', '~> 1.2' gem 'pkg-config', '~> 1.2'
gem 'puma', '~> 3.10' gem 'puma', '~> 3.8'
gem 'rails', '~> 5.1.4' gem 'rails', '~> 5.1.0'
gem 'uglifier', '~> 3.2' gem 'uglifier', '~> 3.2'
gem 'hamlit-rails', '~> 0.2' gem 'hamlit-rails', '~> 0.2'
@@ -14,52 +14,40 @@ gem 'pg', '~> 0.20'
gem 'pghero', '~> 1.7' gem 'pghero', '~> 1.7'
gem 'dotenv-rails', '~> 2.2' gem 'dotenv-rails', '~> 2.2'
gem 'aws-sdk', '~> 2.10', require: false gem 'aws-sdk', '~> 2.9'
gem 'fog-core', '~> 1.45'
gem 'fog-local', '~> 0.4', require: false
gem 'fog-openstack', '~> 0.1', require: false
gem 'paperclip', '~> 5.1' gem 'paperclip', '~> 5.1'
gem 'paperclip-av-transcoder', '~> 0.6' gem 'paperclip-av-transcoder', '~> 0.6'
gem 'posix-spawn'
gem 'active_model_serializers', '~> 0.10'
gem 'addressable', '~> 2.5' gem 'addressable', '~> 2.5'
gem 'bootsnap' gem 'bootsnap'
gem 'browser' gem 'cld3', '~> 3.1'
gem 'charlock_holmes', '~> 0.7.5' gem 'devise', '~> 4.2'
gem 'iso-639'
gem 'cld3', '~> 3.2.0'
gem 'devise', '~> 4.3'
gem 'devise-two-factor', '~> 3.0' gem 'devise-two-factor', '~> 3.0'
gem 'doorkeeper', '~> 4.2' gem 'doorkeeper', '~> 4.2'
gem 'fast_blank', '~> 1.0' gem 'fast_blank', '~> 1.0'
gem 'goldfinger', '~> 2.0' gem 'goldfinger', '~> 1.2'
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', '~> 2.2' gem 'http', '~> 2.2'
gem 'http_accept_language', '~> 2.1' gem 'http_accept_language', '~> 2.1'
gem 'httplog', '~> 0.99' gem 'httplog', '~> 0.99'
gem 'idn-ruby', require: 'idn' gem 'kaminari', '~> 1.0'
gem 'kaminari', '~> 1.1'
gem 'link_header', '~> 0.0' gem 'link_header', '~> 0.0'
gem 'mime-types', '~> 3.1' gem 'nokogiri', '~> 1.7'
gem 'nokogiri', '~> 1.8' gem 'oj', '~> 3.0'
gem 'nsa', '~> 0.2'
gem 'oj', '~> 3.3'
gem 'ostatus2', '~> 2.0' gem 'ostatus2', '~> 2.0'
gem 'ox', '~> 2.8' gem 'ox', '~> 2.5'
gem 'pundit', '~> 1.1' gem 'pundit', '~> 1.1'
gem 'rabl', '~> 0.13'
gem 'rack-attack', '~> 5.0' gem 'rack-attack', '~> 5.0'
gem 'rack-cors', '~> 0.4', require: 'rack/cors' gem 'rack-cors', '~> 0.4', require: 'rack/cors'
gem 'rack-timeout', '~> 0.4' gem 'rack-timeout', '~> 0.4'
gem 'rails-i18n', '~> 5.0' gem 'rails-i18n', '~> 5.0'
gem 'rails-settings-cached', '~> 0.6' gem 'rails-settings-cached', '~> 0.6'
gem 'redis', '~> 3.3', require: ['redis', 'redis/connection/hiredis'] gem 'redis', '~> 3.3', require: ['redis', 'redis/connection/hiredis']
gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
gem 'rqrcode', '~> 0.10' gem 'rqrcode', '~> 0.10'
gem 'ruby-oembed', '~> 0.12', require: 'oembed' gem 'ruby-oembed', '~> 0.12', require: 'oembed'
gem 'ruby-progressbar', '~> 1.4'
gem 'sanitize', '~> 4.4' gem 'sanitize', '~> 4.4'
gem 'sidekiq', '~> 5.0' gem 'sidekiq', '~> 5.0'
gem 'sidekiq-scheduler', '~> 2.1' gem 'sidekiq-scheduler', '~> 2.1'
@@ -68,55 +56,51 @@ gem 'sidekiq-bulk', '~>0.1.1'
gem 'simple-navigation', '~> 4.0' gem 'simple-navigation', '~> 4.0'
gem 'simple_form', '~> 3.4' gem 'simple_form', '~> 3.4'
gem 'sprockets-rails', '~> 3.2', require: 'sprockets/railtie' gem 'sprockets-rails', '~> 3.2', require: 'sprockets/railtie'
gem 'strong_migrations' gem 'statsd-instrument', '~> 2.1'
gem 'twitter-text', '~> 1.14' gem 'twitter-text', '~> 1.14'
gem 'tzinfo-data', '~> 1.2017' gem 'tzinfo-data', '~> 1.2017'
gem 'webpacker', '~> 3.0' gem 'webpacker', '~> 2.0'
gem 'webpush'
gem 'json-ld-preloaded', '~> 2.2.1'
gem 'rdf-normalize', '~> 0.3.1'
group :development, :test do group :development, :test do
gem 'fabrication', '~> 2.18' gem 'fabrication', '~> 2.16'
gem 'fuubar', '~> 2.2' gem 'fuubar', '~> 2.2'
gem 'i18n-tasks', '~> 0.9', require: false gem 'i18n-tasks', '~> 0.9', require: false
gem 'pry-rails', '~> 0.3' gem 'pry-rails', '~> 0.3'
gem 'rspec-rails', '~> 3.7' gem 'rspec-rails', '~> 3.6'
end end
group :test do group :test do
gem 'capybara', '~> 2.15' gem 'capybara', '~> 2.14'
gem 'climate_control', '~> 0.2' gem 'climate_control', '~> 0.2'
gem 'faker', '~> 1.7' gem 'faker', '~> 1.7'
gem 'microformats', '~> 4.0' gem 'microformats2', '~> 3.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.14', require: false gem 'simplecov', '~> 0.14', require: false
gem 'webmock', '~> 3.0' gem 'webmock', '~> 3.0'
gem 'parallel_tests', '~> 2.17' gem 'parallel_tests', '~> 2.14'
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.4' gem 'better_errors', '~> 2.1'
gem 'binding_of_caller', '~> 0.7' gem 'binding_of_caller', '~> 0.7'
gem 'bullet', '~> 5.5' gem 'bullet', '~> 5.5'
gem 'letter_opener', '~> 1.4' gem 'letter_opener', '~> 1.4'
gem 'letter_opener_web', '~> 1.3' gem 'letter_opener_web', '~> 1.3'
gem 'rubocop', require: false gem 'rubocop', require: false
gem 'brakeman', '~> 4.0', require: false gem 'brakeman', '~> 3.6', require: false
gem 'bundler-audit', '~> 0.6', require: false gem 'bundler-audit', '~> 0.5', require: false
gem 'scss_lint', '~> 0.55', require: false gem 'scss_lint', '~> 0.53', require: false
gem 'capistrano', '~> 3.10' gem 'capistrano', '~> 3.8'
gem 'capistrano-rails', '~> 1.3' gem 'capistrano-rails', '~> 1.2'
gem 'capistrano-rbenv', '~> 2.1' gem 'capistrano-rbenv', '~> 2.1'
gem 'capistrano-yarn', '~> 2.0' gem 'capistrano-yarn', '~> 2.0'
end end
group :production do group :production do
gem 'lograge', '~> 0.7' gem 'lograge', '~> 0.5'
gem 'redis-rails', '~> 5.0' gem 'redis-rails', '~> 5.0'
end end

View File

@@ -1,52 +1,47 @@
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
actioncable (5.1.4) actioncable (5.1.1)
actionpack (= 5.1.4) actionpack (= 5.1.1)
nio4r (~> 2.0) nio4r (~> 2.0)
websocket-driver (~> 0.6.1) websocket-driver (~> 0.6.1)
actionmailer (5.1.4) actionmailer (5.1.1)
actionpack (= 5.1.4) actionpack (= 5.1.1)
actionview (= 5.1.4) actionview (= 5.1.1)
activejob (= 5.1.4) activejob (= 5.1.1)
mail (~> 2.5, >= 2.5.4) mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
actionpack (5.1.4) actionpack (5.1.1)
actionview (= 5.1.4) actionview (= 5.1.1)
activesupport (= 5.1.4) activesupport (= 5.1.1)
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.1.4) actionview (5.1.1)
activesupport (= 5.1.4) activesupport (= 5.1.1)
builder (~> 3.1) builder (~> 3.1)
erubi (~> 1.4) erubi (~> 1.4)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3) rails-html-sanitizer (~> 1.0, >= 1.0.3)
active_model_serializers (0.10.7)
actionpack (>= 4.1, < 6)
activemodel (>= 4.1, < 6)
case_transform (>= 0.2)
jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
active_record_query_trace (1.5.4) active_record_query_trace (1.5.4)
activejob (5.1.4) activejob (5.1.1)
activesupport (= 5.1.4) activesupport (= 5.1.1)
globalid (>= 0.3.6) globalid (>= 0.3.6)
activemodel (5.1.4) activemodel (5.1.1)
activesupport (= 5.1.4) activesupport (= 5.1.1)
activerecord (5.1.4) activerecord (5.1.1)
activemodel (= 5.1.4) activemodel (= 5.1.1)
activesupport (= 5.1.4) activesupport (= 5.1.1)
arel (~> 8.0) arel (~> 8.0)
activesupport (5.1.4) activesupport (5.1.1)
concurrent-ruby (~> 1.0, >= 1.0.2) concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (~> 0.7) i18n (~> 0.7)
minitest (~> 5.1) minitest (~> 5.1)
tzinfo (~> 1.1) tzinfo (~> 1.1)
addressable (2.5.2) addressable (2.5.1)
public_suffix (>= 2.0.2, < 4.0) public_suffix (~> 2.0, >= 2.0.2)
airbrussh (1.3.0) airbrussh (1.2.0)
sshkit (>= 1.6.1, != 1.7.0) sshkit (>= 1.6.1, != 1.7.0)
annotate (2.7.2) annotate (2.7.2)
activerecord (>= 3.2, < 6.0) activerecord (>= 3.2, < 6.0)
@@ -57,71 +52,67 @@ 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-sdk (2.10.100) aws-sdk (2.9.37)
aws-sdk-resources (= 2.10.100) aws-sdk-resources (= 2.9.37)
aws-sdk-core (2.10.100) aws-sdk-core (2.9.37)
aws-sigv4 (~> 1.0) aws-sigv4 (~> 1.0)
jmespath (~> 1.0) jmespath (~> 1.0)
aws-sdk-resources (2.10.100) aws-sdk-resources (2.9.37)
aws-sdk-core (= 2.10.100) aws-sdk-core (= 2.9.37)
aws-sigv4 (1.0.2) aws-sigv4 (1.0.0)
bcrypt (3.1.11) bcrypt (3.1.11)
better_errors (2.4.0) better_errors (2.1.1)
coderay (>= 1.0.0) coderay (>= 1.0.0)
erubi (>= 1.0.0) erubis (>= 2.6.6)
rack (>= 0.9.0) rack (>= 0.9.0)
binding_of_caller (0.7.3) binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1) debug_inspector (>= 0.0.1)
bootsnap (1.1.5) bootsnap (1.0.0)
msgpack (~> 1.0) msgpack (~> 1.0)
brakeman (4.0.1) brakeman (3.6.2)
browser (2.5.2)
builder (3.2.3) builder (3.2.3)
bullet (5.6.1) bullet (5.5.1)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
uniform_notifier (~> 1.10.0) uniform_notifier (~> 1.10.0)
bundler-audit (0.6.0) bundler-audit (0.5.0)
bundler (~> 1.2) bundler (~> 1.2)
thor (~> 0.18) thor (~> 0.18)
capistrano (3.10.0) capistrano (3.8.1)
airbrussh (>= 1.0.0) airbrussh (>= 1.0.0)
i18n i18n
rake (>= 10.0.0) rake (>= 10.0.0)
sshkit (>= 1.9.0) sshkit (>= 1.9.0)
capistrano-bundler (1.3.0) capistrano-bundler (1.2.0)
capistrano (~> 3.1) capistrano (~> 3.1)
sshkit (~> 1.2) sshkit (~> 1.2)
capistrano-rails (1.3.1) capistrano-rails (1.3.0)
capistrano (~> 3.1) capistrano (~> 3.1)
capistrano-bundler (~> 1.1) capistrano-bundler (~> 1.1)
capistrano-rbenv (2.1.3) capistrano-rbenv (2.1.1)
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 (2.16.1) capybara (2.14.2)
addressable addressable
mini_mime (>= 0.1.3) mime-types (>= 1.16)
nokogiri (>= 1.3.3) nokogiri (>= 1.3.3)
rack (>= 1.0.0) rack (>= 1.0.0)
rack-test (>= 0.5.4) rack-test (>= 0.5.4)
xpath (~> 2.0) xpath (~> 2.0)
case_transform (0.2)
activesupport
charlock_holmes (0.7.5)
chunky_png (1.3.8) chunky_png (1.3.8)
cld3 (3.2.1) cld3 (3.1.2)
ffi (>= 1.1.0, < 1.10.0) ffi (>= 1.1.0, < 1.10.0)
climate_control (0.2.0) climate_control (0.2.0)
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.1)
colorize (0.8.1) colorize (0.8.1)
concurrent-ruby (1.0.5) concurrent-ruby (1.0.5)
connection_pool (2.2.1) 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.3) crass (1.0.2)
debug_inspector (0.0.3) debug_inspector (0.0.3)
devise (4.3.0) devise (4.3.0)
bcrypt (~> 3.0) bcrypt (~> 3.0)
@@ -129,11 +120,11 @@ GEM
railties (>= 4.1.0, < 5.2) railties (>= 4.1.0, < 5.2)
responders responders
warden (~> 1.2.3) warden (~> 1.2.3)
devise-two-factor (3.0.2) devise-two-factor (3.0.0)
activesupport (< 5.2) activesupport
attr_encrypted (>= 1.3, < 4, != 2) attr_encrypted (>= 1.3, < 4, != 2)
devise (~> 4.0) devise (~> 4.0)
railties (< 5.2) railties
rotp (~> 2.0) rotp (~> 2.0)
diff-lcs (1.3) diff-lcs (1.3)
docile (1.1.5) docile (1.1.5)
@@ -150,41 +141,26 @@ GEM
thread thread
thread_safe thread_safe
encryptor (3.0.0) encryptor (3.0.0)
erubi (1.7.0) erubi (1.6.0)
et-orbi (1.0.8) erubis (2.7.0)
et-orbi (1.0.4)
tzinfo tzinfo
excon (0.59.0)
execjs (2.7.0) execjs (2.7.0)
fabrication (2.18.0) fabrication (2.16.1)
faker (1.8.4) faker (1.7.3)
i18n (~> 0.5) i18n (~> 0.5)
fast_blank (1.0.0) fast_blank (1.0.0)
ffi (1.9.18) ffi (1.9.18)
fog-core (1.45.0)
builder
excon (~> 0.58)
formatador (~> 0.2)
fog-json (1.0.2)
fog-core (~> 1.0)
multi_json (~> 1.10)
fog-local (0.4.0)
fog-core (~> 1.27)
fog-openstack (0.1.22)
fog-core (>= 1.40)
fog-json (>= 1.0)
ipaddress (>= 0.8)
formatador (0.2.5)
fuubar (2.2.0) fuubar (2.2.0)
rspec-core (~> 3.0) rspec-core (~> 3.0)
ruby-progressbar (~> 1.4) ruby-progressbar (~> 1.4)
globalid (0.4.1) globalid (0.4.0)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
goldfinger (2.0.1) goldfinger (1.2.0)
addressable (~> 2.5) addressable (~> 2.4)
http (~> 2.2) http (~> 2.0)
nokogiri (~> 1.8) nokogiri (~> 1.6)
oj (~> 3.0) hamlit (2.8.1)
hamlit (2.8.5)
temple (>= 0.8.0) temple (>= 0.8.0)
thor thor
tilt tilt
@@ -193,12 +169,9 @@ GEM
activesupport (>= 4.0.1) activesupport (>= 4.0.1)
hamlit (>= 1.2.0) hamlit (>= 1.2.0)
railties (>= 4.0.1) railties (>= 4.0.1)
hamster (3.0.0) hashdiff (0.3.4)
concurrent-ruby (~> 1.0) highline (1.7.8)
hashdiff (0.3.7)
highline (1.7.10)
hiredis (0.6.1) hiredis (0.6.1)
hkdf (0.3.0)
htmlentities (4.3.4) htmlentities (4.3.4)
http (2.2.2) http (2.2.2)
addressable (~> 2.3) addressable (~> 2.3)
@@ -208,49 +181,36 @@ GEM
http-cookie (1.0.3) http-cookie (1.0.3)
domain_name (~> 0.5) domain_name (~> 0.5)
http-form_data (1.0.3) http-form_data (1.0.3)
http_accept_language (2.1.1) http_accept_language (2.1.0)
http_parser.rb (0.6.0) http_parser.rb (0.6.0)
httplog (0.99.7) httplog (0.99.3)
colorize colorize
rack rack
i18n (0.9.1) i18n (0.8.4)
concurrent-ruby (~> 1.0) i18n-tasks (0.9.15)
i18n-tasks (0.9.19)
activesupport (>= 4.0.2) activesupport (>= 4.0.2)
ast (>= 2.1.0) ast (>= 2.1.0)
easy_translate (>= 0.5.0) easy_translate (>= 0.5.0)
erubi erubis
highline (>= 1.7.3) highline (>= 1.7.3)
i18n i18n
parser (>= 2.2.3.0) parser (>= 2.2.3.0)
rainbow (~> 2.2) rainbow (~> 2.2)
terminal-table (>= 1.5.1) terminal-table (>= 1.5.1)
idn-ruby (0.1.0)
ipaddress (0.8.3)
iso-639 (0.2.8)
jmespath (1.3.1) jmespath (1.3.1)
json (2.1.0) json (2.1.0)
json-ld (2.1.7) kaminari (1.0.1)
multi_json (~> 1.12)
rdf (~> 2.2, >= 2.2.8)
json-ld-preloaded (2.2.2)
json-ld (~> 2.1, >= 2.1.5)
multi_json (~> 1.11)
rdf (~> 2.2)
jsonapi-renderer (0.2.0)
jwt (2.1.0)
kaminari (1.1.1)
activesupport (>= 4.1.0) activesupport (>= 4.1.0)
kaminari-actionview (= 1.1.1) kaminari-actionview (= 1.0.1)
kaminari-activerecord (= 1.1.1) kaminari-activerecord (= 1.0.1)
kaminari-core (= 1.1.1) kaminari-core (= 1.0.1)
kaminari-actionview (1.1.1) kaminari-actionview (1.0.1)
actionview actionview
kaminari-core (= 1.1.1) kaminari-core (= 1.0.1)
kaminari-activerecord (1.1.1) kaminari-activerecord (1.0.1)
activerecord activerecord
kaminari-core (= 1.1.1) kaminari-core (= 1.0.1)
kaminari-core (1.1.1) kaminari-core (1.0.1)
launchy (2.4.3) launchy (2.4.3)
addressable (~> 2.3) addressable (~> 2.3)
letter_opener (1.4.1) letter_opener (1.4.1)
@@ -260,51 +220,43 @@ GEM
letter_opener (~> 1.0) letter_opener (~> 1.0)
railties (>= 3.2) railties (>= 3.2)
link_header (0.0.8) link_header (0.0.8)
lograge (0.7.1) lograge (0.5.1)
actionpack (>= 4, < 5.2) actionpack (>= 4, < 5.2)
activesupport (>= 4, < 5.2) activesupport (>= 4, < 5.2)
railties (>= 4, < 5.2) railties (>= 4, < 5.2)
request_store (~> 1.0) loofah (2.0.3)
loofah (2.1.1)
crass (~> 1.0.2)
nokogiri (>= 1.5.9) nokogiri (>= 1.5.9)
mail (2.7.0) mail (2.6.6)
mini_mime (>= 0.1.1) mime-types (>= 1.16, < 4)
mario-redis-lock (1.2.0) method_source (0.8.2)
redis (~> 3, >= 3.0.5) microformats2 (3.1.0)
method_source (0.9.0)
microformats (4.0.7)
json json
nokogiri nokogiri
mime-types (3.1) mime-types (3.1)
mime-types-data (~> 3.2015) mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521) mime-types-data (3.2016.0521)
mimemagic (0.3.2) mimemagic (0.3.2)
mini_mime (1.0.0) mini_portile2 (2.2.0)
mini_portile2 (2.3.0) minitest (5.10.2)
minitest (5.10.3)
msgpack (1.1.0) msgpack (1.1.0)
multi_json (1.12.2) multi_json (1.12.1)
net-scp (1.2.1) net-scp (1.2.1)
net-ssh (>= 2.6.5) net-ssh (>= 2.6.5)
net-ssh (4.2.0) net-ssh (4.1.0)
nio4r (2.1.0) nio4r (2.1.0)
nokogiri (1.8.1) nokogiri (1.8.0)
mini_portile2 (~> 2.3.0) mini_portile2 (~> 2.2.0)
nokogumbo (1.4.13) nokogumbo (1.4.13)
nokogiri nokogiri
nsa (0.2.4) oj (3.1.0)
activesupport (>= 4.2, < 6) openssl (2.0.3)
concurrent-ruby (~> 1.0.0)
sidekiq (>= 3.5.0)
statsd-ruby (~> 1.2.0)
oj (3.3.9)
orm_adapter (0.5.0) orm_adapter (0.5.0)
ostatus2 (2.0.2) ostatus2 (2.0.1)
addressable (~> 2.4) addressable (~> 2.4)
http (~> 2.0) http (~> 2.0)
nokogiri (~> 1.6) nokogiri (~> 1.6)
ox (2.8.2) openssl (~> 2.0)
ox (2.5.0)
paperclip (5.1.0) paperclip (5.1.0)
activemodel (>= 4.2.0) activemodel (>= 4.2.0)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
@@ -314,48 +266,48 @@ GEM
paperclip-av-transcoder (0.6.4) paperclip-av-transcoder (0.6.4)
av (~> 0.9.0) av (~> 0.9.0)
paperclip (>= 2.5.2) paperclip (>= 2.5.2)
parallel (1.12.0) parallel (1.11.2)
parallel_tests (2.19.0) parallel_tests (2.14.1)
parallel parallel
parser (2.4.0.2) parser (2.4.0.0)
ast (~> 2.3) ast (~> 2.2)
pg (0.21.0) pg (0.20.0)
pghero (1.7.0) pghero (1.7.0)
activerecord activerecord
pkg-config (1.2.8) pkg-config (1.2.3)
posix-spawn (0.3.13)
powerpack (0.1.1) powerpack (0.1.1)
pry (0.11.3) pry (0.10.4)
coderay (~> 1.1.0) coderay (~> 1.1.0)
method_source (~> 0.9.0) method_source (~> 0.8.1)
slop (~> 3.4)
pry-rails (0.3.6) pry-rails (0.3.6)
pry (>= 0.10.4) pry (>= 0.10.4)
public_suffix (3.0.1) public_suffix (2.0.5)
puma (3.11.0) puma (3.9.1)
pundit (1.1.0) pundit (1.1.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
rabl (0.13.1)
activesupport (>= 2.3.14)
rack (2.0.3) rack (2.0.3)
rack-attack (5.0.1) rack-attack (5.0.1)
rack rack
rack-cors (0.4.1) rack-cors (0.4.1)
rack-protection (2.0.0) rack-protection (2.0.0)
rack rack
rack-proxy (0.6.2) rack-test (0.6.3)
rack rack (>= 1.0)
rack-test (0.8.2)
rack (>= 1.0, < 3)
rack-timeout (0.4.2) rack-timeout (0.4.2)
rails (5.1.4) rails (5.1.1)
actioncable (= 5.1.4) actioncable (= 5.1.1)
actionmailer (= 5.1.4) actionmailer (= 5.1.1)
actionpack (= 5.1.4) actionpack (= 5.1.1)
actionview (= 5.1.4) actionview (= 5.1.1)
activejob (= 5.1.4) activejob (= 5.1.1)
activemodel (= 5.1.4) activemodel (= 5.1.1)
activerecord (= 5.1.4) activerecord (= 5.1.1)
activesupport (= 5.1.4) activesupport (= 5.1.1)
bundler (>= 1.3.0) bundler (>= 1.3.0, < 2.0)
railties (= 5.1.4) railties (= 5.1.1)
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)
@@ -369,80 +321,71 @@ GEM
rails-i18n (5.0.4) rails-i18n (5.0.4)
i18n (~> 0.7) i18n (~> 0.7)
railties (~> 5.0) railties (~> 5.0)
rails-settings-cached (0.6.6) rails-settings-cached (0.6.5)
rails (>= 4.2.0) rails (>= 4.2.0)
railties (5.1.4) railties (5.1.1)
actionpack (= 5.1.4) actionpack (= 5.1.1)
activesupport (= 5.1.4) activesupport (= 5.1.1)
method_source method_source
rake (>= 0.8.7) rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0) thor (>= 0.18.1, < 2.0)
rainbow (2.2.2) rainbow (2.2.2)
rake rake
rake (12.3.0) rake (12.0.0)
rb-fsevent (0.10.2) redis (3.3.3)
rb-inotify (0.9.10) redis-actionpack (5.0.1)
ffi (>= 0.5.0, < 2)
rdf (2.2.12)
hamster (~> 3.0)
link_header (~> 0.0, >= 0.0.8)
rdf-normalize (0.3.2)
rdf (~> 2.0)
redis (3.3.5)
redis-actionpack (5.0.2)
actionpack (>= 4.0, < 6) actionpack (>= 4.0, < 6)
redis-rack (>= 1, < 3) redis-rack (>= 1, < 3)
redis-store (>= 1.1.0, < 2) redis-store (>= 1.1.0, < 1.4.0)
redis-activesupport (5.0.4) redis-activesupport (5.0.2)
activesupport (>= 3, < 6) activesupport (>= 3, < 6)
redis-store (>= 1.3, < 2) redis-store (~> 1.3.0)
redis-namespace (1.6.0) redis-namespace (1.5.3)
redis (>= 3.0.4) redis (~> 3.0, >= 3.0.4)
redis-rack (2.0.3) redis-rack (2.0.2)
rack (>= 1.5, < 3) rack (>= 1.5, < 3)
redis-store (>= 1.2, < 2) redis-store (>= 1.2, < 1.4)
redis-rails (5.0.2) redis-rails (5.0.2)
redis-actionpack (>= 5.0, < 6) redis-actionpack (>= 5.0, < 6)
redis-activesupport (>= 5.0, < 6) redis-activesupport (>= 5.0, < 6)
redis-store (>= 1.2, < 2) redis-store (>= 1.2, < 2)
redis-store (1.4.1) redis-store (1.3.0)
redis (>= 2.2, < 5) redis (>= 2.2)
request_store (1.3.2)
responders (2.4.0) responders (2.4.0)
actionpack (>= 4.2.0, < 5.3) actionpack (>= 4.2.0, < 5.3)
railties (>= 4.2.0, < 5.3) railties (>= 4.2.0, < 5.3)
rotp (2.1.2) rotp (2.1.2)
rqrcode (0.10.1) rqrcode (0.10.1)
chunky_png (~> 1.0) chunky_png (~> 1.0)
rspec-core (3.7.0) rspec-core (3.6.0)
rspec-support (~> 3.7.0) rspec-support (~> 3.6.0)
rspec-expectations (3.7.0) rspec-expectations (3.6.0)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.7.0) rspec-support (~> 3.6.0)
rspec-mocks (3.7.0) rspec-mocks (3.6.0)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.7.0) rspec-support (~> 3.6.0)
rspec-rails (3.7.2) rspec-rails (3.6.0)
actionpack (>= 3.0) actionpack (>= 3.0)
activesupport (>= 3.0) activesupport (>= 3.0)
railties (>= 3.0) railties (>= 3.0)
rspec-core (~> 3.7.0) rspec-core (~> 3.6.0)
rspec-expectations (~> 3.7.0) rspec-expectations (~> 3.6.0)
rspec-mocks (~> 3.7.0) rspec-mocks (~> 3.6.0)
rspec-support (~> 3.7.0) rspec-support (~> 3.6.0)
rspec-sidekiq (3.0.3) rspec-sidekiq (3.0.1)
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.7.0) rspec-support (3.6.0)
rubocop (0.51.0) rubocop (0.49.1)
parallel (~> 1.10) parallel (~> 1.10)
parser (>= 2.3.3.1, < 3.0) parser (>= 2.3.3.1, < 3.0)
powerpack (~> 0.1) powerpack (~> 0.1)
rainbow (>= 2.2.2, < 3.0) rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.7) ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.0, >= 1.0.1) unicode-display_width (~> 1.0, >= 1.0.1)
ruby-oembed (0.12.0) ruby-oembed (0.12.0)
ruby-progressbar (1.9.0) ruby-progressbar (1.8.1)
rufus-scheduler (3.4.2) rufus-scheduler (3.4.2)
et-orbi (~> 1.0) et-orbi (~> 1.0)
safe_yaml (1.0.4) safe_yaml (1.0.4)
@@ -450,28 +393,24 @@ GEM
crass (~> 1.0.2) crass (~> 1.0.2)
nokogiri (>= 1.4.4) nokogiri (>= 1.4.4)
nokogumbo (~> 1.4.1) nokogumbo (~> 1.4.1)
sass (3.5.3) sass (3.4.24)
sass-listen (~> 4.0.0) scss_lint (0.53.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
scss_lint (0.56.0)
rake (>= 0.9, < 13) rake (>= 0.9, < 13)
sass (~> 3.5.3) sass (~> 3.4.20)
sidekiq (5.0.5) sidekiq (5.0.2)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
connection_pool (~> 2.2, >= 2.2.0) connection_pool (~> 2.2, >= 2.2.0)
rack-protection (>= 1.5.0) rack-protection (>= 1.5.0)
redis (>= 3.3.4, < 5) redis (~> 3.3, >= 3.3.3)
sidekiq-bulk (0.1.1) sidekiq-bulk (0.1.1)
activesupport activesupport
sidekiq sidekiq
sidekiq-scheduler (2.1.10) sidekiq-scheduler (2.1.5)
redis (>= 3, < 5) redis (~> 3)
rufus-scheduler (~> 3.2) rufus-scheduler (~> 3.2)
sidekiq (>= 3) sidekiq (>= 3)
tilt (>= 1.4.0) tilt (>= 1.4.0)
sidekiq-unique-jobs (5.0.10) sidekiq-unique-jobs (5.0.8)
sidekiq (>= 4.0, <= 6.0) sidekiq (>= 4.0, <= 6.0)
thor (~> 0) thor (~> 0)
simple-navigation (4.0.5) simple-navigation (4.0.5)
@@ -479,60 +418,56 @@ GEM
simple_form (3.5.0) simple_form (3.5.0)
actionpack (> 4, < 5.2) actionpack (> 4, < 5.2)
activemodel (> 4, < 5.2) activemodel (> 4, < 5.2)
simplecov (0.15.1) simplecov (0.14.1)
docile (~> 1.1.0) docile (~> 1.1.0)
json (>= 1.8, < 3) json (>= 1.8, < 3)
simplecov-html (~> 0.10.0) simplecov-html (~> 0.10.0)
simplecov-html (0.10.2) simplecov-html (0.10.1)
slop (3.6.0)
sprockets (3.7.1) sprockets (3.7.1)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
rack (> 1, < 3) rack (> 1, < 3)
sprockets-rails (3.2.1) sprockets-rails (3.2.0)
actionpack (>= 4.0) actionpack (>= 4.0)
activesupport (>= 4.0) activesupport (>= 4.0)
sprockets (>= 3.0.0) sprockets (>= 3.0.0)
sshkit (1.15.1) sshkit (1.13.1)
net-scp (>= 1.1.2) net-scp (>= 1.1.2)
net-ssh (>= 2.8.0) net-ssh (>= 2.8.0)
statsd-ruby (1.2.1) statsd-instrument (2.1.2)
strong_migrations (0.1.9)
activerecord (>= 3.2.0)
temple (0.8.0) temple (0.8.0)
terminal-table (1.8.0) terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1) unicode-display_width (~> 1.1, >= 1.1.1)
thor (0.20.0) thor (0.19.4)
thread (0.2.2) thread (0.2.2)
thread_safe (0.3.6) thread_safe (0.3.6)
tilt (2.0.8) tilt (2.0.7)
twitter-text (1.14.7) twitter-text (1.14.5)
unf (~> 0.1.0) unf (~> 0.1.0)
tzinfo (1.2.4) tzinfo (1.2.3)
thread_safe (~> 0.1) thread_safe (~> 0.1)
tzinfo-data (1.2017.3) tzinfo-data (1.2017.2)
tzinfo (>= 1.0.0) tzinfo (>= 1.0.0)
uglifier (3.2.0) uglifier (3.2.0)
execjs (>= 0.3.0, < 3) execjs (>= 0.3.0, < 3)
unf (0.1.4) unf (0.1.4)
unf_ext unf_ext
unf_ext (0.0.7.4) unf_ext (0.0.7.4)
unicode-display_width (1.3.0) unicode-display_width (1.2.1)
uniform_notifier (1.10.0) uniform_notifier (1.10.0)
warden (1.2.7) warden (1.2.7)
rack (>= 1.0) rack (>= 1.0)
webmock (3.1.1) webmock (3.0.1)
addressable (>= 2.3.6) addressable (>= 2.3.6)
crack (>= 0.3.2) crack (>= 0.3.2)
hashdiff hashdiff
webpacker (3.0.2) webpacker (2.0)
activesupport (>= 4.2) activesupport (>= 4.2)
rack-proxy (>= 0.6.1) multi_json (~> 1.2)
railties (>= 4.2) railties (>= 4.2)
webpush (0.3.3)
hkdf (~> 0.2)
jwt (~> 2.0)
websocket-driver (0.6.5) websocket-driver (0.6.5)
websocket-extensions (>= 0.1.0) websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.3) websocket-extensions (0.1.2)
xpath (2.1.0) xpath (2.1.0)
nokogiri (~> 1.3) nokogiri (~> 1.3)
@@ -540,38 +475,32 @@ PLATFORMS
ruby ruby
DEPENDENCIES DEPENDENCIES
active_model_serializers (~> 0.10)
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 (~> 2.10) aws-sdk (~> 2.9)
better_errors (~> 2.4) better_errors (~> 2.1)
binding_of_caller (~> 0.7) binding_of_caller (~> 0.7)
bootsnap bootsnap
brakeman (~> 4.0) brakeman (~> 3.6)
browser
bullet (~> 5.5) bullet (~> 5.5)
bundler-audit (~> 0.6) bundler-audit (~> 0.5)
capistrano (~> 3.10) capistrano (~> 3.8)
capistrano-rails (~> 1.3) capistrano-rails (~> 1.2)
capistrano-rbenv (~> 2.1) capistrano-rbenv (~> 2.1)
capistrano-yarn (~> 2.0) capistrano-yarn (~> 2.0)
capybara (~> 2.15) capybara (~> 2.14)
charlock_holmes (~> 0.7.5) cld3 (~> 3.1)
cld3 (~> 3.2.0)
climate_control (~> 0.2) climate_control (~> 0.2)
devise (~> 4.3) devise (~> 4.2)
devise-two-factor (~> 3.0) devise-two-factor (~> 3.0)
doorkeeper (~> 4.2) doorkeeper (~> 4.2)
dotenv-rails (~> 2.2) dotenv-rails (~> 2.2)
fabrication (~> 2.18) fabrication (~> 2.16)
faker (~> 1.7) faker (~> 1.7)
fast_blank (~> 1.0) fast_blank (~> 1.0)
fog-core (~> 1.45)
fog-local (~> 0.4)
fog-openstack (~> 0.1)
fuubar (~> 2.2) fuubar (~> 2.2)
goldfinger (~> 2.0) goldfinger (~> 1.2)
hamlit-rails (~> 0.2) hamlit-rails (~> 0.2)
hiredis (~> 0.6) hiredis (~> 0.6)
htmlentities (~> 4.3) htmlentities (~> 4.3)
@@ -579,51 +508,43 @@ DEPENDENCIES
http_accept_language (~> 2.1) http_accept_language (~> 2.1)
httplog (~> 0.99) httplog (~> 0.99)
i18n-tasks (~> 0.9) i18n-tasks (~> 0.9)
idn-ruby kaminari (~> 1.0)
iso-639
json-ld-preloaded (~> 2.2.1)
kaminari (~> 1.1)
letter_opener (~> 1.4) letter_opener (~> 1.4)
letter_opener_web (~> 1.3) letter_opener_web (~> 1.3)
link_header (~> 0.0) link_header (~> 0.0)
lograge (~> 0.7) lograge (~> 0.5)
mario-redis-lock (~> 1.2) microformats2 (~> 3.0)
microformats (~> 4.0) nokogiri (~> 1.7)
mime-types (~> 3.1) oj (~> 3.0)
nokogiri (~> 1.8)
nsa (~> 0.2)
oj (~> 3.3)
ostatus2 (~> 2.0) ostatus2 (~> 2.0)
ox (~> 2.8) ox (~> 2.5)
paperclip (~> 5.1) paperclip (~> 5.1)
paperclip-av-transcoder (~> 0.6) paperclip-av-transcoder (~> 0.6)
parallel_tests (~> 2.17) parallel_tests (~> 2.14)
pg (~> 0.20) pg (~> 0.20)
pghero (~> 1.7) pghero (~> 1.7)
pkg-config (~> 1.2) pkg-config (~> 1.2)
posix-spawn
pry-rails (~> 0.3) pry-rails (~> 0.3)
puma (~> 3.10) puma (~> 3.8)
pundit (~> 1.1) pundit (~> 1.1)
rabl (~> 0.13)
rack-attack (~> 5.0) rack-attack (~> 5.0)
rack-cors (~> 0.4) rack-cors (~> 0.4)
rack-timeout (~> 0.4) rack-timeout (~> 0.4)
rails (~> 5.1.4) rails (~> 5.1.0)
rails-controller-testing (~> 1.0) rails-controller-testing (~> 1.0)
rails-i18n (~> 5.0) rails-i18n (~> 5.0)
rails-settings-cached (~> 0.6) rails-settings-cached (~> 0.6)
rdf-normalize (~> 0.3.1)
redis (~> 3.3) redis (~> 3.3)
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.7) rspec-rails (~> 3.6)
rspec-sidekiq (~> 3.0) rspec-sidekiq (~> 3.0)
rubocop rubocop
ruby-oembed (~> 0.12) ruby-oembed (~> 0.12)
ruby-progressbar (~> 1.4)
sanitize (~> 4.4) sanitize (~> 4.4)
scss_lint (~> 0.55) scss_lint (~> 0.53)
sidekiq (~> 5.0) sidekiq (~> 5.0)
sidekiq-bulk (~> 0.1.1) sidekiq-bulk (~> 0.1.1)
sidekiq-scheduler (~> 2.1) sidekiq-scheduler (~> 2.1)
@@ -632,16 +553,15 @@ DEPENDENCIES
simple_form (~> 3.4) simple_form (~> 3.4)
simplecov (~> 0.14) simplecov (~> 0.14)
sprockets-rails (~> 3.2) sprockets-rails (~> 3.2)
strong_migrations statsd-instrument (~> 2.1)
twitter-text (~> 1.14) twitter-text (~> 1.14)
tzinfo-data (~> 1.2017) tzinfo-data (~> 1.2017)
uglifier (~> 3.2) uglifier (~> 3.2)
webmock (~> 3.0) webmock (~> 3.0)
webpacker (~> 3.0) webpacker (~> 2.0)
webpush
RUBY VERSION RUBY VERSION
ruby 2.4.2p198 ruby 2.4.1p111
BUNDLED WITH BUNDLED WITH
1.16.1 1.15.1

View File

@@ -1,4 +1,4 @@
web: PORT=3000 bundle exec puma -C config/puma.rb web: PORT=3000 bundle exec puma -C config/puma.rb
sidekiq: PORT=3000 bundle exec sidekiq sidekiq: PORT=3000 bundle exec sidekiq
stream: PORT=4000 yarn run start stream: PORT=4000 yarn run start
webpack: ./bin/webpack-dev-server --listen-host 0.0.0.0 webpack: ./bin/webpack-dev-server --host 0.0.0.0

View File

@@ -1,10 +1,5 @@
# Mastodon Glitch Edition # Mastodon Glitch Edition
========
> Now with automated deploys! Now with automated deploys!
[![Build Status](https://travis-ci.org/glitch-soc/mastodon.svg?branch=master)](https://travis-ci.org/glitch-soc/mastodon)
So here's the deal: we all work on this code, and then it runs on dev.glitch.social and anyone who uses that does so absolutely at their own risk. can you dig it? So here's the deal: we all work on this code, and then it runs on dev.glitch.social and anyone who uses that does so absolutely at their own risk. can you dig it?
- You can view documentation for this project at [glitch-soc.github.io/docs/](https://glitch-soc.github.io/docs/).
- And contributing guidelines are available [here](CONTRIBUTING.md) and [here](https://glitch-soc.github.io/docs/contributing/).

9
Vagrantfile vendored
View File

@@ -35,8 +35,6 @@ sudo apt-get install \
postgresql-contrib \ postgresql-contrib \
protobuf-compiler \ protobuf-compiler \
yarn \ yarn \
libicu-dev \
libidn11-dev \
libprotobuf-dev \ libprotobuf-dev \
libreadline-dev \ libreadline-dev \
-y -y
@@ -44,12 +42,9 @@ sudo apt-get install \
# Install rvm # Install rvm
read RUBY_VERSION < .ruby-version read RUBY_VERSION < .ruby-version
gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
curl -sSL https://raw.githubusercontent.com/rvm/rvm/stable/binscripts/rvm-installer | bash -s stable --ruby=$RUBY_VERSION curl -sSL https://get.rvm.io | bash -s stable --ruby=$RUBY_VERSION
source /home/vagrant/.rvm/scripts/rvm source /home/vagrant/.rvm/scripts/rvm
# Install Ruby
rvm install ruby-$RUBY_VERSION
# Configure database # Configure database
sudo -u postgres createuser -U postgres vagrant -s sudo -u postgres createuser -U postgres vagrant -s
sudo -u postgres createdb -U postgres mastodon_development sudo -u postgres createdb -U postgres mastodon_development
@@ -83,7 +78,7 @@ 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", "4096"] vb.customize ["modifyvm", :id, "--memory", "2048"]
# 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

View File

@@ -2,7 +2,7 @@
"name": "Mastodon", "name": "Mastodon",
"description": "A GNU Social-compatible microblogging server", "description": "A GNU Social-compatible microblogging server",
"repository": "https://github.com/tootsuite/mastodon", "repository": "https://github.com/tootsuite/mastodon",
"logo": "https://github.com/tootsuite.png", "logo": "https://github.com/tootsuite/mastodon/raw/master/app/assets/images/logo.png",
"env": { "env": {
"HEROKU": { "HEROKU": {
"description": "Leave this as true", "description": "Leave this as true",

View File

@@ -1,14 +1,10 @@
# frozen_string_literal: true # frozen_string_literal: true
class AboutController < ApplicationController class AboutController < ApplicationController
before_action :set_pack
before_action :set_body_classes before_action :set_body_classes
before_action :set_instance_presenter, only: [:show, :more, :terms] before_action :set_instance_presenter, only: [:show, :more]
def show def show; end
serializable_resource = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(initial_state_params), serializer: InitialStateSerializer)
@initial_state_json = serializable_resource.to_json
end
def more; end def more; end
@@ -19,13 +15,8 @@ class AboutController < ApplicationController
def new_user def new_user
User.new.tap(&:build_account) User.new.tap(&:build_account)
end end
helper_method :new_user helper_method :new_user
def set_pack
use_pack action_name == 'show' ? 'about' : 'common'
end
def set_instance_presenter def set_instance_presenter
@instance_presenter = InstancePresenter.new @instance_presenter = InstancePresenter.new
end end
@@ -33,11 +24,4 @@ class AboutController < ApplicationController
def set_body_classes def set_body_classes
@body_classes = 'about-body' @body_classes = 'about-body'
end end
def initial_state_params
{
settings: {},
token: current_session&.token,
}
end
end end

View File

@@ -3,88 +3,25 @@
class AccountsController < ApplicationController class AccountsController < ApplicationController
include AccountControllerConcern include AccountControllerConcern
before_action :set_cache_headers
def show def show
respond_to do |format| respond_to do |format|
format.html do format.html do
use_pack 'public' @statuses = @account.statuses.permitted_for(@account, current_account).paginate_by_max_id(20, params[:max_id], params[:since_id])
@pinned_statuses = [] @statuses = cache_collection(@statuses, Status)
if current_account && @account.blocking?(current_account)
@statuses = []
return
end
@pinned_statuses = cache_collection(@account.pinned_statuses, Status) if show_pinned_statuses?
@statuses = filtered_statuses.paginate_by_max_id(20, params[:max_id], params[:since_id])
@statuses = cache_collection(@statuses, Status)
@next_url = next_url unless @statuses.empty?
end end
format.atom do format.atom do
@entries = @account.stream_entries.where(hidden: false).with_includes.paginate_by_max_id(20, params[:max_id], params[:since_id]) @entries = @account.stream_entries.where(hidden: false).with_includes.paginate_by_max_id(20, params[:max_id], params[:since_id])
render xml: OStatus::AtomSerializer.render(OStatus::AtomSerializer.new.feed(@account, @entries.reject { |entry| entry.status.nil? })) render xml: AtomSerializer.render(AtomSerializer.new.feed(@account, @entries.to_a))
end end
format.json do format.activitystreams2
skip_session!
render_cached_json(['activitypub', 'actor', @account.cache_key], content_type: 'application/activity+json') do
ActiveModelSerializers::SerializableResource.new(@account, serializer: ActivityPub::ActorSerializer, adapter: ActivityPub::Adapter)
end
end
end end
end end
private private
def show_pinned_statuses?
[replies_requested?, media_requested?, params[:max_id].present?, params[:since_id].present?].none?
end
def filtered_statuses
default_statuses.tap do |statuses|
statuses.merge!(only_media_scope) if media_requested?
statuses.merge!(no_replies_scope) unless replies_requested?
end
end
def default_statuses
@account.statuses.not_local_only.where(visibility: [:public, :unlisted])
end
def only_media_scope
Status.where(id: account_media_status_ids)
end
def account_media_status_ids
@account.media_attachments.attached.reorder(nil).select(:status_id).distinct
end
def no_replies_scope
Status.without_replies
end
def set_account def set_account
@account = Account.find_local!(params[:username]) @account = Account.find_local!(params[:username])
end end
def next_url
if media_requested?
short_account_media_url(@account, max_id: @statuses.last.id)
elsif replies_requested?
short_account_with_replies_url(@account, max_id: @statuses.last.id)
else
short_account_url(@account, max_id: @statuses.last.id)
end
end
def media_requested?
request.path.ends_with?('/media')
end
def replies_requested?
request.path.ends_with?('/with_replies')
end
end end

View File

@@ -1,41 +0,0 @@
# frozen_string_literal: true
class ActivityPub::InboxesController < Api::BaseController
include SignatureVerification
before_action :set_account
def create
if signed_request_account
upgrade_account
process_payload
head 202
else
[signature_verification_failure_reason, 401]
end
end
private
def set_account
@account = Account.find_local!(params[:account_username]) if params[:account_username]
end
def body
@body ||= request.body.read
end
def upgrade_account
if signed_request_account.ostatus?
signed_request_account.update(last_webfingered_at: nil)
ResolveRemoteAccountWorker.perform_async(signed_request_account.acct)
end
Pubsubhubbub::UnsubscribeWorker.perform_async(signed_request_account.id) if signed_request_account.subscribed?
DeliveryFailureTracker.track_inverse_success!(signed_request_account)
end
def process_payload
ActivityPub::ProcessingWorker.perform_async(signed_request_account.id, body.force_encoding('UTF-8'))
end
end

View File

@@ -1,27 +0,0 @@
# frozen_string_literal: true
class ActivityPub::OutboxesController < Api::BaseController
before_action :set_account
def show
@statuses = @account.statuses.permitted_for(@account, current_account).paginate_by_max_id(20, params[:max_id], params[:since_id])
@statuses = cache_collection(@statuses, Status)
render json: outbox_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json'
end
private
def set_account
@account = Account.find_local!(params[:account_username])
end
def outbox_presenter
ActivityPub::CollectionPresenter.new(
id: account_outbox_url(@account),
type: :ordered,
size: @account.statuses_count,
items: @statuses
)
end
end

View File

@@ -1,41 +0,0 @@
# frozen_string_literal: true
module Admin
class AccountModerationNotesController < BaseController
before_action :set_account_moderation_note, only: [:destroy]
def create
authorize AccountModerationNote, :create?
@account_moderation_note = current_account.account_moderation_notes.new(resource_params)
if @account_moderation_note.save
redirect_to admin_account_path(@account_moderation_note.target_account_id), notice: I18n.t('admin.account_moderation_notes.created_msg')
else
@account = @account_moderation_note.target_account
@moderation_notes = @account.targeted_moderation_notes.latest
render template: 'admin/accounts/show'
end
end
def destroy
authorize @account_moderation_note, :destroy?
@account_moderation_note.destroy!
redirect_to admin_account_path(@account_moderation_note.target_account_id), notice: I18n.t('admin.account_moderation_notes.destroyed_msg')
end
private
def resource_params
params.require(:account_moderation_note).permit(
:content,
:target_account_id
)
end
def set_account_moderation_note
@account_moderation_note = AccountModerationNote.find(params[:id])
end
end
end

View File

@@ -2,59 +2,28 @@
module Admin module Admin
class AccountsController < BaseController class AccountsController < BaseController
before_action :set_account, only: [:show, :subscribe, :unsubscribe, :redownload, :enable, :disable, :memorialize] before_action :set_account, only: [:show, :subscribe, :unsubscribe, :redownload]
before_action :require_remote_account!, only: [:subscribe, :unsubscribe, :redownload] before_action :require_remote_account!, only: [:subscribe, :unsubscribe, :redownload]
before_action :require_local_account!, only: [:enable, :disable, :memorialize]
def index def index
authorize :account, :index?
@accounts = filtered_accounts.page(params[:page]) @accounts = filtered_accounts.page(params[:page])
end end
def show def show; end
authorize @account, :show?
@account_moderation_note = current_account.account_moderation_notes.new(target_account: @account)
@moderation_notes = @account.targeted_moderation_notes.latest
end
def subscribe def subscribe
authorize @account, :subscribe?
Pubsubhubbub::SubscribeWorker.perform_async(@account.id) Pubsubhubbub::SubscribeWorker.perform_async(@account.id)
redirect_to admin_account_path(@account.id) redirect_to admin_account_path(@account.id)
end end
def unsubscribe def unsubscribe
authorize @account, :unsubscribe? UnsubscribeService.new.call(@account)
Pubsubhubbub::UnsubscribeWorker.perform_async(@account.id)
redirect_to admin_account_path(@account.id)
end
def memorialize
authorize @account, :memorialize?
@account.memorialize!
log_action :memorialize, @account
redirect_to admin_account_path(@account.id)
end
def enable
authorize @account.user, :enable?
@account.user.enable!
log_action :enable, @account.user
redirect_to admin_account_path(@account.id)
end
def disable
authorize @account.user, :disable?
@account.user.disable!
log_action :disable, @account.user
redirect_to admin_account_path(@account.id) redirect_to admin_account_path(@account.id)
end end
def redownload def redownload
authorize @account, :redownload? @account.avatar = @account.avatar_remote_url
@account.header = @account.header_remote_url
@account.reset_avatar!
@account.reset_header!
@account.save! @account.save!
redirect_to admin_account_path(@account.id) redirect_to admin_account_path(@account.id)
@@ -70,10 +39,6 @@ module Admin
redirect_to admin_account_path(@account.id) if @account.local? redirect_to admin_account_path(@account.id) if @account.local?
end end
def require_local_account!
redirect_to admin_account_path(@account.id) unless @account.local? && @account.user.present?
end
def filtered_accounts def filtered_accounts
AccountFilter.new(filter_params).results AccountFilter.new(filter_params).results
end end
@@ -89,8 +54,7 @@ module Admin
:username, :username,
:display_name, :display_name,
:email, :email,
:ip, :ip
:staff
) )
end end
end end

View File

@@ -1,9 +0,0 @@
# frozen_string_literal: true
module Admin
class ActionLogsController < BaseController
def index
@action_logs = Admin::ActionLog.page(params[:page])
end
end
end

View File

@@ -2,16 +2,8 @@
module Admin module Admin
class BaseController < ApplicationController class BaseController < ApplicationController
include Authorization before_action :require_admin!
include AccountableConcern
layout 'admin' layout 'admin'
before_action :require_staff!
before_action :set_pack
def set_pack
use_pack 'admin'
end
end end
end end

View File

@@ -2,19 +2,15 @@
module Admin module Admin
class ConfirmationsController < BaseController class ConfirmationsController < BaseController
before_action :set_user
def create def create
authorize @user, :confirm? account_user.confirm
@user.confirm!
log_action :confirm, @user
redirect_to admin_accounts_path redirect_to admin_accounts_path
end end
private private
def set_user def account_user
@user = Account.find(params[:account_id]).user || raise(ActiveRecord::RecordNotFound) Account.find(params[:account_id]).user || raise(ActiveRecord::RecordNotFound)
end end
end end
end end

View File

@@ -1,111 +0,0 @@
# frozen_string_literal: true
module Admin
class CustomEmojisController < BaseController
before_action :set_custom_emoji, except: [:index, :new, :create]
before_action :set_filter_params
def index
authorize :custom_emoji, :index?
@custom_emojis = filtered_custom_emojis.eager_load(:local_counterpart).page(params[:page])
end
def new
authorize :custom_emoji, :create?
@custom_emoji = CustomEmoji.new
end
def create
authorize :custom_emoji, :create?
@custom_emoji = CustomEmoji.new(resource_params)
if @custom_emoji.save
log_action :create, @custom_emoji
redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.created_msg')
else
render :new
end
end
def update
authorize @custom_emoji, :update?
if @custom_emoji.update(resource_params)
log_action :update, @custom_emoji
flash[:notice] = I18n.t('admin.custom_emojis.updated_msg')
else
flash[:alert] = I18n.t('admin.custom_emojis.update_failed_msg')
end
redirect_to admin_custom_emojis_path(page: params[:page], **@filter_params)
end
def destroy
authorize @custom_emoji, :destroy?
@custom_emoji.destroy!
log_action :destroy, @custom_emoji
flash[:notice] = I18n.t('admin.custom_emojis.destroyed_msg')
redirect_to admin_custom_emojis_path(page: params[:page], **@filter_params)
end
def copy
authorize @custom_emoji, :copy?
emoji = CustomEmoji.find_or_initialize_by(domain: nil,
shortcode: @custom_emoji.shortcode)
emoji.image = @custom_emoji.image
if emoji.save
log_action :create, emoji
flash[:notice] = I18n.t('admin.custom_emojis.copied_msg')
else
flash[:alert] = I18n.t('admin.custom_emojis.copy_failed_msg')
end
redirect_to admin_custom_emojis_path(page: params[:page], **@filter_params)
end
def enable
authorize @custom_emoji, :enable?
@custom_emoji.update!(disabled: false)
log_action :enable, @custom_emoji
flash[:notice] = I18n.t('admin.custom_emojis.enabled_msg')
redirect_to admin_custom_emojis_path(page: params[:page], **@filter_params)
end
def disable
authorize @custom_emoji, :disable?
@custom_emoji.update!(disabled: true)
log_action :disable, @custom_emoji
flash[:notice] = I18n.t('admin.custom_emojis.disabled_msg')
redirect_to admin_custom_emojis_path(page: params[:page], **@filter_params)
end
private
def set_custom_emoji
@custom_emoji = CustomEmoji.find(params[:id])
end
def set_filter_params
@filter_params = filter_params.to_hash.symbolize_keys
end
def resource_params
params.require(:custom_emoji).permit(:shortcode, :image, :visible_in_picker)
end
def filtered_custom_emojis
CustomEmojiFilter.new(filter_params).results
end
def filter_params
params.permit(
:local,
:remote,
:by_domain,
:shortcode
)
end
end
end

View File

@@ -5,37 +5,28 @@ module Admin
before_action :set_domain_block, only: [:show, :destroy] before_action :set_domain_block, only: [:show, :destroy]
def index def index
authorize :domain_block, :index?
@domain_blocks = DomainBlock.page(params[:page]) @domain_blocks = DomainBlock.page(params[:page])
end end
def new def new
authorize :domain_block, :create?
@domain_block = DomainBlock.new @domain_block = DomainBlock.new
end end
def create def create
authorize :domain_block, :create?
@domain_block = DomainBlock.new(resource_params) @domain_block = DomainBlock.new(resource_params)
if @domain_block.save if @domain_block.save
DomainBlockWorker.perform_async(@domain_block.id) DomainBlockWorker.perform_async(@domain_block.id)
log_action :create, @domain_block
redirect_to admin_domain_blocks_path, notice: I18n.t('admin.domain_blocks.created_msg') redirect_to admin_domain_blocks_path, notice: I18n.t('admin.domain_blocks.created_msg')
else else
render :new render :new
end end
end end
def show def show; end
authorize @domain_block, :show?
end
def destroy def destroy
authorize @domain_block, :destroy?
UnblockDomainService.new.call(@domain_block, retroactive_unblock?) UnblockDomainService.new.call(@domain_block, retroactive_unblock?)
log_action :destroy, @domain_block
redirect_to admin_domain_blocks_path, notice: I18n.t('admin.domain_blocks.destroyed_msg') redirect_to admin_domain_blocks_path, notice: I18n.t('admin.domain_blocks.destroyed_msg')
end end

View File

@@ -1,47 +0,0 @@
# frozen_string_literal: true
module Admin
class EmailDomainBlocksController < BaseController
before_action :set_email_domain_block, only: [:show, :destroy]
def index
authorize :email_domain_block, :index?
@email_domain_blocks = EmailDomainBlock.page(params[:page])
end
def new
authorize :email_domain_block, :create?
@email_domain_block = EmailDomainBlock.new
end
def create
authorize :email_domain_block, :create?
@email_domain_block = EmailDomainBlock.new(resource_params)
if @email_domain_block.save
log_action :create, @email_domain_block
redirect_to admin_email_domain_blocks_path, notice: I18n.t('admin.email_domain_blocks.created_msg')
else
render :new
end
end
def destroy
authorize @email_domain_block, :destroy?
@email_domain_block.destroy!
log_action :destroy, @email_domain_block
redirect_to admin_email_domain_blocks_path, notice: I18n.t('admin.email_domain_blocks.destroyed_msg')
end
private
def set_email_domain_block
@email_domain_block = EmailDomainBlock.find(params[:id])
end
def resource_params
params.require(:email_domain_block).permit(:domain)
end
end
end

View File

@@ -3,41 +3,18 @@
module Admin module Admin
class InstancesController < BaseController class InstancesController < BaseController
def index def index
authorize :instance, :index?
@instances = ordered_instances @instances = ordered_instances
end end
def resubscribe
authorize :instance, :resubscribe?
params.require(:by_domain)
Pubsubhubbub::SubscribeWorker.push_bulk(subscribeable_accounts.pluck(:id))
redirect_to admin_instances_path
end
private private
def filtered_instances
InstanceFilter.new(filter_params).results
end
def paginated_instances def paginated_instances
filtered_instances.page(params[:page]) Account.remote.by_domain_accounts.page(params[:page])
end end
helper_method :paginated_instances helper_method :paginated_instances
def ordered_instances def ordered_instances
paginated_instances.map { |account| Instance.new(account) } paginated_instances.map { |account| Instance.new(account) }
end end
def subscribeable_accounts
Account.with_followers.remote.where(domain: params[:by_domain])
end
def filter_params
params.permit(
:domain_name
)
end
end end
end end

View File

@@ -1,47 +0,0 @@
# frozen_string_literal: true
module Admin
class InvitesController < BaseController
def index
authorize :invite, :index?
@invites = filtered_invites.includes(user: :account).page(params[:page])
@invite = Invite.new
end
def create
authorize :invite, :create?
@invite = Invite.new(resource_params)
@invite.user = current_user
if @invite.save
redirect_to admin_invites_path
else
@invites = Invite.page(params[:page])
render :index
end
end
def destroy
@invite = Invite.find(params[:id])
authorize @invite, :destroy?
@invite.expire!
redirect_to admin_invites_path
end
private
def resource_params
params.require(:invite).permit(:max_uses, :expires_in)
end
def filtered_invites
InviteFilter.new(filter_params).results
end
def filter_params
params.permit(:available, :expired)
end
end
end

View File

@@ -2,30 +2,20 @@
module Admin module Admin
class ReportedStatusesController < BaseController class ReportedStatusesController < BaseController
include Authorization
before_action :set_report before_action :set_report
before_action :set_status, only: [:update, :destroy] before_action :set_status
def create
authorize :status, :update?
@form = Form::StatusBatch.new(form_status_batch_params.merge(current_account: current_account))
flash[:alert] = I18n.t('admin.statuses.failed_to_execute') unless @form.save
redirect_to admin_report_path(@report)
end
def update def update
authorize @status, :update? @status.update(status_params)
@status.update!(status_params)
log_action :update, @status
redirect_to admin_report_path(@report) redirect_to admin_report_path(@report)
end end
def destroy def destroy
authorize @status, :destroy? authorize @status, :destroy?
RemovalWorker.perform_async(@status.id) RemovalWorker.perform_async(@status.id)
log_action :destroy, @status redirect_to admin_report_path(@report)
render json: @status
end end
private private
@@ -34,10 +24,6 @@ module Admin
params.require(:status).permit(:sensitive) params.require(:status).permit(:sensitive)
end end
def form_status_batch_params
params.require(:form_status_batch).permit(:action, status_ids: [])
end
def set_report def set_report
@report = Report.find(params[:report_id]) @report = Report.find(params[:report_id])
end end

View File

@@ -5,17 +5,12 @@ module Admin
before_action :set_report, except: [:index] before_action :set_report, except: [:index]
def index def index
authorize :report, :index?
@reports = filtered_reports.page(params[:page]) @reports = filtered_reports.page(params[:page])
end end
def show def show; end
authorize @report, :show?
@form = Form::StatusBatch.new
end
def update def update
authorize @report, :update?
process_report process_report
redirect_to admin_report_path(@report) redirect_to admin_report_path(@report)
end end
@@ -25,17 +20,12 @@ module Admin
def process_report def process_report
case params[:outcome].to_s case params[:outcome].to_s
when 'resolve' when 'resolve'
@report.update!(action_taken_by_current_attributes) @report.update(action_taken_by_current_attributes)
log_action :resolve, @report
when 'suspend' when 'suspend'
Admin::SuspensionWorker.perform_async(@report.target_account.id) Admin::SuspensionWorker.perform_async(@report.target_account.id)
log_action :resolve, @report
log_action :suspend, @report.target_account
resolve_all_target_account_reports resolve_all_target_account_reports
when 'silence' when 'silence'
@report.target_account.update!(silenced: true) @report.target_account.update(silenced: true)
log_action :resolve, @report
log_action :silence, @report.target_account
resolve_all_target_account_reports resolve_all_target_account_reports
else else
raise ActiveRecord::RecordNotFound raise ActiveRecord::RecordNotFound

View File

@@ -2,19 +2,17 @@
module Admin module Admin
class ResetsController < BaseController class ResetsController < BaseController
before_action :set_user before_action :set_account
def create def create
authorize @user, :reset_password? @account.user.send_reset_password_instructions
@user.send_reset_password_instructions
log_action :reset_password, @user
redirect_to admin_accounts_path redirect_to admin_accounts_path
end end
private private
def set_user def set_account
@user = Account.find(params[:account_id]).user || raise(ActiveRecord::RecordNotFound) @account = Account.find(params[:account_id])
end end
end end
end end

View File

@@ -1,27 +0,0 @@
# frozen_string_literal: true
module Admin
class RolesController < BaseController
before_action :set_user
def promote
authorize @user, :promote?
@user.promote!
log_action :promote, @user
redirect_to admin_account_path(@user.account_id)
end
def demote
authorize @user, :demote?
@user.demote!
log_action :demote, @user
redirect_to admin_account_path(@user.account_id)
end
private
def set_user
@user = Account.find(params[:account_id]).user || raise(ActiveRecord::RecordNotFound)
end
end
end

View File

@@ -8,63 +8,34 @@ module Admin
site_title site_title
site_description site_description
site_extended_description site_extended_description
site_terms
open_registrations open_registrations
closed_registrations_message closed_registrations_message
open_deletion
timeline_preview
show_staff_badge
bootstrap_timeline_accounts
thumbnail
min_invite_role
activity_api_enabled
peers_api_enabled
).freeze
BOOLEAN_SETTINGS = %w(
open_registrations
open_deletion
timeline_preview
show_staff_badge
activity_api_enabled
peers_api_enabled
).freeze
UPLOAD_SETTINGS = %w(
thumbnail
).freeze ).freeze
BOOLEAN_SETTINGS = %w(open_registrations).freeze
def edit def edit
authorize :settings, :show? @settings = Setting.all_as_records
@admin_settings = Form::AdminSettings.new
end end
def update def update
authorize :settings, :update?
settings_params.each do |key, value| settings_params.each do |key, value|
if UPLOAD_SETTINGS.include?(key) setting = Setting.where(var: key).first_or_initialize(var: key)
upload = SiteUpload.where(var: key).first_or_initialize(var: key) setting.update(value: value_for_update(key, value))
upload.update(file: value)
else
setting = Setting.where(var: key).first_or_initialize(var: key)
setting.update(value: value_for_update(key, value))
end
end end
flash[:notice] = I18n.t('generic.changes_saved_msg') flash[:notice] = 'Success!'
redirect_to edit_admin_settings_path redirect_to edit_admin_settings_path
end end
private private
def settings_params def settings_params
params.require(:form_admin_settings).permit(ADMIN_SETTINGS) params.permit(ADMIN_SETTINGS)
end end
def value_for_update(key, value) def value_for_update(key, value)
if BOOLEAN_SETTINGS.include?(key) if BOOLEAN_SETTINGS.include?(key)
value == '1' value == 'true'
else else
value value
end end

View File

@@ -5,16 +5,12 @@ module Admin
before_action :set_account before_action :set_account
def create def create
authorize @account, :silence? @account.update(silenced: true)
@account.update!(silenced: true)
log_action :silence, @account
redirect_to admin_accounts_path redirect_to admin_accounts_path
end end
def destroy def destroy
authorize @account, :unsilence? @account.update(silenced: false)
@account.update!(silenced: false)
log_action :unsilence, @account
redirect_to admin_accounts_path redirect_to admin_accounts_path
end end

View File

@@ -1,76 +0,0 @@
# frozen_string_literal: true
module Admin
class StatusesController < BaseController
helper_method :current_params
before_action :set_account
before_action :set_status, only: [:update, :destroy]
PER_PAGE = 20
def index
authorize :status, :index?
@statuses = @account.statuses
if params[:media]
account_media_status_ids = @account.media_attachments.attached.reorder(nil).select(:status_id).distinct
@statuses.merge!(Status.where(id: account_media_status_ids))
end
@statuses = @statuses.preload(:media_attachments, :mentions).page(params[:page]).per(PER_PAGE)
@form = Form::StatusBatch.new
end
def create
authorize :status, :update?
@form = Form::StatusBatch.new(form_status_batch_params.merge(current_account: current_account))
flash[:alert] = I18n.t('admin.statuses.failed_to_execute') unless @form.save
redirect_to admin_account_statuses_path(@account.id, current_params)
end
def update
authorize @status, :update?
@status.update!(status_params)
log_action :update, @status
redirect_to admin_account_statuses_path(@account.id, current_params)
end
def destroy
authorize @status, :destroy?
RemovalWorker.perform_async(@status.id)
log_action :destroy, @status
render json: @status
end
private
def status_params
params.require(:status).permit(:sensitive)
end
def form_status_batch_params
params.require(:form_status_batch).permit(:action, status_ids: [])
end
def set_status
@status = @account.statuses.find(params[:id])
end
def set_account
@account = Account.find(params[:account_id])
end
def current_params
page = (params[:page] || 1).to_i
{
media: params[:media],
page: page > 1 && page,
}.select { |_, value| value.present? }
end
end
end

View File

@@ -3,7 +3,6 @@
module Admin module Admin
class SubscriptionsController < BaseController class SubscriptionsController < BaseController
def index def index
authorize :subscription, :index?
@subscriptions = ordered_subscriptions.page(requested_page) @subscriptions = ordered_subscriptions.page(requested_page)
end end

View File

@@ -5,16 +5,12 @@ module Admin
before_action :set_account before_action :set_account
def create def create
authorize @account, :suspend?
Admin::SuspensionWorker.perform_async(@account.id) Admin::SuspensionWorker.perform_async(@account.id)
log_action :suspend, @account
redirect_to admin_accounts_path redirect_to admin_accounts_path
end end
def destroy def destroy
authorize @account, :unsuspend? @account.update(suspended: false)
@account.unsuspend!
log_action :unsuspend, @account
redirect_to admin_accounts_path redirect_to admin_accounts_path
end end

View File

@@ -5,9 +5,7 @@ module Admin
before_action :set_user before_action :set_user
def destroy def destroy
authorize @user, :disable_2fa?
@user.disable_two_factor! @user.disable_two_factor!
log_action :disable_2fa, @user
redirect_to admin_accounts_path redirect_to admin_accounts_path
end end

View File

@@ -0,0 +1,27 @@
# frozen_string_literal: true
class Api::ActivityPub::ActivitiesController < Api::BaseController
include Authorization
# before_action :set_follow, only: [:show_follow]
before_action :set_status, only: [:show_status]
respond_to :activitystreams2
# Show a status in AS2 format, as either an Announce (reblog) or a Create (post) activity.
def show_status
authorize @status, :show?
if @status.reblog?
render :show_status_announce
else
render :show_status_create
end
end
private
def set_status
@status = Status.find(params[:id])
end
end

View File

@@ -0,0 +1,19 @@
# frozen_string_literal: true
class Api::ActivityPub::NotesController < Api::BaseController
include Authorization
before_action :set_status
respond_to :activitystreams2
def show
authorize @status, :show?
end
private
def set_status
@status = Status.find(params[:id])
end
end

View File

@@ -0,0 +1,69 @@
# frozen_string_literal: true
class Api::ActivityPub::OutboxController < Api::BaseController
before_action :set_account
respond_to :activitystreams2
def show
if params[:max_id] || params[:since_id]
show_outbox_page
else
show_base_outbox
end
end
private
def show_base_outbox
@statuses = Status.as_outbox_timeline(@account)
@statuses = cache_collection(@statuses)
set_maps(@statuses)
set_first_last_page(@statuses)
render :show
end
def show_outbox_page
all_statuses = Status.as_outbox_timeline(@account)
@statuses = all_statuses.paginate_by_max_id(limit_param(DEFAULT_STATUSES_LIMIT), params[:max_id], params[:since_id])
all_statuses = cache_collection(all_statuses)
@statuses = cache_collection(@statuses)
set_maps(@statuses)
set_first_last_page(all_statuses)
@next_page_url = api_activitypub_outbox_url(pagination_params(max_id: @statuses.last.id)) unless @statuses.empty?
@prev_page_url = api_activitypub_outbox_url(pagination_params(since_id: @statuses.first.id)) unless @statuses.empty?
@paginated = @next_page_url || @prev_page_url
@part_of_url = api_activitypub_outbox_url
set_pagination_headers(@next_page_url, @prev_page_url)
render :show_page
end
def cache_collection(raw)
super(raw, Status)
end
def set_account
@account = Account.find(params[:id])
end
def set_first_last_page(statuses) # rubocop:disable Style/AccessorMethodName
return if statuses.empty?
@first_page_url = api_activitypub_outbox_url(max_id: statuses.first.id + 1)
@last_page_url = api_activitypub_outbox_url(since_id: statuses.last.id - 1)
end
def pagination_params(core_params)
params.permit(:local, :limit).merge(core_params)
end
end

View File

@@ -6,8 +6,8 @@ class Api::BaseController < ApplicationController
include RateLimitHeaders include RateLimitHeaders
skip_before_action :verify_authenticity_token
skip_before_action :store_current_location skip_before_action :store_current_location
protect_from_forgery with: :null_session
rescue_from ActiveRecord::RecordInvalid, Mastodon::ValidationError do |e| rescue_from ActiveRecord::RecordInvalid, Mastodon::ValidationError do |e|
render json: { error: e.to_s }, status: 422 render json: { error: e.to_s }, status: 422
@@ -17,7 +17,11 @@ class Api::BaseController < ApplicationController
render json: { error: 'Record not found' }, status: 404 render json: { error: 'Record not found' }, status: 404
end end
rescue_from HTTP::Error, Mastodon::UnexpectedResponseError do rescue_from Goldfinger::Error do
render json: { error: 'Remote account could not be resolved' }, status: 422
end
rescue_from HTTP::Error do
render json: { error: 'Remote data could not be fetched' }, status: 503 render json: { error: 'Remote data could not be fetched' }, status: 503
end end
@@ -43,7 +47,7 @@ class Api::BaseController < ApplicationController
links = [] links = []
links << [next_path, [%w(rel next)]] if next_path links << [next_path, [%w(rel next)]] if next_path
links << [prev_path, [%w(rel prev)]] if prev_path links << [prev_path, [%w(rel prev)]] if prev_path
response.headers['Link'] = LinkHeader.new(links) unless links.empty? response.headers['Link'] = LinkHeader.new(links)
end end
def limit_param(default_limit) def limit_param(default_limit)
@@ -62,14 +66,28 @@ class Api::BaseController < ApplicationController
end end
def require_user! def require_user!
if current_user current_resource_owner
set_user_activity set_user_activity
else rescue ActiveRecord::RecordNotFound
render json: { error: 'This method requires an authenticated user' }, status: 422 render json: { error: 'This method requires an authenticated user' }, status: 422
end
end end
def render_empty def render_empty
render json: {}, status: 200 render json: {}, status: 200
end end
def set_maps(statuses) # rubocop:disable Style/AccessorMethodName
if current_account.nil?
@reblogs_map = {}
@favourites_map = {}
@mutes_map = {}
return
end
status_ids = statuses.compact.flat_map { |s| [s.id, s.reblog_of_id] }.uniq
conversation_ids = statuses.compact.map(&:conversation_id).compact.uniq
@reblogs_map = Status.reblogs_map(status_ids, current_account)
@favourites_map = Status.favourites_map(status_ids, current_account)
@mutes_map = Status.mutes_map(conversation_ids, current_account)
end
end end

View File

@@ -4,14 +4,15 @@ class Api::OEmbedController < Api::BaseController
respond_to :json respond_to :json
def show def show
@status = status_finder.status @stream_entry = find_stream_entry.stream_entry
render json: @status, serializer: OEmbedSerializer, width: maxwidth_or_default, height: maxheight_or_default @width = maxwidth_or_default
@height = maxheight_or_default
end end
private private
def status_finder def find_stream_entry
StatusFinder.new(params[:url]) StreamEntryFinder.new(params[:url])
end end
def maxwidth_or_default def maxwidth_or_default

View File

@@ -1,8 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::PushController < Api::BaseController class Api::PushController < Api::BaseController
include SignatureVerification
def update def update
response, status = process_push_request response, status = process_push_request
render plain: response, status: status render plain: response, status: status
@@ -13,7 +11,7 @@ class Api::PushController < Api::BaseController
def process_push_request def process_push_request
case hub_mode case hub_mode
when 'subscribe' when 'subscribe'
Pubsubhubbub::SubscribeService.new.call(account_from_topic, hub_callback, hub_secret, hub_lease_seconds, verified_domain) Pubsubhubbub::SubscribeService.new.call(account_from_topic, hub_callback, hub_secret, hub_lease_seconds)
when 'unsubscribe' when 'unsubscribe'
Pubsubhubbub::UnsubscribeService.new.call(account_from_topic, hub_callback) Pubsubhubbub::UnsubscribeService.new.call(account_from_topic, hub_callback)
else else
@@ -59,10 +57,6 @@ class Api::PushController < Api::BaseController
TagManager.instance.web_domain?(hub_topic_domain) TagManager.instance.web_domain?(hub_topic_domain)
end end
def verified_domain
return signed_request_account.domain if signed_request_account
end
def hub_topic_domain def hub_topic_domain
hub_topic_uri.host + (hub_topic_uri.port ? ":#{hub_topic_uri.port}" : '') hub_topic_uri.host + (hub_topic_uri.port ? ":#{hub_topic_uri.port}" : '')
end end

View File

@@ -7,11 +7,9 @@ class Api::SalmonController < Api::BaseController
def update def update
if verify_payload? if verify_payload?
process_salmon process_salmon
head 202 head 201
elsif payload.present?
[signature_verification_failure_reason, 401]
else else
head 400 head 202
end end
end end

View File

@@ -42,7 +42,7 @@ class Api::SubscriptionsController < Api::BaseController
end end
def lease_seconds_or_default def lease_seconds_or_default
(params['hub.lease_seconds'] || 1.day).to_i.seconds (params['hub.lease_seconds'] || 86_400).to_i.seconds
end end
def set_account def set_account

View File

@@ -1,20 +1,18 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Accounts::CredentialsController < Api::BaseController class Api::V1::Accounts::CredentialsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read }, except: [:update]
before_action -> { doorkeeper_authorize! :write }, only: [:update] before_action -> { doorkeeper_authorize! :write }, only: [:update]
before_action :require_user! before_action :require_user!
def show def show
@account = current_account @account = current_account
render json: @account, serializer: REST::CredentialAccountSerializer render 'api/v1/accounts/show'
end end
def update def update
current_account.update!(account_params)
@account = current_account @account = current_account
UpdateAccountService.new.call(@account, account_params, raise_error: true) render 'api/v1/accounts/show'
ActivityPub::UpdateDistributionWorker.perform_async(@account.id)
render json: @account, serializer: REST::CredentialAccountSerializer
end end
private private

View File

@@ -9,7 +9,7 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController
def index def index
@accounts = load_accounts @accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer render 'api/v1/accounts/index'
end end
private private

View File

@@ -9,7 +9,7 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController
def index def index
@accounts = load_accounts @accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer render 'api/v1/accounts/index'
end end
private private

View File

@@ -1,20 +0,0 @@
# frozen_string_literal: true
class Api::V1::Accounts::ListsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read }
before_action :require_user!
before_action :set_account
respond_to :json
def index
@lists = @account.lists.where(account: current_account)
render json: @lists, each_serializer: REST::ListSerializer
end
private
def set_account
@account = Account.find(params[:account_id])
end
end

View File

@@ -7,19 +7,17 @@ class Api::V1::Accounts::RelationshipsController < Api::BaseController
respond_to :json respond_to :json
def index def index
accounts = Account.where(id: account_ids).select('id') @accounts = Account.where(id: account_ids).select('id')
# .where doesn't guarantee that our results are in the same order @following = Account.following_map(account_ids, current_user.account_id)
# we requested them, so return the "right" order to the requestor. @followed_by = Account.followed_by_map(account_ids, current_user.account_id)
@accounts = accounts.index_by(&:id).values_at(*account_ids) @blocking = Account.blocking_map(account_ids, current_user.account_id)
render json: @accounts, each_serializer: REST::RelationshipSerializer, relationships: relationships @muting = Account.muting_map(account_ids, current_user.account_id)
@requested = Account.requested_map(account_ids, current_user.account_id)
@domain_blocking = Account.domain_blocking_map(account_ids, current_user.account_id)
end end
private private
def relationships
AccountRelationshipsPresenter.new(@accounts, current_user.account_id)
end
def account_ids def account_ids
@_account_ids ||= Array(params[:id]).map(&:to_i) @_account_ids ||= Array(params[:id]).map(&:to_i)
end end

View File

@@ -8,7 +8,8 @@ class Api::V1::Accounts::SearchController < Api::BaseController
def show def show
@accounts = account_search @accounts = account_search
render json: @accounts, each_serializer: REST::AccountSerializer
render 'api/v1/accounts/index'
end end
private private
@@ -17,13 +18,12 @@ class Api::V1::Accounts::SearchController < Api::BaseController
AccountSearchService.new.call( AccountSearchService.new.call(
params[:q], params[:q],
limit_param(DEFAULT_ACCOUNTS_LIMIT), limit_param(DEFAULT_ACCOUNTS_LIMIT),
current_account, resolving_search?,
resolve: truthy_param?(:resolve), current_account
following: truthy_param?(:following)
) )
end end
def truthy_param?(key) def resolving_search?
params[key] == 'true' params[:resolve] == 'true'
end end
end end

View File

@@ -9,7 +9,6 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
def index def index
@statuses = load_statuses @statuses = load_statuses
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
end end
private private
@@ -19,7 +18,9 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
end end
def load_statuses def load_statuses
cached_account_statuses cached_account_statuses.tap do |statuses|
set_maps(statuses)
end
end end
def cached_account_statuses def cached_account_statuses
@@ -29,7 +30,6 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
def account_statuses def account_statuses
default_statuses.tap do |statuses| default_statuses.tap do |statuses|
statuses.merge!(only_media_scope) if params[:only_media] statuses.merge!(only_media_scope) if params[:only_media]
statuses.merge!(pinned_scope) if params[:pinned]
statuses.merge!(no_replies_scope) if params[:exclude_replies] statuses.merge!(no_replies_scope) if params[:exclude_replies]
end end
end end
@@ -54,10 +54,6 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
@account.media_attachments.attached.reorder(nil).select(:status_id).distinct @account.media_attachments.attached.reorder(nil).select(:status_id).distinct
end end
def pinned_scope
@account.pinned_statuses
end
def no_replies_scope def no_replies_scope
Status.without_replies Status.without_replies
end end

View File

@@ -8,41 +8,49 @@ class Api::V1::AccountsController < Api::BaseController
respond_to :json respond_to :json
def show def show; end
render json: @account, serializer: REST::AccountSerializer
end
def follow def follow
FollowService.new.call(current_user.account, @account.acct, reblogs: params[:reblogs]) FollowService.new.call(current_user.account, @account.acct)
set_relationship
options = @account.locked? ? {} : { following_map: { @account.id => { reblogs: params[:reblogs] } }, requested_map: { @account.id => false } } render :relationship
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships(options)
end end
def block def block
BlockService.new.call(current_user.account, @account) BlockService.new.call(current_user.account, @account)
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
@following = { @account.id => false }
@followed_by = { @account.id => false }
@blocking = { @account.id => true }
@requested = { @account.id => false }
@muting = { @account.id => current_account.muting?(@account.id) }
@domain_blocking = { @account.id => current_account.domain_blocking?(@account.domain) }
render :relationship
end end
def mute def mute
MuteService.new.call(current_user.account, @account, notifications: params[:notifications]) MuteService.new.call(current_user.account, @account)
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships set_relationship
render :relationship
end end
def unfollow def unfollow
UnfollowService.new.call(current_user.account, @account) UnfollowService.new.call(current_user.account, @account)
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships set_relationship
render :relationship
end end
def unblock def unblock
UnblockService.new.call(current_user.account, @account) UnblockService.new.call(current_user.account, @account)
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships set_relationship
render :relationship
end end
def unmute def unmute
UnmuteService.new.call(current_user.account, @account) UnmuteService.new.call(current_user.account, @account)
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships set_relationship
render :relationship
end end
private private
@@ -51,7 +59,12 @@ class Api::V1::AccountsController < Api::BaseController
@account = Account.find(params[:id]) @account = Account.find(params[:id])
end end
def relationships(**options) def set_relationship
AccountRelationshipsPresenter.new([@account.id], current_user.account_id, options) @following = Account.following_map([@account.id], current_user.account_id)
@followed_by = Account.followed_by_map([@account.id], current_user.account_id)
@blocking = Account.blocking_map([@account.id], current_user.account_id)
@muting = Account.muting_map([@account.id], current_user.account_id)
@requested = Account.requested_map([@account.id], current_user.account_id)
@domain_blocking = Account.domain_blocking_map([@account.id], current_user.account_id)
end end
end end

View File

@@ -1,11 +0,0 @@
# frozen_string_literal: true
class Api::V1::Apps::CredentialsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read }
respond_to :json
def show
render json: doorkeeper_token.application, serializer: REST::StatusSerializer::ApplicationSerializer
end
end

View File

@@ -1,9 +1,10 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::AppsController < Api::BaseController class Api::V1::AppsController < Api::BaseController
respond_to :json
def create def create
@app = Doorkeeper::Application.create!(application_options) @app = Doorkeeper::Application.create!(application_options)
render json: @app, serializer: REST::ApplicationSerializer
end end
private private

View File

@@ -9,23 +9,24 @@ class Api::V1::BlocksController < Api::BaseController
def index def index
@accounts = load_accounts @accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
end end
private private
def load_accounts def load_accounts
paginated_blocks.map(&:target_account) default_accounts.merge(paginated_blocks).to_a
end
def default_accounts
Account.includes(:blocked_by).references(:blocked_by)
end end
def paginated_blocks def paginated_blocks
@paginated_blocks ||= Block.eager_load(:target_account) Block.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 +40,21 @@ class Api::V1::BlocksController < Api::BaseController
end end
def prev_path def prev_path
unless paginated_blocks.empty? unless @accounts.empty?
api_v1_blocks_url pagination_params(since_id: pagination_since_id) api_v1_blocks_url pagination_params(since_id: pagination_since_id)
end end
end end
def pagination_max_id def pagination_max_id
paginated_blocks.last.id @accounts.last.blocked_by_ids.last
end end
def pagination_since_id def pagination_since_id
paginated_blocks.first.id @accounts.first.blocked_by_ids.first
end end
def records_continue? def records_continue?
paginated_blocks.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

@@ -1,9 +0,0 @@
# frozen_string_literal: true
class Api::V1::CustomEmojisController < Api::BaseController
respond_to :json
def index
render json: CustomEmoji.local.where(disabled: false), each_serializer: REST::CustomEmojiSerializer
end
end

View File

@@ -9,18 +9,21 @@ class Api::V1::FavouritesController < Api::BaseController
def index def index
@statuses = load_statuses @statuses = load_statuses
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
end end
private private
def load_statuses def load_statuses
cached_favourites cached_favourites.tap do |statuses|
set_maps(statuses)
end
end end
def cached_favourites def cached_favourites
cache_collection( cache_collection(
Status.reorder(nil).joins(:favourites).merge(results), Status.where(
id: results.map(&:status_id)
),
Status Status
) )
end end

View File

@@ -7,7 +7,6 @@ class Api::V1::FollowRequestsController < Api::BaseController
def index def index
@accounts = load_accounts @accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
end end
def authorize def authorize

View File

@@ -10,13 +10,7 @@ class Api::V1::FollowsController < Api::BaseController
raise ActiveRecord::RecordNotFound if follow_params[:uri].blank? raise ActiveRecord::RecordNotFound if follow_params[:uri].blank?
@account = FollowService.new.call(current_user.account, target_uri).try(:target_account) @account = FollowService.new.call(current_user.account, target_uri).try(:target_account)
render :show
if @account.nil?
username, domain = target_uri.split('@')
@account = Account.find_remote!(username, domain)
end
render json: @account, serializer: REST::AccountSerializer
end end
private private

View File

@@ -1,36 +0,0 @@
# frozen_string_literal: true
class Api::V1::Instances::ActivityController < Api::BaseController
before_action :require_enabled_api!
respond_to :json
def show
render_cached_json('api:v1:instances:activity:show', expires_in: 1.day) { activity }
end
private
def activity
weeks = []
12.times do |i|
day = i.weeks.ago.to_date
week_id = day.cweek
week = Date.commercial(day.cwyear, week_id)
weeks << {
week: week.to_time.to_i.to_s,
statuses: Redis.current.get("activity:statuses:local:#{week_id}") || '0',
logins: Redis.current.pfcount("activity:logins:#{week_id}").to_s,
registrations: Redis.current.get("activity:accounts:local:#{week_id}") || '0',
}
end
weeks
end
def require_enabled_api!
head 404 unless Setting.activity_api_enabled
end
end

View File

@@ -1,17 +0,0 @@
# frozen_string_literal: true
class Api::V1::Instances::PeersController < Api::BaseController
before_action :require_enabled_api!
respond_to :json
def index
render_cached_json('api:v1:instances:peers:index', expires_in: 1.day) { Account.remote.domains }
end
private
def require_enabled_api!
head 404 unless Setting.peers_api_enabled
end
end

View File

@@ -3,7 +3,5 @@
class Api::V1::InstancesController < Api::BaseController class Api::V1::InstancesController < Api::BaseController
respond_to :json respond_to :json
def show def show; end
render json: {}, serializer: REST::InstanceSerializer
end
end end

View File

@@ -1,97 +0,0 @@
# frozen_string_literal: true
class Api::V1::Lists::AccountsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read }, only: [:show]
before_action -> { doorkeeper_authorize! :write }, except: [:show]
before_action :require_user!
before_action :set_list
after_action :insert_pagination_headers, only: :show
def show
@accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
end
def create
ApplicationRecord.transaction do
list_accounts.each do |account|
@list.accounts << account
end
end
render_empty
end
def destroy
ListAccount.where(list: @list, account_id: account_ids).destroy_all
render_empty
end
private
def set_list
@list = List.where(account: current_account).find(params[:list_id])
end
def load_accounts
if unlimited?
@list.accounts.all
else
@list.accounts.paginate_by_max_id(limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:max_id], params[:since_id])
end
end
def list_accounts
Account.find(account_ids)
end
def account_ids
Array(resource_params[:account_ids])
end
def resource_params
params.permit(account_ids: [])
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def next_path
return if unlimited?
if records_continue?
api_v1_list_accounts_url pagination_params(max_id: pagination_max_id)
end
end
def prev_path
return if unlimited?
unless @accounts.empty?
api_v1_list_accounts_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.permit(:limit).merge(core_params)
end
def unlimited?
params[:limit] == '0'
end
end

View File

@@ -1,43 +0,0 @@
# frozen_string_literal: true
class Api::V1::ListsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read }, only: [:index, :show]
before_action -> { doorkeeper_authorize! :write }, except: [:index, :show]
before_action :require_user!
before_action :set_list, except: [:index, :create]
def index
@lists = List.where(account: current_account).all
render json: @lists, each_serializer: REST::ListSerializer
end
def show
render json: @list, serializer: REST::ListSerializer
end
def create
@list = List.create!(list_params.merge(account: current_account))
render json: @list, serializer: REST::ListSerializer
end
def update
@list.update!(list_params)
render json: @list, serializer: REST::ListSerializer
end
def destroy
@list.destroy!
render_empty
end
private
def set_list
@list = List.where(account: current_account).find(params[:id])
end
def list_params
params.permit(:title)
end
end

View File

@@ -10,24 +10,17 @@ class Api::V1::MediaController < Api::BaseController
respond_to :json respond_to :json
def create def create
@media = current_account.media_attachments.create!(media_params) @media = current_account.media_attachments.create!(file: media_params[:file])
render json: @media, serializer: REST::MediaAttachmentSerializer
rescue Paperclip::Errors::NotIdentifiedByImageMagickError rescue Paperclip::Errors::NotIdentifiedByImageMagickError
render json: file_type_error, status: 422 render json: file_type_error, status: 422
rescue Paperclip::Error rescue Paperclip::Error
render json: processing_error, status: 500 render json: processing_error, status: 500
end end
def update
@media = current_account.media_attachments.where(status_id: nil).find(params[:id])
@media.update!(media_params)
render json: @media, serializer: REST::MediaAttachmentSerializer
end
private private
def media_params def media_params
params.permit(:file, :description) params.permit(:file)
end end
def file_type_error def file_type_error

View File

@@ -8,15 +8,9 @@ class Api::V1::MutesController < Api::BaseController
respond_to :json respond_to :json
def index def index
@data = @accounts = load_accounts @accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
end end
def details
@data = @mutes = load_mutes
render json: @mutes, each_serializer: REST::MuteSerializer
end
private private
def load_accounts def load_accounts
@@ -27,10 +21,6 @@ class Api::V1::MutesController < Api::BaseController
Account.includes(:muted_by).references(:muted_by) Account.includes(:muted_by).references(:muted_by)
end end
def load_mutes
paginated_mutes.includes(:account, :target_account).to_a
end
def paginated_mutes def paginated_mutes
Mute.where(account: current_account).paginate_by_max_id( Mute.where(account: current_account).paginate_by_max_id(
limit_param(DEFAULT_ACCOUNTS_LIMIT), limit_param(DEFAULT_ACCOUNTS_LIMIT),
@@ -45,34 +35,26 @@ class Api::V1::MutesController < Api::BaseController
def next_path def next_path
if records_continue? if records_continue?
url_for pagination_params(max_id: pagination_max_id) api_v1_mutes_url pagination_params(max_id: pagination_max_id)
end end
end end
def prev_path def prev_path
unless@data.empty? unless @accounts.empty?
url_for 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
if params[:action] == "details" @accounts.last.muted_by_ids.last
@mutes.last.id
else
@accounts.last.muted_by_ids.last
end
end end
def pagination_since_id def pagination_since_id
if params[:action] == "details" @accounts.first.muted_by_ids.first
@mutes.first.id
else
@accounts.first.muted_by_ids.first
end
end end
def records_continue? def records_continue?
@data.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

@@ -11,12 +11,11 @@ class Api::V1::NotificationsController < Api::BaseController
def index def index
@notifications = load_notifications @notifications = load_notifications
render json: @notifications, each_serializer: REST::NotificationSerializer, relationships: StatusRelationshipsPresenter.new(target_statuses_from_notifications, current_user&.account_id) set_maps_for_notification_target_statuses
end end
def show def show
@notification = current_account.notifications.find(params[:id]) @notification = current_account.notifications.find(params[:id])
render json: @notification, serializer: REST::NotificationSerializer
end end
def clear def clear
@@ -24,20 +23,11 @@ class Api::V1::NotificationsController < Api::BaseController
render_empty render_empty
end end
def destroy
dismiss
end
def dismiss def dismiss
current_account.notifications.find_by!(id: params[:id]).destroy! current_account.notifications.find_by!(id: params[:id]).destroy!
render_empty render_empty
end end
def destroy_multiple
current_account.notifications.where(id: params[:ids]).destroy_all
render_empty
end
private private
def load_notifications def load_notifications
@@ -56,6 +46,10 @@ class Api::V1::NotificationsController < Api::BaseController
current_account.notifications.browserable(exclude_types) current_account.notifications.browserable(exclude_types)
end end
def set_maps_for_notification_target_statuses
set_maps target_statuses_from_notifications
end
def target_statuses_from_notifications def target_statuses_from_notifications
@notifications.reject { |notification| notification.target_status.nil? }.map(&:target_status) @notifications.reject { |notification| notification.target_status.nil? }.map(&:target_status)
end end

View File

@@ -9,7 +9,6 @@ class Api::V1::ReportsController < Api::BaseController
def index def index
@reports = current_account.reports @reports = current_account.reports
render json: @reports, each_serializer: REST::ReportSerializer
end end
def create def create
@@ -18,10 +17,7 @@ class Api::V1::ReportsController < Api::BaseController
status_ids: reported_status_ids, status_ids: reported_status_ids,
comment: report_params[:comment] comment: report_params[:comment]
) )
render :show
User.staff.includes(:account).each { |u| AdminMailer.new_report(u.account, @report).deliver_later }
render json: @report, serializer: REST::ReportSerializer
end end
private private

View File

@@ -1,34 +1,16 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::SearchController < Api::BaseController class Api::V1::SearchController < Api::BaseController
include Authorization RESULTS_LIMIT = 5
RESULTS_LIMIT = 10
before_action -> { doorkeeper_authorize! :read }
before_action :require_user!
respond_to :json respond_to :json
def index def index
@search = Search.new(search) @search = OpenStruct.new(search_results)
render json: @search, serializer: REST::SearchSerializer
end end
private private
def search
search_results.tap do |search|
search[:statuses].keep_if do |status|
begin
authorize status, :show?
rescue Mastodon::NotPermittedError
false
end
end
end
end
def search_results def search_results
SearchService.new.call( SearchService.new.call(
params[:q], params[:q],

View File

@@ -11,7 +11,7 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController
def index def index
@accounts = load_accounts @accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer render 'api/v1/statuses/accounts'
end end
private private

View File

@@ -10,7 +10,7 @@ class Api::V1::Statuses::FavouritesController < Api::BaseController
def create def create
@status = favourited_status @status = favourited_status
render json: @status, serializer: REST::StatusSerializer render 'api/v1/statuses/show'
end end
def destroy def destroy
@@ -19,7 +19,7 @@ class Api::V1::Statuses::FavouritesController < Api::BaseController
UnfavouriteWorker.perform_async(current_user.account_id, @status.id) UnfavouriteWorker.perform_async(current_user.account_id, @status.id)
render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_user&.account_id, favourites_map: @favourites_map) render 'api/v1/statuses/show'
end end
private private

View File

@@ -14,14 +14,14 @@ class Api::V1::Statuses::MutesController < Api::BaseController
current_account.mute_conversation!(@conversation) current_account.mute_conversation!(@conversation)
@mutes_map = { @conversation.id => true } @mutes_map = { @conversation.id => true }
render json: @status, serializer: REST::StatusSerializer render 'api/v1/statuses/show'
end end
def destroy def destroy
current_account.unmute_conversation!(@conversation) current_account.unmute_conversation!(@conversation)
@mutes_map = { @conversation.id => false } @mutes_map = { @conversation.id => false }
render json: @status, serializer: REST::StatusSerializer render 'api/v1/statuses/show'
end end
private private

View File

@@ -1,28 +0,0 @@
# frozen_string_literal: true
class Api::V1::Statuses::PinsController < Api::BaseController
include Authorization
before_action -> { doorkeeper_authorize! :write }
before_action :require_user!
before_action :set_status
respond_to :json
def create
StatusPin.create!(account: current_account, status: @status)
render json: @status, serializer: REST::StatusSerializer
end
def destroy
pin = StatusPin.find_by(account: current_account, status: @status)
pin&.destroy!
render json: @status, serializer: REST::StatusSerializer
end
private
def set_status
@status = Status.find(params[:status_id])
end
end

View File

@@ -11,7 +11,7 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController
def index def index
@accounts = load_accounts @accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer render 'api/v1/statuses/accounts'
end end
private private

View File

@@ -10,7 +10,7 @@ class Api::V1::Statuses::ReblogsController < Api::BaseController
def create def create
@status = ReblogService.new.call(current_user.account, status_for_reblog) @status = ReblogService.new.call(current_user.account, status_for_reblog)
render json: @status, serializer: REST::StatusSerializer render 'api/v1/statuses/show'
end end
def destroy def destroy
@@ -20,7 +20,7 @@ class Api::V1::Statuses::ReblogsController < Api::BaseController
authorize status_for_destroy, :unreblog? authorize status_for_destroy, :unreblog?
RemovalWorker.perform_async(status_for_destroy.id) RemovalWorker.perform_async(status_for_destroy.id)
render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_user&.account_id, reblogs_map: @reblogs_map) render 'api/v1/statuses/show'
end end
private private

View File

@@ -13,7 +13,6 @@ class Api::V1::StatusesController < Api::BaseController
def show def show
cached = Rails.cache.read(@status.cache_key) cached = Rails.cache.read(@status.cache_key)
@status = cached unless cached.nil? @status = cached unless cached.nil?
render json: @status, serializer: REST::StatusSerializer
end end
def context def context
@@ -22,20 +21,15 @@ class Api::V1::StatusesController < Api::BaseController
loaded_ancestors = cache_collection(ancestors_results, Status) loaded_ancestors = cache_collection(ancestors_results, Status)
loaded_descendants = cache_collection(descendants_results, Status) loaded_descendants = cache_collection(descendants_results, Status)
@context = Context.new(ancestors: loaded_ancestors, descendants: loaded_descendants) @context = OpenStruct.new(ancestors: loaded_ancestors, descendants: loaded_descendants)
statuses = [@status] + @context.ancestors + @context.descendants statuses = [@status] + @context[:ancestors] + @context[:descendants]
render json: @context, serializer: REST::ContextSerializer, relationships: StatusRelationshipsPresenter.new(statuses, current_user&.account_id) set_maps(statuses)
end end
def card def card
@card = @status.preview_cards.first @card = PreviewCard.find_by(status: @status)
render_empty if @card.nil?
if @card.nil?
render_empty
else
render json: @card, serializer: REST::PreviewCardSerializer
end
end end
def create def create
@@ -49,7 +43,7 @@ class Api::V1::StatusesController < Api::BaseController
application: doorkeeper_token.application, application: doorkeeper_token.application,
idempotency: request.headers['Idempotency-Key']) idempotency: request.headers['Idempotency-Key'])
render json: @status, serializer: REST::StatusSerializer render :show
end end
def destroy def destroy

View File

@@ -1,60 +0,0 @@
# frozen_string_literal: true
class Api::V1::Timelines::DirectController < Api::BaseController
before_action -> { doorkeeper_authorize! :read }, only: [:show]
before_action :require_user!, only: [:show]
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
respond_to :json
def show
@statuses = load_statuses
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
end
private
def load_statuses
cached_direct_statuses
end
def cached_direct_statuses
cache_collection direct_statuses, Status
end
def direct_statuses
direct_timeline_statuses.paginate_by_max_id(
limit_param(DEFAULT_STATUSES_LIMIT),
params[:max_id],
params[:since_id]
)
end
def direct_timeline_statuses
Status.as_direct_timeline(current_account)
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def pagination_params(core_params)
params.permit(:local, :limit).merge(core_params)
end
def next_path
api_v1_timelines_direct_url pagination_params(max_id: pagination_max_id)
end
def prev_path
api_v1_timelines_direct_url pagination_params(since_id: pagination_since_id)
end
def pagination_max_id
@statuses.last.id
end
def pagination_since_id
@statuses.first.id
end
end

View File

@@ -9,13 +9,15 @@ class Api::V1::Timelines::HomeController < Api::BaseController
def show def show
@statuses = load_statuses @statuses = load_statuses
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id) render 'api/v1/timelines/show'
end end
private private
def load_statuses def load_statuses
cached_home_statuses cached_home_statuses.tap do |statuses|
set_maps(statuses)
end
end end
def cached_home_statuses def cached_home_statuses
@@ -31,7 +33,7 @@ class Api::V1::Timelines::HomeController < Api::BaseController
end end
def account_home_feed def account_home_feed
HomeFeed.new(current_account) Feed.new(:home, current_account)
end end
def insert_pagination_headers def insert_pagination_headers

View File

@@ -1,66 +0,0 @@
# frozen_string_literal: true
class Api::V1::Timelines::ListController < Api::BaseController
before_action -> { doorkeeper_authorize! :read }
before_action :require_user!
before_action :set_list
before_action :set_statuses
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
def show
render json: @statuses,
each_serializer: REST::StatusSerializer,
relationships: StatusRelationshipsPresenter.new(@statuses, current_user.account_id)
end
private
def set_list
@list = List.where(account: current_account).find(params[:id])
end
def set_statuses
@statuses = cached_list_statuses
end
def cached_list_statuses
cache_collection list_statuses, Status
end
def list_statuses
list_feed.get(
limit_param(DEFAULT_STATUSES_LIMIT),
params[:max_id],
params[:since_id]
)
end
def list_feed
ListFeed.new(@list)
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def pagination_params(core_params)
params.permit(:limit).merge(core_params)
end
def next_path
api_v1_timelines_list_url params[:id], pagination_params(max_id: pagination_max_id)
end
def prev_path
api_v1_timelines_list_url params[:id], pagination_params(since_id: pagination_since_id)
end
def pagination_max_id
@statuses.last.id
end
def pagination_since_id
@statuses.first.id
end
end

View File

@@ -7,13 +7,15 @@ class Api::V1::Timelines::PublicController < Api::BaseController
def show def show
@statuses = load_statuses @statuses = load_statuses
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id) render 'api/v1/timelines/show'
end end
private private
def load_statuses def load_statuses
cached_public_statuses cached_public_statuses.tap do |statuses|
set_maps(statuses)
end
end end
def cached_public_statuses def cached_public_statuses

View File

@@ -8,7 +8,7 @@ class Api::V1::Timelines::TagController < Api::BaseController
def show def show
@statuses = load_statuses @statuses = load_statuses
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id) render 'api/v1/timelines/show'
end end
private private
@@ -18,7 +18,9 @@ class Api::V1::Timelines::TagController < Api::BaseController
end end
def load_statuses def load_statuses
cached_tagged_statuses cached_tagged_statuses.tap do |statuses|
set_maps(statuses)
end
end end
def cached_tagged_statuses def cached_tagged_statuses

View File

@@ -1,17 +0,0 @@
# frozen_string_literal: true
class Api::Web::EmbedsController < Api::BaseController
respond_to :json
before_action :require_user!
def create
status = StatusFinder.new(params[:url]).status
render json: status, serializer: OEmbedSerializer, width: 400
rescue ActiveRecord::RecordNotFound
oembed = OEmbed::Providers.get(params[:url])
render json: Oj.dump(oembed.fields)
rescue OEmbed::NotFound
render json: {}, status: :not_found
end
end

View File

@@ -1,54 +0,0 @@
# frozen_string_literal: true
class Api::Web::PushSubscriptionsController < Api::BaseController
respond_to :json
before_action :require_user!
def create
params.require(:subscription).require(:endpoint)
params.require(:subscription).require(:keys).require([:auth, :p256dh])
active_session = current_session
unless active_session.web_push_subscription.nil?
active_session.web_push_subscription.destroy!
active_session.update!(web_push_subscription: nil)
end
# Mobile devices do not support regular notifications, so we enable push notifications by default
alerts_enabled = active_session.detection.device.mobile? || active_session.detection.device.tablet?
data = {
alerts: {
follow: alerts_enabled,
favourite: alerts_enabled,
reblog: alerts_enabled,
mention: alerts_enabled,
},
}
data.deep_merge!(params[:data]) if params[:data]
web_subscription = ::Web::PushSubscription.create!(
endpoint: params[:subscription][:endpoint],
key_p256dh: params[:subscription][:keys][:p256dh],
key_auth: params[:subscription][:keys][:auth],
data: data
)
active_session.update!(web_push_subscription: web_subscription)
render json: web_subscription.as_payload
end
def update
params.require([:id, :data])
web_subscription = ::Web::PushSubscription.find(params[:id])
web_subscription.update!(data: params[:data])
render json: web_subscription.as_payload
end
end

View File

@@ -11,15 +11,11 @@ class ApplicationController < ActionController::Base
include UserTrackingConcern include UserTrackingConcern
helper_method :current_account helper_method :current_account
helper_method :current_session
helper_method :current_flavour
helper_method :current_skin
helper_method :single_user_mode? helper_method :single_user_mode?
rescue_from ActionController::RoutingError, with: :not_found rescue_from ActionController::RoutingError, with: :not_found
rescue_from ActiveRecord::RecordNotFound, with: :not_found rescue_from ActiveRecord::RecordNotFound, with: :not_found
rescue_from ActionController::InvalidAuthenticityToken, with: :unprocessable_entity rescue_from ActionController::InvalidAuthenticityToken, with: :unprocessable_entity
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_suspension, if: :user_signed_in? before_action :check_suspension, if: :user_signed_in?
@@ -31,7 +27,7 @@ class ApplicationController < ActionController::Base
private private
def https_enabled? def https_enabled?
Rails.env.production? Rails.env.production? && ENV['LOCAL_HTTPS'] == 'true'
end end
def store_current_location def store_current_location
@@ -42,87 +38,10 @@ class ApplicationController < ActionController::Base
redirect_to root_path unless current_user&.admin? redirect_to root_path unless current_user&.admin?
end end
def require_staff!
redirect_to root_path unless current_user&.staff?
end
def check_suspension def check_suspension
forbidden if current_user.account.suspended? forbidden if current_user.account.suspended?
end end
def after_sign_out_path_for(_resource_or_scope)
new_user_session_path
end
def pack(data, pack_name, skin = 'default')
return nil unless pack?(data, pack_name)
pack_data = {
common: pack_name == 'common' ? nil : resolve_pack(data['name'] ? Themes.instance.flavour(current_flavour) : Themes.instance.core, 'common', skin),
flavour: data['name'],
pack: pack_name,
preload: nil,
skin: nil,
supported_locales: data['locales'],
}
if data['pack'][pack_name].is_a?(Hash)
pack_data[:common] = nil if data['pack'][pack_name]['use_common'] == false
pack_data[:pack] = nil unless data['pack'][pack_name]['filename']
if data['pack'][pack_name]['preload']
pack_data[:preload] = [data['pack'][pack_name]['preload']] if data['pack'][pack_name]['preload'].is_a?(String)
pack_data[:preload] = data['pack'][pack_name]['preload'] if data['pack'][pack_name]['preload'].is_a?(Array)
end
if skin != 'default' && data['skin'][skin]
pack_data[:skin] = skin if data['skin'][skin].include?(pack_name)
else # default skin
pack_data[:skin] = 'default' if data['pack'][pack_name]['stylesheet']
end
end
pack_data
end
def pack?(data, pack_name)
if data['pack'].is_a?(Hash) && data['pack'].key?(pack_name)
return true if data['pack'][pack_name].is_a?(String) || data['pack'][pack_name].is_a?(Hash)
end
false
end
def nil_pack(data, pack_name, skin = 'default')
{
common: pack_name == 'common' ? nil : resolve_pack(data['name'] ? Themes.instance.flavour(current_flavour) : Themes.instance.core, 'common', skin),
flavour: data['name'],
pack: nil,
preload: nil,
skin: nil,
supported_locales: data['locales'],
}
end
def resolve_pack(data, pack_name, skin = 'default')
result = pack(data, pack_name, skin)
unless result
if data['name'] && data.key?('fallback')
if data['fallback'].nil?
return nil_pack(data, pack_name, skin)
elsif data['fallback'].is_a?(String) && Themes.instance.flavour(data['fallback'])
return resolve_pack(Themes.instance.flavour(data['fallback']), pack_name)
elsif data['fallback'].is_a?(Array)
data['fallback'].each do |fallback|
return resolve_pack(Themes.instance.flavour(fallback), pack_name) if Themes.instance.flavour(fallback)
end
end
return nil_pack(data, pack_name, skin)
end
return data.key?('name') && data['name'] != Setting.default_settings['flavour'] ? resolve_pack(Themes.instance.flavour(Setting.default_settings['flavour']), pack_name) : nil_pack(data, pack_name, skin)
end
result
end
def use_pack(pack_name)
@core = resolve_pack(Themes.instance.core, pack_name)
@theme = resolve_pack(Themes.instance.flavour(current_flavour), pack_name, current_skin)
end
protected protected
def forbidden def forbidden
@@ -149,20 +68,6 @@ class ApplicationController < ActionController::Base
@current_account ||= current_user.try(:account) @current_account ||= current_user.try(:account)
end end
def current_session
@current_session ||= SessionActivation.find_by(session_id: cookies.signed['_session_id'])
end
def current_flavour
return Setting.default_settings['flavour'] unless Themes.instance.flavours.include? current_user&.setting_flavour
current_user.setting_flavour
end
def current_skin
return 'default' unless Themes.instance.skins_for(current_flavour).include? current_user&.setting_skin
current_user.setting_skin
end
def cache_collection(raw, klass) def cache_collection(raw, klass)
return raw unless klass.respond_to?(:with_includes) return raw unless klass.respond_to?(:with_includes)
@@ -179,7 +84,7 @@ class ApplicationController < ActionController::Base
unless uncached_ids.empty? unless uncached_ids.empty?
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.values.each do |item|
Rails.cache.write(item.cache_key, item) Rails.cache.write(item.cache_key, item)
end end
end end
@@ -192,31 +97,8 @@ class ApplicationController < ActionController::Base
format.any { head code } format.any { head code }
format.html do format.html do
set_locale set_locale
use_pack 'error'
render "errors/#{code}", layout: 'error', status: code render "errors/#{code}", layout: 'error', status: code
end end
end end
end end
def render_cached_json(cache_key, **options)
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
content_type = options.delete(:content_type) || 'application/json'
data = Rails.cache.fetch(cache_key, { raw: true }.merge(options)) do
yield.to_json
end
expires_in options[:expires_in], public: cache_public
render json: data, content_type: content_type
end
def set_cache_headers
response.headers['Vary'] = 'Accept'
end
def skip_session!
request.session_options[:skip] = true
end
end end

View File

@@ -2,12 +2,4 @@
class Auth::ConfirmationsController < Devise::ConfirmationsController class Auth::ConfirmationsController < Devise::ConfirmationsController
layout 'auth' layout 'auth'
before_action :set_pack
private
def set_pack
use_pack 'auth'
end
end end

View File

@@ -1,25 +1,5 @@
# frozen_string_literal: true # frozen_string_literal: true
class Auth::PasswordsController < Devise::PasswordsController class Auth::PasswordsController < Devise::PasswordsController
before_action :check_validity_of_reset_password_token, only: :edit
before_action :set_pack
layout 'auth' layout 'auth'
private
def check_validity_of_reset_password_token
unless reset_password_token_is_valid?
flash[:error] = I18n.t('auth.invalid_reset_password_token')
redirect_to new_password_path(resource_name)
end
end
def reset_password_token_is_valid?
resource_class.with_reset_password_token(params[:reset_password_token]).present?
end
def set_pack
use_pack 'auth'
end
end end

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