1826 changed files with 65997 additions and 28478 deletions
@ -1,276 +1,209 @@
|
||||
version: 2 |
||||
version: 2.1 |
||||
|
||||
aliases: |
||||
- &defaults |
||||
orbs: |
||||
ruby: circleci/ruby@1.4.1 |
||||
node: circleci/node@5.0.1 |
||||
|
||||
executors: |
||||
default: |
||||
parameters: |
||||
ruby-version: |
||||
type: string |
||||
docker: |
||||
- image: circleci/ruby:2.7-buster-node |
||||
environment: &ruby_environment |
||||
- image: cimg/ruby:<< parameters.ruby-version >> |
||||
environment: |
||||
BUNDLE_JOBS: 3 |
||||
BUNDLE_RETRY: 3 |
||||
BUNDLE_APP_CONFIG: ./.bundle/ |
||||
BUNDLE_PATH: ./vendor/bundle/ |
||||
CONTINUOUS_INTEGRATION: true |
||||
DB_HOST: localhost |
||||
DB_USER: root |
||||
RAILS_ENV: test |
||||
ALLOW_NOPAM: true |
||||
CONTINUOUS_INTEGRATION: true |
||||
DISABLE_SIMPLECOV: true |
||||
PAM_ENABLED: true |
||||
PAM_DEFAULT_SERVICE: pam_test |
||||
PAM_CONTROLLED_SERVICE: pam_test_controlled |
||||
working_directory: ~/projects/mastodon/ |
||||
|
||||
- &attach_workspace |
||||
attach_workspace: |
||||
at: ~/projects/ |
||||
|
||||
- &persist_to_workspace |
||||
persist_to_workspace: |
||||
root: ~/projects/ |
||||
paths: |
||||
- ./mastodon/ |
||||
|
||||
- &restore_ruby_dependencies |
||||
restore_cache: |
||||
keys: |
||||
- v3-ruby-dependencies-{{ checksum "/tmp/.ruby-version" }}-{{ checksum "Gemfile.lock" }} |
||||
- v3-ruby-dependencies-{{ checksum "/tmp/.ruby-version" }}- |
||||
- v3-ruby-dependencies- |
||||
RAILS_ENV: test |
||||
- image: cimg/postgres:14.0 |
||||
environment: |
||||
POSTGRES_USER: root |
||||
POSTGRES_HOST_AUTH_METHOD: trust |
||||
- image: cimg/redis:6.2 |
||||
|
||||
- &install_steps |
||||
commands: |
||||
install-system-dependencies: |
||||
steps: |
||||
- checkout |
||||
- *attach_workspace |
||||
- restore_cache: |
||||
keys: |
||||
- v2-node-dependencies-{{ checksum "yarn.lock" }} |
||||
- v2-node-dependencies- |
||||
- run: |
||||
name: Install yarn dependencies |
||||
command: yarn install --frozen-lockfile |
||||
- save_cache: |
||||
key: v2-node-dependencies-{{ checksum "yarn.lock" }} |
||||
paths: |
||||
- ./node_modules/ |
||||
- *persist_to_workspace |
||||
|
||||
- &install_system_dependencies |
||||
run: |
||||
name: Install system dependencies |
||||
command: | |
||||
sudo apt-get update |
||||
sudo apt-get install -y libicu-dev libidn11-dev libprotobuf-dev protobuf-compiler |
||||
|
||||
- &install_ruby_dependencies |
||||
steps: |
||||
- *attach_workspace |
||||
- *install_system_dependencies |
||||
- run: |
||||
name: Set Ruby version |
||||
command: ruby -e 'puts RUBY_VERSION' | tee /tmp/.ruby-version |
||||
- *restore_ruby_dependencies |
||||
- run: |
||||
name: Set bundler settings |
||||
command: | |
||||
bundle config --local clean 'true' |
||||
bundle config --local deployment 'true' |
||||
bundle config --local with 'pam_authentication' |
||||
bundle config --local without 'development production' |
||||
bundle config --local frozen 'true' |
||||
bundle config --local path $BUNDLE_PATH |
||||
- run: |
||||
name: Install bundler dependencies |
||||
command: bundle check || (bundle install && bundle clean) |
||||
- save_cache: |
||||
key: v3-ruby-dependencies-{{ checksum "/tmp/.ruby-version" }}-{{ checksum "Gemfile.lock" }} |
||||
paths: |
||||
- ./.bundle/ |
||||
- ./vendor/bundle/ |
||||
- persist_to_workspace: |
||||
root: ~/projects/ |
||||
paths: |
||||
- ./mastodon/.bundle/ |
||||
- ./mastodon/vendor/bundle/ |
||||
name: Install system dependencies |
||||
command: | |
||||
sudo apt-get update |
||||
sudo apt-get install -y libicu-dev libidn11-dev |
||||
install-ruby-dependencies: |
||||
parameters: |
||||
ruby-version: |
||||
type: string |
||||
steps: |
||||
- run: |
||||
command: | |
||||
bundle config clean 'true' |
||||
bundle config frozen 'true' |
||||
bundle config without 'development production' |
||||
name: Set bundler settings |
||||
- ruby/install-deps: |
||||
bundler-version: '2.3.8' |
||||
key: ruby<< parameters.ruby-version >>-gems-v1 |
||||
wait-db: |
||||
steps: |
||||
- run: |
||||
command: dockerize -wait tcp://localhost:5432 -wait tcp://localhost:6379 -timeout 1m |
||||
name: Wait for PostgreSQL and Redis |
||||
|
||||
- &test_steps |
||||
parallelism: 4 |
||||
steps: |
||||
- *attach_workspace |
||||
- *install_system_dependencies |
||||
- run: |
||||
name: Install FFMPEG |
||||
command: sudo apt-get install -y ffmpeg |
||||
- run: |
||||
name: Load database schema |
||||
command: ./bin/rails db:create db:schema:load db:seed |
||||
- run: |
||||
name: Run rspec in parallel |
||||
command: | |
||||
bundle exec rspec --profile 10 \ |
||||
--format RspecJunitFormatter \ |
||||
--out test_results/rspec.xml \ |
||||
--format progress \ |
||||
$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings) |
||||
- store_test_results: |
||||
path: test_results |
||||
jobs: |
||||
install: |
||||
<<: *defaults |
||||
<<: *install_steps |
||||
|
||||
install-ruby2.7: |
||||
<<: *defaults |
||||
<<: *install_ruby_dependencies |
||||
|
||||
install-ruby2.6: |
||||
<<: *defaults |
||||
docker: |
||||
- image: circleci/ruby:2.6-buster-node |
||||
environment: *ruby_environment |
||||
<<: *install_ruby_dependencies |
||||
|
||||
install-ruby3.0: |
||||
<<: *defaults |
||||
docker: |
||||
- image: circleci/ruby:3.0-buster-node |
||||
environment: *ruby_environment |
||||
<<: *install_ruby_dependencies |
||||
|
||||
build: |
||||
<<: *defaults |
||||
docker: |
||||
- image: cimg/ruby:3.0-node |
||||
environment: |
||||
RAILS_ENV: test |
||||
steps: |
||||
- *attach_workspace |
||||
- *install_system_dependencies |
||||
- checkout |
||||
- install-system-dependencies |
||||
- install-ruby-dependencies: |
||||
ruby-version: '3.0' |
||||
- node/install-packages: |
||||
cache-version: v1 |
||||
pkg-manager: yarn |
||||
- run: |
||||
name: Precompile assets |
||||
command: ./bin/rails assets:precompile |
||||
name: Precompile assets |
||||
- persist_to_workspace: |
||||
root: ~/projects/ |
||||
paths: |
||||
- ./mastodon/public/assets |
||||
- ./mastodon/public/packs-test/ |
||||
- public/assets |
||||
- public/packs-test |
||||
root: . |
||||
|
||||
test: |
||||
parameters: |
||||
ruby-version: |
||||
type: string |
||||
executor: |
||||
name: default |
||||
ruby-version: << parameters.ruby-version >> |
||||
environment: |
||||
ALLOW_NOPAM: true |
||||
PAM_ENABLED: true |
||||
PAM_DEFAULT_SERVICE: pam_test |
||||
PAM_CONTROLLED_SERVICE: pam_test_controlled |
||||
parallelism: 4 |
||||
steps: |
||||
- checkout |
||||
- install-system-dependencies |
||||
- run: |
||||
command: sudo apt-get install -y ffmpeg imagemagick libpam-dev |
||||
name: Install additional system dependencies |
||||
- run: |
||||
command: bundle config with 'pam_authentication' |
||||
name: Enable PAM authentication |
||||
- install-ruby-dependencies: |
||||
ruby-version: << parameters.ruby-version >> |
||||
- attach_workspace: |
||||
at: . |
||||
- wait-db |
||||
- run: |
||||
command: ./bin/rails db:create db:schema:load db:seed |
||||
name: Load database schema |
||||
- ruby/rspec-test |
||||
|
||||
test-migrations: |
||||
<<: *defaults |
||||
docker: |
||||
- image: circleci/ruby:2.7-buster-node |
||||
environment: *ruby_environment |
||||
- image: circleci/postgres:12.2 |
||||
environment: |
||||
POSTGRES_USER: root |
||||
POSTGRES_HOST_AUTH_METHOD: trust |
||||
- image: circleci/redis:5-alpine |
||||
executor: |
||||
name: default |
||||
ruby-version: '3.0' |
||||
steps: |
||||
- *attach_workspace |
||||
- *install_system_dependencies |
||||
- checkout |
||||
- install-system-dependencies |
||||
- install-ruby-dependencies: |
||||
ruby-version: '3.0' |
||||
- wait-db |
||||
- run: |
||||
name: Create database |
||||
command: ./bin/rails db:create |
||||
name: Create database |
||||
- run: |
||||
command: ./bin/rails db:migrate VERSION=20171010025614 |
||||
name: Run migrations up to v2.0.0 |
||||
- run: |
||||
command: ./bin/rails tests:migrations:populate_v2 |
||||
name: Populate database with test data |
||||
- run: |
||||
command: ./bin/rails db:migrate VERSION=20180514140000 |
||||
name: Run migrations up to v2.4.0 |
||||
- run: |
||||
command: ./bin/rails tests:migrations:populate_v2_4 |
||||
name: Populate database with test data |
||||
- run: |
||||
name: Run migrations |
||||
command: ./bin/rails db:migrate |
||||
|
||||
test-ruby2.7: |
||||
<<: *defaults |
||||
docker: |
||||
- image: circleci/ruby:2.7-buster-node |
||||
environment: *ruby_environment |
||||
- image: circleci/postgres:12.2 |
||||
environment: |
||||
POSTGRES_USER: root |
||||
POSTGRES_HOST_AUTH_METHOD: trust |
||||
- image: circleci/redis:5-alpine |
||||
<<: *test_steps |
||||
|
||||
test-ruby2.6: |
||||
<<: *defaults |
||||
docker: |
||||
- image: circleci/ruby:2.6-buster-node |
||||
environment: *ruby_environment |
||||
- image: circleci/postgres:12.2 |
||||
environment: |
||||
POSTGRES_USER: root |
||||
POSTGRES_HOST_AUTH_METHOD: trust |
||||
- image: circleci/redis:5-alpine |
||||
<<: *test_steps |
||||
|
||||
test-ruby3.0: |
||||
<<: *defaults |
||||
docker: |
||||
- image: circleci/ruby:3.0-buster-node |
||||
environment: *ruby_environment |
||||
- image: circleci/postgres:12.2 |
||||
environment: |
||||
POSTGRES_USER: root |
||||
POSTGRES_HOST_AUTH_METHOD: trust |
||||
- image: circleci/redis:5-alpine |
||||
<<: *test_steps |
||||
|
||||
test-webui: |
||||
<<: *defaults |
||||
docker: |
||||
- image: circleci/node:12-buster |
||||
steps: |
||||
- *attach_workspace |
||||
name: Run all remaining migrations |
||||
- run: |
||||
name: Run jest |
||||
command: yarn test:jest |
||||
command: ./bin/rails tests:migrations:check_database |
||||
name: Check migration result |
||||
|
||||
check-i18n: |
||||
<<: *defaults |
||||
test-two-step-migrations: |
||||
executor: |
||||
name: default |
||||
ruby-version: '3.0' |
||||
steps: |
||||
- *attach_workspace |
||||
- *install_system_dependencies |
||||
- checkout |
||||
- install-system-dependencies |
||||
- install-ruby-dependencies: |
||||
ruby-version: '3.0' |
||||
- wait-db |
||||
- run: |
||||
command: ./bin/rails db:create |
||||
name: Create database |
||||
- run: |
||||
command: ./bin/rails db:migrate VERSION=20171010025614 |
||||
name: Run migrations up to v2.0.0 |
||||
- run: |
||||
command: ./bin/rails tests:migrations:populate_v2 |
||||
name: Populate database with test data |
||||
- run: |
||||
name: Check locale file normalization |
||||
command: bundle exec i18n-tasks check-normalized |
||||
command: ./bin/rails db:migrate VERSION=20180514140000 |
||||
name: Run pre-deployment migrations up to v2.4.0 |
||||
environment: |
||||
SKIP_POST_DEPLOYMENT_MIGRATIONS: true |
||||
- run: |
||||
name: Check for unused strings |
||||
command: bundle exec i18n-tasks unused -l en |
||||
command: ./bin/rails tests:migrations:populate_v2_4 |
||||
name: Populate database with test data |
||||
- run: |
||||
name: Check for wrong string interpolations |
||||
command: bundle exec i18n-tasks check-consistent-interpolations |
||||
command: ./bin/rails db:migrate |
||||
name: Run all pre-deployment migrations |
||||
environment: |
||||
SKIP_POST_DEPLOYMENT_MIGRATIONS: true |
||||
- run: |
||||
command: ./bin/rails db:migrate |
||||
name: Run all post-deployment remaining migrations |
||||
- run: |
||||
name: Check that all required locale files exist |
||||
command: bundle exec rake repo:check_locales_files |
||||
command: ./bin/rails tests:migrations:check_database |
||||
name: Check migration result |
||||
|
||||
workflows: |
||||
version: 2 |
||||
build-and-test: |
||||
jobs: |
||||
- install |
||||
- install-ruby2.7: |
||||
requires: |
||||
- install |
||||
- install-ruby2.6: |
||||
requires: |
||||
- install |
||||
- install-ruby2.7 |
||||
- install-ruby3.0: |
||||
- build |
||||
- test: |
||||
matrix: |
||||
parameters: |
||||
ruby-version: |
||||
- '2.7' |
||||
- '3.0' |
||||
name: test-ruby<< matrix.ruby-version >> |
||||
requires: |
||||
- install |
||||
- install-ruby2.7 |
||||
- build: |
||||
requires: |
||||
- install-ruby2.7 |
||||
- build |
||||
- test-migrations: |
||||
requires: |
||||
- install-ruby2.7 |
||||
- test-ruby2.7: |
||||
requires: |
||||
- install-ruby2.7 |
||||
- build |
||||
- test-ruby2.6: |
||||
- test-two-step-migrations: |
||||
requires: |
||||
- install-ruby2.6 |
||||
- build |
||||
- test-ruby3.0: |
||||
- node/run: |
||||
cache-version: v1 |
||||
name: test-webui |
||||
pkg-manager: yarn |
||||
requires: |
||||
- install-ruby3.0 |
||||
- build |
||||
- test-webui: |
||||
requires: |
||||
- install |
||||
- check-i18n: |
||||
requires: |
||||
- install-ruby2.7 |
||||
version: lts |
||||
yarn-run: test:jest |
||||
|
||||
@ -0,0 +1,24 @@
|
||||
# [Choice] Ruby version (use -bullseye variants on local arm64/Apple Silicon): 3, 3.1, 3.0, 2, 2.7, 2.6, 3-bullseye, 3.1-bullseye, 3.0-bullseye, 2-bullseye, 2.7-bullseye, 2.6-bullseye, 3-buster, 3.1-buster, 3.0-buster, 2-buster, 2.7-buster, 2.6-buster |
||||
ARG VARIANT=3.1-bullseye |
||||
FROM mcr.microsoft.com/vscode/devcontainers/ruby:${VARIANT} |
||||
|
||||
# Install Rails |
||||
# RUN gem install rails webdrivers |
||||
|
||||
# Default value to allow debug server to serve content over GitHub Codespace's port forwarding service |
||||
# The value is a comma-separated list of allowed domains |
||||
ENV RAILS_DEVELOPMENT_HOSTS=".githubpreview.dev" |
||||
|
||||
# [Choice] Node.js version: lts/*, 16, 14, 12, 10 |
||||
ARG NODE_VERSION="lts/*" |
||||
RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1" |
||||
|
||||
# [Optional] Uncomment this section to install additional OS packages. |
||||
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ |
||||
&& apt-get -y install --no-install-recommends libicu-dev libidn11-dev ffmpeg imagemagick libpam-dev |
||||
|
||||
# [Optional] Uncomment this line to install additional gems. |
||||
RUN gem install foreman |
||||
|
||||
# [Optional] Uncomment this line to install global node packages. |
||||
RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g yarn" 2>&1 |
||||
@ -0,0 +1,26 @@
|
||||
{ |
||||
"name": "Mastodon", |
||||
"dockerComposeFile": "docker-compose.yml", |
||||
"service": "app", |
||||
"workspaceFolder": "/workspaces/mastodon", |
||||
|
||||
// Set *default* container specific settings.json values on container create. |
||||
"settings": {}, |
||||
|
||||
// Add the IDs of extensions you want installed when the container is created. |
||||
"extensions": [ |
||||
"EditorConfig.EditorConfig", |
||||
"dbaeumer.vscode-eslint", |
||||
"rebornix.Ruby" |
||||
], |
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally. |
||||
// This can be used to network with other containers or the host. |
||||
"forwardPorts": [3000, 4000], |
||||
|
||||
// Use 'postCreateCommand' to run commands after the container is created. |
||||
"postCreateCommand": "bundle install --path vendor/bundle && yarn install && ./bin/rails db:setup", |
||||
|
||||
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. |
||||
"remoteUser": "vscode" |
||||
} |
||||
@ -0,0 +1,83 @@
|
||||
version: '3' |
||||
|
||||
services: |
||||
app: |
||||
build: |
||||
context: . |
||||
dockerfile: Dockerfile |
||||
args: |
||||
# Update 'VARIANT' to pick a version of Ruby: 3, 3.1, 3.0, 2, 2.7, 2.6 |
||||
# Append -bullseye or -buster to pin to an OS version. |
||||
# Use -bullseye variants on local arm64/Apple Silicon. |
||||
VARIANT: '3.0-bullseye' |
||||
# Optional Node.js version to install |
||||
NODE_VERSION: '14' |
||||
volumes: |
||||
- ..:/workspaces/mastodon:cached |
||||
environment: |
||||
RAILS_ENV: development |
||||
NODE_ENV: development |
||||
|
||||
REDIS_HOST: redis |
||||
REDIS_PORT: '6379' |
||||
DB_HOST: db |
||||
DB_USER: postgres |
||||
DB_PASS: postgres |
||||
DB_PORT: '5432' |
||||
ES_ENABLED: 'true' |
||||
ES_HOST: es |
||||
ES_PORT: '9200' |
||||
# Overrides default command so things don't shut down after the process ends. |
||||
command: sleep infinity |
||||
networks: |
||||
- external_network |
||||
- internal_network |
||||
user: vscode |
||||
|
||||
db: |
||||
image: postgres:14-alpine |
||||
restart: unless-stopped |
||||
volumes: |
||||
- postgres-data:/var/lib/postgresql/data |
||||
environment: |
||||
POSTGRES_USER: postgres |
||||
POSTGRES_DB: postgres |
||||
POSTGRES_PASSWORD: postgres |
||||
POSTGRES_HOST_AUTH_METHOD: trust |
||||
networks: |
||||
- internal_network |
||||
|
||||
redis: |
||||
image: redis:6-alpine |
||||
restart: unless-stopped |
||||
volumes: |
||||
- redis-data:/data |
||||
networks: |
||||
- internal_network |
||||
|
||||
es: |
||||
image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.10.2 |
||||
restart: unless-stopped |
||||
environment: |
||||
ES_JAVA_OPTS: -Xms512m -Xmx512m |
||||
cluster.name: es-mastodon |
||||
discovery.type: single-node |
||||
bootstrap.memory_lock: 'true' |
||||
volumes: |
||||
- es-data:/usr/share/elasticsearch/data |
||||
networks: |
||||
- internal_network |
||||
ulimits: |
||||
memlock: |
||||
soft: -1 |
||||
hard: -1 |
||||
|
||||
volumes: |
||||
postgres-data: |
||||
redis-data: |
||||
es-data: |
||||
|
||||
networks: |
||||
external_network: |
||||
internal_network: |
||||
internal: true |
||||
@ -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 |
||||
@ -1,3 +1,3 @@
|
||||
patreon: mastodon |
||||
open_collective: mastodon |
||||
github: [Gargron] |
||||
custom: https://sponsor.joinmastodon.org |
||||
|
||||
@ -0,0 +1,42 @@
|
||||
name: Bug Report |
||||
description: If something isn't working as expected |
||||
labels: bug |
||||
body: |
||||
- type: markdown |
||||
attributes: |
||||
value: | |
||||
Make sure that you are submitting a new bug that was not previously reported or already fixed. |
||||
|
||||
Please use a concise and distinct title for the issue. |
||||
- type: textarea |
||||
attributes: |
||||
label: Steps to reproduce the problem |
||||
description: What were you trying to do? |
||||
value: | |
||||
1. |
||||
2. |
||||
3. |
||||
... |
||||
validations: |
||||
required: true |
||||
- type: input |
||||
attributes: |
||||
label: Expected behaviour |
||||
description: What should have happened? |
||||
validations: |
||||
required: true |
||||
- type: input |
||||
attributes: |
||||
label: Actual behaviour |
||||
description: What happened? |
||||
validations: |
||||
required: true |
||||
- type: textarea |
||||
attributes: |
||||
label: Specifications |
||||
description: | |
||||
What version or commit hash of Mastodon did you find this bug in? |
||||
|
||||
If a front-end issue, what browser and operating systems were you using? |
||||
validations: |
||||
required: true |
||||
@ -0,0 +1,22 @@
|
||||
name: Feature Request |
||||
description: I have a suggestion |
||||
labels: suggestion |
||||
body: |
||||
- type: markdown |
||||
attributes: |
||||
value: | |
||||
Please use a concise and distinct title for the issue. |
||||
|
||||
Consider: Could it be implemented as a 3rd party app using the REST API instead? |
||||
- type: textarea |
||||
attributes: |
||||
label: Pitch |
||||
description: Describe your idea for a feature. Make sure it has not already been suggested/implemented/turned down before. |
||||
validations: |
||||
required: true |
||||
- type: textarea |
||||
attributes: |
||||
label: Motivation |
||||
description: Why do you think this feature is needed? Who would benefit from it? |
||||
validations: |
||||
required: true |
||||
@ -1,27 +0,0 @@
|
||||
--- |
||||
name: Bug Report |
||||
about: If something isn't working as expected |
||||
labels: bug |
||||
--- |
||||
|
||||
<!-- Make sure that you are submitting a new bug that was not previously reported or already fixed --> |
||||
|
||||
<!-- Please use a concise and distinct title for the issue --> |
||||
|
||||
### Expected behaviour |
||||
|
||||
<!-- What should have happened? --> |
||||
|
||||
### Actual behaviour |
||||
|
||||
<!-- What happened? --> |
||||
|
||||
### Steps to reproduce the problem |
||||
|
||||
<!-- What were you trying to do? --> |
||||
|
||||
### Specifications |
||||
|
||||
<!-- What version or commit hash of Mastodon did you find this bug in? --> |
||||
|
||||
<!-- If a front-end issue, what browser and operating systems were you using? --> |
||||
@ -1,5 +1,8 @@
|
||||
blank_issues_enabled: false |
||||
contact_links: |
||||
- name: Mastodon Meta Discussion Board |
||||
url: https://discourse.joinmastodon.org/ |
||||
- name: GitHub Discussions |
||||
url: https://github.com/mastodon/mastodon/discussions |
||||
about: Please ask and answer questions here. |
||||
- name: Bug Bounty Program |
||||
url: https://app.intigriti.com/programs/mastodon/mastodonio/detail |
||||
about: Please report security vulnerabilities here. |
||||
|
||||
@ -1,16 +0,0 @@
|
||||
--- |
||||
name: Feature Request |
||||
about: I have a suggestion |
||||
--- |
||||
|
||||
<!-- Please use a concise and distinct title for the issue --> |
||||
|
||||
<!-- Consider: Could it be implemented as a 3rd party app using the REST API instead? --> |
||||
|
||||
### Pitch |
||||
|
||||
<!-- Describe your idea for a feature. Make sure it has not already been suggested/implemented/turned down before --> |
||||
|
||||
### Motivation |
||||
|
||||
<!-- Why do you think this feature is needed? Who would benefit from it? --> |
||||
@ -1,10 +0,0 @@
|
||||
--- |
||||
name: Support |
||||
about: Ask for help with your deployment |
||||
|
||||
--- |
||||
|
||||
We primarily use GitHub as a bug and feature tracker. For usage questions, troubleshooting of deployments and other individual technical assistance, please use one of the resources below: |
||||
|
||||
- https://discourse.joinmastodon.org |
||||
- #mastodon on irc.freenode.net |
||||
@ -0,0 +1,42 @@
|
||||
name: Build container image |
||||
on: |
||||
workflow_dispatch: |
||||
push: |
||||
branches: |
||||
- 'main' |
||||
tags: |
||||
- '*' |
||||
pull_request: |
||||
paths: |
||||
- .github/workflows/build-image.yml |
||||
- Dockerfile |
||||
jobs: |
||||
build-image: |
||||
runs-on: ubuntu-latest |
||||
steps: |
||||
- uses: actions/checkout@v2 |
||||
- uses: docker/setup-qemu-action@v1 |
||||
- uses: docker/setup-buildx-action@v1 |
||||
- uses: docker/login-action@v1 |
||||
with: |
||||
username: ${{ secrets.DOCKERHUB_USERNAME }} |
||||
password: ${{ secrets.DOCKERHUB_TOKEN }} |
||||
if: github.event_name != 'pull_request' |
||||
- uses: docker/metadata-action@v3 |
||||
id: meta |
||||
with: |
||||
images: tootsuite/mastodon |
||||
flavor: | |
||||
latest=auto |
||||
tags: | |
||||
type=edge,branch=main |
||||
type=match,pattern=v(.*),group=0 |
||||
type=ref,event=pr |
||||
- uses: docker/build-push-action@v2 |
||||
with: |
||||
context: . |
||||
platforms: linux/amd64,linux/arm64 |
||||
push: ${{ github.event_name != 'pull_request' }} |
||||
tags: ${{ steps.meta.outputs.tags }} |
||||
cache-from: type=registry,ref=tootsuite/mastodon:latest |
||||
cache-to: type=inline |
||||
@ -0,0 +1,34 @@
|
||||
name: Check i18n |
||||
|
||||
on: |
||||
push: |
||||
branches: [main] |
||||
pull_request: |
||||
branches: [main] |
||||
|
||||
env: |
||||
RAILS_ENV: test |
||||
|
||||
jobs: |
||||
check-i18n: |
||||
runs-on: ubuntu-latest |
||||
|
||||
steps: |
||||
- uses: actions/checkout@v2 |
||||
- name: Install system dependencies |
||||
run: | |
||||
sudo apt-get update |
||||
sudo apt-get install -y libicu-dev libidn11-dev |
||||
- name: Set up Ruby |
||||
uses: ruby/setup-ruby@v1 |
||||
with: |
||||
ruby-version: '3.0' |
||||
bundler-cache: true |
||||
- name: Check locale file normalization |
||||
run: bundle exec i18n-tasks check-normalized |
||||
- name: Check for unused strings |
||||
run: bundle exec i18n-tasks unused -l en |
||||
- name: Check for wrong string interpolations |
||||
run: bundle exec i18n-tasks check-consistent-interpolations |
||||
- name: Check that all required locale files exist |
||||
run: bundle exec rake repo:check_locales_files |
||||
@ -0,0 +1,78 @@
|
||||
# See https://help.github.com/articles/ignoring-files for more about ignoring files. |
||||
# |
||||
# If you find yourself ignoring temporary files generated by your text editor |
||||
# or operating system, you probably want to add a global ignore instead: |
||||
# git config --global core.excludesfile '~/.gitignore_global' |
||||
|
||||
# Ignore bundler config and downloaded libraries. |
||||
/.bundle |
||||
/vendor/bundle |
||||
|
||||
# Ignore the default SQLite database. |
||||
/db/*.sqlite3 |
||||
/db/*.sqlite3-journal |
||||
|
||||
# Ignore all logfiles and tempfiles. |
||||
.eslintcache |
||||
/log/* |
||||
!/log/.keep |
||||
/tmp |
||||
/coverage |
||||
/public/system |
||||
/public/assets |
||||
/public/packs |
||||
/public/packs-test |
||||
.env |
||||
.env.production |
||||
.env.development |
||||
/node_modules/ |
||||
/build/ |
||||
|
||||
# Ignore Vagrant files |
||||
.vagrant/ |
||||
|
||||
# Ignore Capistrano customizations |
||||
/config/deploy/* |
||||
|
||||
# Ignore IDE files |
||||
.vscode/ |
||||
.idea/ |
||||
|
||||
# Ignore postgres + redis + elasticsearch volume optionally created by docker-compose |
||||
/postgres |
||||
/postgres14 |
||||
/redis |
||||
/elasticsearch |
||||
|
||||
# ignore Helm dependency charts |
||||
/chart/charts/*.tgz |
||||
|
||||
# Ignore Apple files |
||||
.DS_Store |
||||
|
||||
# Ignore vim files |
||||
*~ |
||||
*.swp |
||||
|
||||
# Ignore npm debug log |
||||
npm-debug.log |
||||
|
||||
# Ignore yarn log files |
||||
yarn-error.log |
||||
yarn-debug.log |
||||
|
||||
# Ignore vagrant log files |
||||
*-cloudimg-console.log |
||||
|
||||
# Ignore Docker option files |
||||
docker-compose.override.yml |
||||
|
||||
# Ignore Helm files |
||||
/chart |
||||
|
||||
# Ignore emoji map file |
||||
/app/javascript/mastodon/features/emoji/emoji_map.json |
||||
|
||||
# Ignore locale files |
||||
/app/javascript/mastodon/locales |
||||
/config/locales |
||||
@ -0,0 +1,30 @@
|
||||
## ActivityPub federation in Mastodon |
||||
|
||||
Mastodon largely follows the ActivityPub server-to-server specification but it makes uses of some non-standard extensions, some of which are required for interacting with Mastodon at all. |
||||
|
||||
Supported vocabulary: https://docs.joinmastodon.org/spec/activitypub/ |
||||
|
||||
### Required extensions |
||||
|
||||
#### Webfinger |
||||
|
||||
In Mastodon, users are identified by a `username` and `domain` pair (e.g., `Gargron@mastodon.social`). |
||||
This is used both for discovery and for unambiguously mentioning users across the fediverse. Furthermore, this is part of Mastodon's database design from its very beginnings. |
||||
|
||||
As a result, Mastodon requires that each ActivityPub actor uniquely maps back to an `acct:` URI that can be resolved via WebFinger. |
||||
|
||||
More information and examples are available at: https://docs.joinmastodon.org/spec/webfinger/ |
||||
|
||||
#### HTTP Signatures |
||||
|
||||
In order to authenticate activities, Mastodon relies on HTTP Signatures, signing every `POST` and `GET` request to other ActivityPub implementations on behalf of the user authoring an activity (for `POST` requests) or an actor representing the Mastodon server itself (for most `GET` requests). |
||||
|
||||
Mastodon requires all `POST` requests to be signed, and MAY require `GET` requests to be signed, depending on the configuration of the Mastodon server. |
||||
|
||||
More information on HTTP Signatures, as well as examples, can be found here: https://docs.joinmastodon.org/spec/security/#http |
||||
|
||||
### Optional extensions |
||||
|
||||
- Linked-Data Signatures: https://docs.joinmastodon.org/spec/security/#ld |
||||
- Bearcaps: https://docs.joinmastodon.org/spec/bearcaps/ |
||||
- Followers collection synchronization: https://git.activitypub.dev/ActivityPubDev/Fediverse-Enhancement-Proposals/src/branch/main/feps/fep-8fcf.md |
||||
@ -1,13 +1,19 @@
|
||||
# Security Policy |
||||
|
||||
If you believe you've identified a security vulnerability in Mastodon (a bug that allows something to happen that shouldn't be possible), you should submit the report through our [Bug Bounty Program][bug-bounty]. Alternatively, you can reach us at <hello@joinmastodon.org>. |
||||
|
||||
You should *not* report such issues on GitHub or in other public spaces to give us time to publish a fix for the issue without exposing Mastodon's users to increased risk. |
||||
|
||||
## Scope |
||||
|
||||
A "vulnerability in Mastodon" is a vulnerability in the code distributed through our main source code repository on GitHub. Vulnerabilities that are specific to a given installation (e.g. misconfiguration) should be reported to the owner of that installation and not us. |
||||
|
||||
## Supported Versions |
||||
|
||||
| Version | Supported | |
||||
| ------- | ------------------ | |
||||
| 3.4.x | :white_check_mark: | |
||||
| 3.3.x | :white_check_mark: | |
||||
| < 3.3 | :x: | |
||||
|
||||
## Reporting a Vulnerability |
||||
| 3.4.x | Yes | |
||||
| 3.3.x | Yes | |
||||
| < 3.3 | No | |
||||
|
||||
hello@joinmastodon.org |
||||
[bug-bounty]: https://app.intigriti.com/programs/mastodon/mastodonio/detail |
||||
|
||||
@ -0,0 +1,40 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
class Admin::Disputes::AppealsController < Admin::BaseController |
||||
before_action :set_appeal, except: :index |
||||
|
||||
def index |
||||
authorize :appeal, :index? |
||||
|
||||
@appeals = filtered_appeals.page(params[:page]) |
||||
end |
||||
|
||||
def approve |
||||
authorize @appeal, :approve? |
||||
log_action :approve, @appeal |
||||
ApproveAppealService.new.call(@appeal, current_account) |
||||
redirect_to disputes_strike_path(@appeal.strike) |
||||
end |
||||
|
||||
def reject |
||||
authorize @appeal, :approve? |
||||
log_action :reject, @appeal |
||||
@appeal.reject!(current_account) |
||||
UserMailer.appeal_rejected(@appeal.account.user, @appeal) |
||||
redirect_to disputes_strike_path(@appeal.strike) |
||||
end |
||||
|
||||
private |
||||
|
||||
def filtered_appeals |
||||
Admin::AppealFilter.new(filter_params.with_defaults(status: 'pending')).results.includes(strike: :account) |
||||
end |
||||
|
||||
def filter_params |
||||
params.slice(:page, *Admin::AppealFilter::KEYS).permit(:page, *Admin::AppealFilter::KEYS) |
||||
end |
||||
|
||||
def set_appeal |
||||
@appeal = Appeal.find(params[:id]) |
||||
end |
||||
end |
||||
@ -1,52 +0,0 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
module Admin |
||||
class PendingAccountsController < BaseController |
||||
before_action :set_accounts, only: :index |
||||
|
||||
def index |
||||
@form = Form::AccountBatch.new |
||||
end |
||||
|
||||
def batch |
||||
@form = Form::AccountBatch.new(form_account_batch_params.merge(current_account: current_account, action: action_from_button)) |
||||
@form.save |
||||
rescue ActionController::ParameterMissing |
||||
flash[:alert] = I18n.t('admin.accounts.no_account_selected') |
||||
ensure |
||||
redirect_to admin_pending_accounts_path(current_params) |
||||
end |
||||
|
||||
def approve_all |
||||
Form::AccountBatch.new(current_account: current_account, account_ids: User.pending.pluck(:account_id), action: 'approve').save |
||||
redirect_to admin_pending_accounts_path(current_params) |
||||
end |
||||
|
||||
def reject_all |
||||
Form::AccountBatch.new(current_account: current_account, account_ids: User.pending.pluck(:account_id), action: 'reject').save |
||||
redirect_to admin_pending_accounts_path(current_params) |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_accounts |
||||
@accounts = Account.joins(:user).merge(User.pending.recent).includes(user: :invite_request).page(params[:page]) |
||||
end |
||||
|
||||
def form_account_batch_params |
||||
params.require(:form_account_batch).permit(:action, account_ids: []) |
||||
end |
||||
|
||||
def action_from_button |
||||
if params[:approve] |
||||
'approve' |
||||
elsif params[:reject] |
||||
'reject' |
||||
end |
||||
end |
||||
|
||||
def current_params |
||||
params.slice(:page).permit(:page) |
||||
end |
||||
end |
||||
end |
||||
@ -1,44 +0,0 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
module Admin |
||||
class ReportedStatusesController < BaseController |
||||
before_action :set_report |
||||
|
||||
def create |
||||
authorize :status, :update? |
||||
|
||||
@form = Form::StatusBatch.new(form_status_batch_params.merge(current_account: current_account, action: action_from_button)) |
||||
flash[:alert] = I18n.t('admin.statuses.failed_to_execute') unless @form.save |
||||
|
||||
redirect_to admin_report_path(@report) |
||||
rescue ActionController::ParameterMissing |
||||
flash[:alert] = I18n.t('admin.statuses.no_status_selected') |
||||
|
||||
redirect_to admin_report_path(@report) |
||||
end |
||||
|
||||
private |
||||
|
||||
def status_params |
||||
params.require(:status).permit(:sensitive) |
||||
end |
||||
|
||||
def form_status_batch_params |
||||
params.require(:form_status_batch).permit(status_ids: []) |
||||
end |
||||
|
||||
def action_from_button |
||||
if params[:nsfw_on] |
||||
'nsfw_on' |
||||
elsif params[:nsfw_off] |
||||
'nsfw_off' |
||||
elsif params[:delete] |
||||
'delete' |
||||
end |
||||
end |
||||
|
||||
def set_report |
||||
@report = Report.find(params[:report_id]) |
||||
end |
||||
end |
||||
end |
||||
@ -0,0 +1,52 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
class Admin::Reports::ActionsController < Admin::BaseController |
||||
before_action :set_report |
||||
|
||||
def create |
||||
authorize @report, :show? |
||||
|
||||
case action_from_button |
||||
when 'delete', 'mark_as_sensitive' |
||||
status_batch_action = Admin::StatusBatchAction.new( |
||||
type: action_from_button, |
||||
status_ids: @report.status_ids, |
||||
current_account: current_account, |
||||
report_id: @report.id, |
||||
send_email_notification: !@report.spam? |
||||
) |
||||
|
||||
status_batch_action.save! |
||||
when 'silence', 'suspend' |
||||
account_action = Admin::AccountAction.new( |
||||
type: action_from_button, |
||||
report_id: @report.id, |
||||
target_account: @report.target_account, |
||||
current_account: current_account, |
||||
send_email_notification: !@report.spam? |
||||
) |
||||
|
||||
account_action.save! |
||||
end |
||||
|
||||
redirect_to admin_reports_path |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_report |
||||
@report = Report.find(params[:report_id]) |
||||
end |
||||
|
||||
def action_from_button |
||||
if params[:delete] |
||||
'delete' |
||||
elsif params[:mark_as_sensitive] |
||||
'mark_as_sensitive' |
||||
elsif params[:silence] |
||||
'silence' |
||||
elsif params[:suspend] |
||||
'suspend' |
||||
end |
||||
end |
||||
end |
||||
@ -0,0 +1,27 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
module Admin |
||||
class SignInTokenAuthenticationsController < BaseController |
||||
before_action :set_target_user |
||||
|
||||
def create |
||||
authorize @user, :enable_sign_in_token_auth? |
||||
@user.update(skip_sign_in_token: false) |
||||
log_action :enable_sign_in_token_auth, @user |
||||
redirect_to admin_account_path(@user.account_id) |
||||
end |
||||
|
||||
def destroy |
||||
authorize @user, :disable_sign_in_token_auth? |
||||
@user.update(skip_sign_in_token: true) |
||||
log_action :disable_sign_in_token_auth, @user |
||||
redirect_to admin_account_path(@user.account_id) |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_target_user |
||||
@user = User.find(params[:user_id]) |
||||
end |
||||
end |
||||
end |
||||
@ -0,0 +1,41 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
class Admin::Trends::Links::PreviewCardProvidersController < Admin::BaseController |
||||
def index |
||||
authorize :preview_card_provider, :index? |
||||
|
||||
@preview_card_providers = filtered_preview_card_providers.page(params[:page]) |
||||
@form = Trends::PreviewCardProviderBatch.new |
||||
end |
||||
|
||||
def batch |
||||
@form = Trends::PreviewCardProviderBatch.new(trends_preview_card_provider_batch_params.merge(current_account: current_account, action: action_from_button)) |
||||
@form.save |
||||
rescue ActionController::ParameterMissing |
||||
flash[:alert] = I18n.t('admin.accounts.no_account_selected') |
||||
ensure |
||||
redirect_to admin_trends_links_preview_card_providers_path(filter_params) |
||||
end |
||||
|
||||
private |
||||
|
||||
def filtered_preview_card_providers |
||||
Trends::PreviewCardProviderFilter.new(filter_params).results |
||||
end |
||||
|
||||
def filter_params |
||||
params.slice(:page, *Trends::PreviewCardProviderFilter::KEYS).permit(:page, *Trends::PreviewCardProviderFilter::KEYS) |
||||
end |
||||
|
||||
def trends_preview_card_provider_batch_params |
||||
params.require(:trends_preview_card_provider_batch).permit(:action, preview_card_provider_ids: []) |
||||
end |
||||
|
||||
def action_from_button |
||||
if params[:approve] |
||||
'approve' |
||||
elsif params[:reject] |
||||
'reject' |
||||
end |
||||
end |
||||
end |
||||
@ -0,0 +1,45 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
class Admin::Trends::LinksController < Admin::BaseController |
||||
def index |
||||
authorize :preview_card, :index? |
||||
|
||||
@preview_cards = filtered_preview_cards.page(params[:page]) |
||||
@form = Trends::PreviewCardBatch.new |
||||
end |
||||
|
||||
def batch |
||||
@form = Trends::PreviewCardBatch.new(trends_preview_card_batch_params.merge(current_account: current_account, action: action_from_button)) |
||||
@form.save |
||||
rescue ActionController::ParameterMissing |
||||
flash[:alert] = I18n.t('admin.accounts.no_account_selected') |
||||
ensure |
||||
redirect_to admin_trends_links_path(filter_params) |
||||
end |
||||
|
||||
private |
||||
|
||||
def filtered_preview_cards |
||||
Trends::PreviewCardFilter.new(filter_params.with_defaults(trending: 'all')).results |
||||
end |
||||
|
||||
def filter_params |
||||
params.slice(:page, *Trends::PreviewCardFilter::KEYS).permit(:page, *Trends::PreviewCardFilter::KEYS) |
||||
end |
||||
|
||||
def trends_preview_card_batch_params |
||||
params.require(:trends_preview_card_batch).permit(:action, preview_card_ids: []) |
||||
end |
||||
|
||||
def action_from_button |
||||
if params[:approve] |
||||
'approve' |
||||
elsif params[:approve_providers] |
||||
'approve_providers' |
||||
elsif params[:reject] |
||||
'reject' |
||||
elsif params[:reject_providers] |
||||
'reject_providers' |
||||
end |
||||
end |
||||
end |
||||
@ -0,0 +1,45 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
class Admin::Trends::StatusesController < Admin::BaseController |
||||
def index |
||||
authorize :status, :index? |
||||
|
||||
@statuses = filtered_statuses.page(params[:page]) |
||||
@form = Trends::StatusBatch.new |
||||
end |
||||
|
||||
def batch |
||||
@form = Trends::StatusBatch.new(trends_status_batch_params.merge(current_account: current_account, action: action_from_button)) |
||||
@form.save |
||||
rescue ActionController::ParameterMissing |
||||
flash[:alert] = I18n.t('admin.accounts.no_account_selected') |
||||
ensure |
||||
redirect_to admin_trends_statuses_path(filter_params) |
||||
end |
||||
|
||||
private |
||||
|
||||
def filtered_statuses |
||||
Trends::StatusFilter.new(filter_params.with_defaults(trending: 'all')).results.includes(:account, :media_attachments, :active_mentions) |
||||
end |
||||
|
||||
def filter_params |
||||
params.slice(:page, *Trends::StatusFilter::KEYS).permit(:page, *Trends::StatusFilter::KEYS) |
||||
end |
||||
|
||||
def trends_status_batch_params |
||||
params.require(:trends_status_batch).permit(:action, status_ids: []) |
||||
end |
||||
|
||||
def action_from_button |
||||
if params[:approve] |
||||
'approve' |
||||
elsif params[:approve_accounts] |
||||
'approve_accounts' |
||||
elsif params[:reject] |
||||
'reject' |
||||
elsif params[:reject_accounts] |
||||
'reject_accounts' |
||||
end |
||||
end |
||||
end |
||||
@ -0,0 +1,41 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
class Admin::Trends::TagsController < Admin::BaseController |
||||
def index |
||||
authorize :tag, :index? |
||||
|
||||
@tags = filtered_tags.page(params[:page]) |
||||
@form = Trends::TagBatch.new |
||||
end |
||||
|
||||
def batch |
||||
@form = Trends::TagBatch.new(trends_tag_batch_params.merge(current_account: current_account, action: action_from_button)) |
||||
@form.save |
||||
rescue ActionController::ParameterMissing |
||||
flash[:alert] = I18n.t('admin.accounts.no_account_selected') |
||||
ensure |
||||
redirect_to admin_trends_tags_path(filter_params) |
||||
end |
||||
|
||||
private |
||||
|
||||
def filtered_tags |
||||
Trends::TagFilter.new(filter_params).results |
||||
end |
||||
|
||||
def filter_params |
||||
params.slice(:page, *Trends::TagFilter::KEYS).permit(:page, *Trends::TagFilter::KEYS) |
||||
end |
||||
|
||||
def trends_tag_batch_params |
||||
params.require(:trends_tag_batch).permit(:action, tag_ids: []) |
||||
end |
||||
|
||||
def action_from_button |
||||
if params[:approve] |
||||
'approve' |
||||
elsif params[:reject] |
||||
'reject' |
||||
end |
||||
end |
||||
end |
||||
@ -1,23 +0,0 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
class Api::ProofsController < Api::BaseController |
||||
include AccountOwnedConcern |
||||
|
||||
skip_before_action :require_authenticated_user! |
||||
|
||||
before_action :set_provider |
||||
|
||||
def index |
||||
render json: @account, serializer: @provider.serializer_class |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_provider |
||||
@provider = ProofProvider.find(params[:provider]) || raise(ActiveRecord::RecordNotFound) |
||||
end |
||||
|
||||
def username_param |
||||
params[:username] |
||||
end |
||||
end |
||||
@ -0,0 +1,25 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
class Api::V1::Accounts::FamiliarFollowersController < Api::BaseController |
||||
before_action -> { doorkeeper_authorize! :read, :'read:follows' } |
||||
before_action :require_user! |
||||
before_action :set_accounts |
||||
|
||||
def index |
||||
render json: familiar_followers.accounts, each_serializer: REST::FamiliarFollowersSerializer |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_accounts |
||||
@accounts = Account.without_suspended.where(id: account_ids).select('id, hide_collections').index_by(&:id).values_at(*account_ids).compact |
||||
end |
||||
|
||||
def familiar_followers |
||||
FamiliarFollowersPresenter.new(@accounts, current_user.account_id) |
||||
end |
||||
|
||||
def account_ids |
||||
Array(params[:id]).map(&:to_i) |
||||
end |
||||
end |
||||
@ -0,0 +1,25 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
class Api::V1::Admin::DimensionsController < Api::BaseController |
||||
protect_from_forgery with: :exception |
||||
|
||||
before_action -> { authorize_if_got_token! :'admin:read' } |
||||
before_action :require_staff! |
||||
before_action :set_dimensions |
||||
|
||||
def create |
||||
render json: @dimensions, each_serializer: REST::Admin::DimensionSerializer |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_dimensions |
||||
@dimensions = Admin::Metrics::Dimension.retrieve( |
||||
params[:keys], |
||||
params[:start_at], |
||||
params[:end_at], |
||||
params[:limit], |
||||
params |
||||
) |
||||
end |
||||
end |
||||
@ -0,0 +1,24 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
class Api::V1::Admin::MeasuresController < Api::BaseController |
||||
protect_from_forgery with: :exception |
||||
|
||||
before_action -> { authorize_if_got_token! :'admin:read' } |
||||
before_action :require_staff! |
||||
before_action :set_measures |
||||
|
||||
def create |
||||
render json: @measures, each_serializer: REST::Admin::MeasureSerializer |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_measures |
||||
@measures = Admin::Metrics::Measure.retrieve( |
||||
params[:keys], |
||||
params[:start_at], |
||||
params[:end_at], |
||||
params |
||||
) |
||||
end |
||||
end |
||||
@ -0,0 +1,23 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
class Api::V1::Admin::RetentionController < Api::BaseController |
||||
protect_from_forgery with: :exception |
||||
|
||||
before_action -> { authorize_if_got_token! :'admin:read' } |
||||
before_action :require_staff! |
||||
before_action :set_cohorts |
||||
|
||||
def create |
||||
render json: @cohorts, each_serializer: REST::Admin::CohortSerializer |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_cohorts |
||||
@cohorts = Admin::Metrics::Retention.new( |
||||
params[:start_at], |
||||
params[:end_at], |
||||
params[:frequency] |
||||
).cohorts |
||||
end |
||||
end |
||||
@ -0,0 +1,19 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
class Api::V1::Admin::Trends::LinksController < Api::BaseController |
||||
protect_from_forgery with: :exception |
||||
|
||||
before_action -> { authorize_if_got_token! :'admin:read' } |
||||
before_action :require_staff! |
||||
before_action :set_links |
||||
|
||||
def index |
||||
render json: @links, each_serializer: REST::Trends::LinkSerializer |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_links |
||||
@links = Trends.links.query.limit(limit_param(10)) |
||||
end |
||||
end |
||||
@ -0,0 +1,19 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
class Api::V1::Admin::Trends::StatusesController < Api::BaseController |
||||
protect_from_forgery with: :exception |
||||
|
||||
before_action -> { authorize_if_got_token! :'admin:read' } |
||||
before_action :require_staff! |
||||
before_action :set_statuses |
||||
|
||||
def index |
||||
render json: @statuses, each_serializer: REST::StatusSerializer |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_statuses |
||||
@statuses = cache_collection(Trends.statuses.query.limit(limit_param(DEFAULT_STATUSES_LIMIT)), Status) |
||||
end |
||||
end |
||||
@ -0,0 +1,19 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
class Api::V1::Admin::Trends::TagsController < Api::BaseController |
||||
protect_from_forgery with: :exception |
||||
|
||||
before_action -> { authorize_if_got_token! :'admin:read' } |
||||
before_action :require_staff! |
||||
before_action :set_tags |
||||
|
||||
def index |
||||
render json: @tags, each_serializer: REST::Admin::TagSerializer |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_tags |
||||
@tags = Trends.tags.query.limit(limit_param(10)) |
||||
end |
||||
end |
||||
@ -0,0 +1,21 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
class Api::V1::Statuses::HistoriesController < Api::BaseController |
||||
include Authorization |
||||
|
||||
before_action -> { authorize_if_got_token! :read, :'read:statuses' } |
||||
before_action :set_status |
||||
|
||||
def show |
||||
render json: @status.edits.includes(:account, status: [:account]), each_serializer: REST::StatusEditSerializer |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_status |
||||
@status = Status.find(params[:status_id]) |
||||
authorize @status, :show? |
||||
rescue Mastodon::NotPermittedError |
||||
not_found |
||||
end |
||||
end |
||||
@ -0,0 +1,21 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
class Api::V1::Statuses::SourcesController < Api::BaseController |
||||
include Authorization |
||||
|
||||
before_action -> { doorkeeper_authorize! :read, :'read:statuses' } |
||||
before_action :set_status |
||||
|
||||
def show |
||||
render json: @status, serializer: REST::StatusSourceSerializer |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_status |
||||
@status = Status.find(params[:status_id]) |
||||
authorize @status, :show? |
||||
rescue Mastodon::NotPermittedError |
||||
not_found |
||||
end |
||||
end |
||||
@ -0,0 +1,49 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
class Api::V1::Trends::LinksController < Api::BaseController |
||||
before_action :set_links |
||||
|
||||
after_action :insert_pagination_headers |
||||
|
||||
DEFAULT_LINKS_LIMIT = 10 |
||||
|
||||
def index |
||||
render json: @links, each_serializer: REST::Trends::LinkSerializer |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_links |
||||
@links = begin |
||||
if Setting.trends |
||||
links_from_trends |
||||
else |
||||
[] |
||||
end |
||||
end |
||||
end |
||||
|
||||
def links_from_trends |
||||
Trends.links.query.allowed.in_locale(content_locale).offset(offset_param).limit(limit_param(DEFAULT_LINKS_LIMIT)) |
||||
end |
||||
|
||||
def insert_pagination_headers |
||||
set_pagination_headers(next_path, prev_path) |
||||
end |
||||
|
||||
def pagination_params(core_params) |
||||
params.slice(:limit).permit(:limit).merge(core_params) |
||||
end |
||||
|
||||
def next_path |
||||
api_v1_trends_links_url pagination_params(offset: offset_param + limit_param(DEFAULT_LINKS_LIMIT)) |
||||
end |
||||
|
||||
def prev_path |
||||
api_v1_trends_links_url pagination_params(offset: offset_param - limit_param(DEFAULT_LINKS_LIMIT)) if offset_param > limit_param(DEFAULT_LINKS_LIMIT) |
||||
end |
||||
|
||||
def offset_param |
||||
params[:offset].to_i |
||||
end |
||||
end |
||||
@ -0,0 +1,49 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
class Api::V1::Trends::StatusesController < Api::BaseController |
||||
before_action :set_statuses |
||||
|
||||
after_action :insert_pagination_headers |
||||
|
||||
def index |
||||
render json: @statuses, each_serializer: REST::StatusSerializer |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_statuses |
||||
@statuses = begin |
||||
if Setting.trends |
||||
cache_collection(statuses_from_trends, Status) |
||||
else |
||||
[] |
||||
end |
||||
end |
||||
end |
||||
|
||||
def statuses_from_trends |
||||
scope = Trends.statuses.query.allowed.in_locale(content_locale) |
||||
scope = scope.filtered_for(current_account) if user_signed_in? |
||||
scope.offset(offset_param).limit(limit_param(DEFAULT_STATUSES_LIMIT)) |
||||
end |
||||
|
||||
def insert_pagination_headers |
||||
set_pagination_headers(next_path, prev_path) |
||||
end |
||||
|
||||
def pagination_params(core_params) |
||||
params.slice(:limit).permit(:limit).merge(core_params) |
||||
end |
||||
|
||||
def next_path |
||||
api_v1_trends_statuses_url pagination_params(offset: offset_param + limit_param(DEFAULT_STATUSES_LIMIT)) |
||||
end |
||||
|
||||
def prev_path |
||||
api_v1_trends_statuses_url pagination_params(offset: offset_param - limit_param(DEFAULT_STATUSES_LIMIT)) if offset_param > limit_param(DEFAULT_STATUSES_LIMIT) |
||||
end |
||||
|
||||
def offset_param |
||||
params[:offset].to_i |
||||
end |
||||
end |
||||
@ -0,0 +1,45 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
class Api::V1::Trends::TagsController < Api::BaseController |
||||
before_action :set_tags |
||||
|
||||
after_action :insert_pagination_headers |
||||
|
||||
DEFAULT_TAGS_LIMIT = 10 |
||||
|
||||
def index |
||||
render json: @tags, each_serializer: REST::TagSerializer |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_tags |
||||
@tags = begin |
||||
if Setting.trends |
||||
Trends.tags.query.allowed.limit(limit_param(DEFAULT_TAGS_LIMIT)) |
||||
else |
||||
[] |
||||
end |
||||
end |
||||
end |
||||
|
||||
def insert_pagination_headers |
||||
set_pagination_headers(next_path, prev_path) |
||||
end |
||||
|
||||
def pagination_params(core_params) |
||||
params.slice(:limit).permit(:limit).merge(core_params) |
||||
end |
||||
|
||||
def next_path |
||||
api_v1_trends_tags_url pagination_params(offset: offset_param + limit_param(DEFAULT_TAGS_LIMIT)) |
||||
end |
||||
|
||||
def prev_path |
||||
api_v1_trends_tags_url pagination_params(offset: offset_param - limit_param(DEFAULT_TAGS_LIMIT)) if offset_param > limit_param(DEFAULT_TAGS_LIMIT) |
||||
end |
||||
|
||||
def offset_param |
||||
params[:offset].to_i |
||||
end |
||||
end |
||||
@ -1,15 +0,0 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
class Api::V1::TrendsController < Api::BaseController |
||||
before_action :set_tags |
||||
|
||||
def index |
||||
render json: @tags, each_serializer: REST::TagSerializer |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_tags |
||||
@tags = TrendingTags.get(limit_param(10)) |
||||
end |
||||
end |
||||
@ -0,0 +1,31 @@
|
||||
# frozen_string_literal: true |
||||
|
||||
class Api::V2::Admin::AccountsController < Api::V1::Admin::AccountsController |
||||
FILTER_PARAMS = %i( |
||||
origin |
||||
status |
||||
permissions |
||||
username |
||||
by_domain |
||||
display_name |
||||
email |
||||
ip |
||||
invited_by |
||||
).freeze |
||||
|
||||
PAGINATION_PARAMS = (%i(limit) + FILTER_PARAMS).freeze |
||||
|
||||
private |
||||
|
||||
def filtered_accounts |
||||
AccountFilter.new(filter_params).results |
||||
end |
||||
|
||||
def filter_params |
||||
params.permit(*FILTER_PARAMS) |
||||
end |
||||
|
||||
def pagination_params(core_params) |
||||
params.slice(*PAGINATION_PARAMS).permit(*PAGINATION_PARAMS).merge(core_params) |
||||
end |
||||
end |
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue