Merge commit 'c62604b5f6
' into kb_migration
This commit is contained in:
commit
a1f6ef00db
86 changed files with 929 additions and 221 deletions
|
@ -71,7 +71,7 @@ module.exports = {
|
||||||
'comma-style': ['warn', 'last'],
|
'comma-style': ['warn', 'last'],
|
||||||
'consistent-return': 'error',
|
'consistent-return': 'error',
|
||||||
'dot-notation': 'error',
|
'dot-notation': 'error',
|
||||||
eqeqeq: 'error',
|
eqeqeq: ['error', 'always', { 'null': 'ignore' }],
|
||||||
indent: ['warn', 2],
|
indent: ['warn', 2],
|
||||||
'jsx-quotes': ['error', 'prefer-single'],
|
'jsx-quotes': ['error', 'prefer-single'],
|
||||||
'no-case-declarations': 'off',
|
'no-case-declarations': 'off',
|
||||||
|
|
53
.github/workflows/build-nightly.yml
vendored
Normal file
53
.github/workflows/build-nightly.yml
vendored
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
name: Build nightly container image
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 2 * * *' # run at 2 AM UTC
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-nightly-image:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: hadolint/hadolint-action@v3.1.0
|
||||||
|
- uses: docker/setup-qemu-action@v2
|
||||||
|
- uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
- name: Log in to the Github Container registry
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- uses: docker/metadata-action@v4
|
||||||
|
id: meta
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
ghcr.io/mastodon/mastodon
|
||||||
|
flavor: |
|
||||||
|
latest=auto
|
||||||
|
tags: |
|
||||||
|
type=raw,value=nightly
|
||||||
|
labels: |
|
||||||
|
org.opencontainers.image.description=Nightly build image used for testing purposes
|
||||||
|
|
||||||
|
- uses: docker/build-push-action@v4
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
provenance: false
|
||||||
|
builder: ${{ steps.buildx.outputs.name }}
|
||||||
|
push: ${{ github.repository == 'mastodon/mastodon' && github.event_name != 'pull_request' }}
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
|
@ -1224,9 +1224,6 @@ Rails/ActiveRecordCallbacksOrder:
|
||||||
Rails/ApplicationController:
|
Rails/ApplicationController:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'app/controllers/health_controller.rb'
|
- 'app/controllers/health_controller.rb'
|
||||||
- 'app/controllers/well_known/host_meta_controller.rb'
|
|
||||||
- 'app/controllers/well_known/nodeinfo_controller.rb'
|
|
||||||
- 'app/controllers/well_known/webfinger_controller.rb'
|
|
||||||
|
|
||||||
# Configuration parameters: Database, Include.
|
# Configuration parameters: Database, Include.
|
||||||
# SupportedDatabases: mysql, postgresql
|
# SupportedDatabases: mysql, postgresql
|
||||||
|
|
2
Gemfile
2
Gemfile
|
@ -120,7 +120,7 @@ end
|
||||||
group :test do
|
group :test do
|
||||||
gem 'capybara', '~> 3.39'
|
gem 'capybara', '~> 3.39'
|
||||||
gem 'climate_control'
|
gem 'climate_control'
|
||||||
gem 'faker', '~> 3.1'
|
gem 'faker', '~> 3.2'
|
||||||
gem 'json-schema', '~> 3.0'
|
gem 'json-schema', '~> 3.0'
|
||||||
gem 'rack-test', '~> 2.1'
|
gem 'rack-test', '~> 2.1'
|
||||||
gem 'rails-controller-testing', '~> 1.0'
|
gem 'rails-controller-testing', '~> 1.0'
|
||||||
|
|
18
Gemfile.lock
18
Gemfile.lock
|
@ -243,7 +243,7 @@ GEM
|
||||||
tzinfo
|
tzinfo
|
||||||
excon (0.95.0)
|
excon (0.95.0)
|
||||||
fabrication (2.30.0)
|
fabrication (2.30.0)
|
||||||
faker (3.1.1)
|
faker (3.2.0)
|
||||||
i18n (>= 1.8.11, < 2)
|
i18n (>= 1.8.11, < 2)
|
||||||
faraday (1.10.3)
|
faraday (1.10.3)
|
||||||
faraday-em_http (~> 1.0)
|
faraday-em_http (~> 1.0)
|
||||||
|
@ -346,19 +346,19 @@ GEM
|
||||||
ipaddress (0.8.3)
|
ipaddress (0.8.3)
|
||||||
jmespath (1.6.2)
|
jmespath (1.6.2)
|
||||||
json (2.6.3)
|
json (2.6.3)
|
||||||
json-canonicalization (0.3.0)
|
json-canonicalization (0.3.1)
|
||||||
json-jwt (1.15.3)
|
json-jwt (1.15.3)
|
||||||
activesupport (>= 4.2)
|
activesupport (>= 4.2)
|
||||||
aes_key_wrap
|
aes_key_wrap
|
||||||
bindata
|
bindata
|
||||||
httpclient
|
httpclient
|
||||||
json-ld (3.2.3)
|
json-ld (3.2.4)
|
||||||
htmlentities (~> 4.3)
|
htmlentities (~> 4.3)
|
||||||
json-canonicalization (~> 0.3)
|
json-canonicalization (~> 0.3)
|
||||||
link_header (~> 0.0, >= 0.0.8)
|
link_header (~> 0.0, >= 0.0.8)
|
||||||
multi_json (~> 1.15)
|
multi_json (~> 1.15)
|
||||||
rack (~> 2.2)
|
rack (>= 2.2, < 4)
|
||||||
rdf (~> 3.2, >= 3.2.9)
|
rdf (~> 3.2, >= 3.2.10)
|
||||||
json-ld-preloaded (3.2.2)
|
json-ld-preloaded (3.2.2)
|
||||||
json-ld (~> 3.2)
|
json-ld (~> 3.2)
|
||||||
rdf (~> 3.2)
|
rdf (~> 3.2)
|
||||||
|
@ -477,7 +477,7 @@ GEM
|
||||||
openssl-signature_algorithm (1.3.0)
|
openssl-signature_algorithm (1.3.0)
|
||||||
openssl (> 2.0)
|
openssl (> 2.0)
|
||||||
orm_adapter (0.5.0)
|
orm_adapter (0.5.0)
|
||||||
ox (2.14.14)
|
ox (2.14.16)
|
||||||
parallel (1.22.1)
|
parallel (1.22.1)
|
||||||
parser (3.2.2.0)
|
parser (3.2.2.0)
|
||||||
ast (~> 2.4.1)
|
ast (~> 2.4.1)
|
||||||
|
@ -485,7 +485,7 @@ GEM
|
||||||
pastel (0.8.0)
|
pastel (0.8.0)
|
||||||
tty-color (~> 0.5)
|
tty-color (~> 0.5)
|
||||||
pg (1.4.6)
|
pg (1.4.6)
|
||||||
pghero (3.3.1)
|
pghero (3.3.2)
|
||||||
activerecord (>= 6)
|
activerecord (>= 6)
|
||||||
pkg-config (1.5.1)
|
pkg-config (1.5.1)
|
||||||
posix-spawn (0.3.15)
|
posix-spawn (0.3.15)
|
||||||
|
@ -555,7 +555,7 @@ GEM
|
||||||
thor (~> 1.0)
|
thor (~> 1.0)
|
||||||
rainbow (3.1.1)
|
rainbow (3.1.1)
|
||||||
rake (13.0.6)
|
rake (13.0.6)
|
||||||
rdf (3.2.9)
|
rdf (3.2.10)
|
||||||
link_header (~> 0.0, >= 0.0.8)
|
link_header (~> 0.0, >= 0.0.8)
|
||||||
rdf-normalize (0.5.1)
|
rdf-normalize (0.5.1)
|
||||||
rdf (~> 3.2)
|
rdf (~> 3.2)
|
||||||
|
@ -797,7 +797,7 @@ DEPENDENCIES
|
||||||
dotenv-rails (~> 2.8)
|
dotenv-rails (~> 2.8)
|
||||||
ed25519 (~> 1.3)
|
ed25519 (~> 1.3)
|
||||||
fabrication (~> 2.30)
|
fabrication (~> 2.30)
|
||||||
faker (~> 3.1)
|
faker (~> 3.2)
|
||||||
fast_blank (~> 1.0)
|
fast_blank (~> 1.0)
|
||||||
fastimage
|
fastimage
|
||||||
fog-core (<= 2.4.0)
|
fog-core (<= 2.4.0)
|
||||||
|
|
|
@ -7,8 +7,9 @@ class AccountsController < ApplicationController
|
||||||
include AccountControllerConcern
|
include AccountControllerConcern
|
||||||
include SignatureAuthentication
|
include SignatureAuthentication
|
||||||
|
|
||||||
|
vary_by -> { public_fetch_mode? ? 'Accept' : 'Accept, Signature' }
|
||||||
|
|
||||||
before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
|
before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
|
||||||
before_action :set_cache_headers
|
|
||||||
|
|
||||||
skip_around_action :set_locale, if: -> { [:json, :rss].include?(request.format&.to_sym) }
|
skip_around_action :set_locale, if: -> { [:json, :rss].include?(request.format&.to_sym) }
|
||||||
skip_before_action :require_functional!, unless: :whitelist_mode?
|
skip_before_action :require_functional!, unless: :whitelist_mode?
|
||||||
|
|
|
@ -7,10 +7,6 @@ class ActivityPub::BaseController < Api::BaseController
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_cache_headers
|
|
||||||
response.headers['Vary'] = 'Signature' if authorized_fetch_mode?
|
|
||||||
end
|
|
||||||
|
|
||||||
def skip_temporary_suspension_response?
|
def skip_temporary_suspension_response?
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,11 +4,12 @@ class ActivityPub::CollectionsController < ActivityPub::BaseController
|
||||||
include SignatureVerification
|
include SignatureVerification
|
||||||
include AccountOwnedConcern
|
include AccountOwnedConcern
|
||||||
|
|
||||||
|
vary_by -> { 'Signature' if authorized_fetch_mode? }
|
||||||
|
|
||||||
before_action :require_account_signature!, if: :authorized_fetch_mode?
|
before_action :require_account_signature!, if: :authorized_fetch_mode?
|
||||||
before_action :set_items
|
before_action :set_items
|
||||||
before_action :set_size
|
before_action :set_size
|
||||||
before_action :set_type
|
before_action :set_type
|
||||||
before_action :set_cache_headers
|
|
||||||
|
|
||||||
def show
|
def show
|
||||||
expires_in 3.minutes, public: public_fetch_mode?
|
expires_in 3.minutes, public: public_fetch_mode?
|
||||||
|
|
|
@ -4,9 +4,10 @@ class ActivityPub::FollowersSynchronizationsController < ActivityPub::BaseContro
|
||||||
include SignatureVerification
|
include SignatureVerification
|
||||||
include AccountOwnedConcern
|
include AccountOwnedConcern
|
||||||
|
|
||||||
|
vary_by -> { 'Signature' if authorized_fetch_mode? }
|
||||||
|
|
||||||
before_action :require_account_signature!
|
before_action :require_account_signature!
|
||||||
before_action :set_items
|
before_action :set_items
|
||||||
before_action :set_cache_headers
|
|
||||||
|
|
||||||
def show
|
def show
|
||||||
expires_in 0, public: false
|
expires_in 0, public: false
|
||||||
|
|
|
@ -6,9 +6,10 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController
|
||||||
include SignatureVerification
|
include SignatureVerification
|
||||||
include AccountOwnedConcern
|
include AccountOwnedConcern
|
||||||
|
|
||||||
|
vary_by -> { 'Signature' if authorized_fetch_mode? || page_requested? }
|
||||||
|
|
||||||
before_action :require_account_signature!, if: :authorized_fetch_mode?
|
before_action :require_account_signature!, if: :authorized_fetch_mode?
|
||||||
before_action :set_statuses
|
before_action :set_statuses
|
||||||
before_action :set_cache_headers
|
|
||||||
|
|
||||||
def show
|
def show
|
||||||
if page_requested?
|
if page_requested?
|
||||||
|
@ -16,6 +17,7 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController
|
||||||
else
|
else
|
||||||
expires_in(3.minutes, public: public_fetch_mode?)
|
expires_in(3.minutes, public: public_fetch_mode?)
|
||||||
end
|
end
|
||||||
|
|
||||||
render json: outbox_presenter, serializer: ActivityPub::OutboxSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json'
|
render json: outbox_presenter, serializer: ActivityPub::OutboxSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -80,8 +82,4 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController
|
||||||
def set_account
|
def set_account
|
||||||
@account = params[:account_username].present? ? Account.find_local!(username_param) : Account.representative
|
@account = params[:account_username].present? ? Account.find_local!(username_param) : Account.representative
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_cache_headers
|
|
||||||
response.headers['Vary'] = 'Signature' if authorized_fetch_mode? || page_requested?
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,9 +7,10 @@ class ActivityPub::RepliesController < ActivityPub::BaseController
|
||||||
|
|
||||||
DESCENDANTS_LIMIT = 60
|
DESCENDANTS_LIMIT = 60
|
||||||
|
|
||||||
|
vary_by -> { 'Signature' if authorized_fetch_mode? }
|
||||||
|
|
||||||
before_action :require_account_signature!, if: :authorized_fetch_mode?
|
before_action :require_account_signature!, if: :authorized_fetch_mode?
|
||||||
before_action :set_status
|
before_action :set_status
|
||||||
before_action :set_cache_headers
|
|
||||||
before_action :set_replies
|
before_action :set_replies
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
|
|
@ -8,6 +8,8 @@ module Admin
|
||||||
layout 'admin'
|
layout 'admin'
|
||||||
|
|
||||||
before_action :set_body_classes
|
before_action :set_body_classes
|
||||||
|
before_action :set_cache_headers
|
||||||
|
|
||||||
after_action :verify_authorized
|
after_action :verify_authorized
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -16,6 +18,10 @@ module Admin
|
||||||
@body_classes = 'admin'
|
@body_classes = 'admin'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_cache_headers
|
||||||
|
response.cache_control.replace(private: true, no_store: true)
|
||||||
|
end
|
||||||
|
|
||||||
def set_user
|
def set_user
|
||||||
@user = Account.find(params[:account_id]).user || raise(ActiveRecord::RecordNotFound)
|
@user = Account.find(params[:account_id]).user || raise(ActiveRecord::RecordNotFound)
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,7 +12,7 @@ class Api::BaseController < ApplicationController
|
||||||
|
|
||||||
before_action :require_authenticated_user!, if: :disallow_unauthenticated_api_access?
|
before_action :require_authenticated_user!, if: :disallow_unauthenticated_api_access?
|
||||||
before_action :require_not_suspended!
|
before_action :require_not_suspended!
|
||||||
before_action :set_cache_headers
|
before_action :set_cache_control_defaults
|
||||||
|
|
||||||
protect_from_forgery with: :null_session
|
protect_from_forgery with: :null_session
|
||||||
|
|
||||||
|
@ -148,8 +148,8 @@ class Api::BaseController < ApplicationController
|
||||||
doorkeeper_authorize!(*scopes) if doorkeeper_token
|
doorkeeper_authorize!(*scopes) if doorkeeper_token
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_cache_headers
|
def set_cache_control_defaults
|
||||||
response.headers['Cache-Control'] = 'private, no-store'
|
response.cache_control.replace(private: true, no_store: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
def disallow_unauthenticated_api_access?
|
def disallow_unauthenticated_api_access?
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Api::V1::Admin::Trends::Links::PreviewCardProvidersController < Api::BaseController
|
||||||
|
include Authorization
|
||||||
|
|
||||||
|
LIMIT = 100
|
||||||
|
|
||||||
|
before_action -> { authorize_if_got_token! :'admin:read' }, only: :index
|
||||||
|
before_action -> { authorize_if_got_token! :'admin:write' }, except: :index
|
||||||
|
before_action :set_providers, only: :index
|
||||||
|
|
||||||
|
after_action :verify_authorized
|
||||||
|
after_action :insert_pagination_headers, only: :index
|
||||||
|
|
||||||
|
PAGINATION_PARAMS = %i(limit).freeze
|
||||||
|
|
||||||
|
def index
|
||||||
|
authorize :preview_card_provider, :index?
|
||||||
|
|
||||||
|
render json: @providers, each_serializer: REST::Admin::Trends::Links::PreviewCardProviderSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def approve
|
||||||
|
authorize :preview_card_provider, :review?
|
||||||
|
|
||||||
|
provider = PreviewCardProvider.find(params[:id])
|
||||||
|
provider.update(trendable: true, reviewed_at: Time.now.utc)
|
||||||
|
render json: provider, serializer: REST::Admin::Trends::Links::PreviewCardProviderSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def reject
|
||||||
|
authorize :preview_card_provider, :review?
|
||||||
|
|
||||||
|
provider = PreviewCardProvider.find(params[:id])
|
||||||
|
provider.update(trendable: false, reviewed_at: Time.now.utc)
|
||||||
|
render json: provider, serializer: REST::Admin::Trends::Links::PreviewCardProviderSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_providers
|
||||||
|
@providers = PreviewCardProvider.all.to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
|
||||||
|
end
|
||||||
|
|
||||||
|
def insert_pagination_headers
|
||||||
|
set_pagination_headers(next_path, prev_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_path
|
||||||
|
api_v1_admin_trends_links_preview_card_providers_url(pagination_params(max_id: pagination_max_id)) if records_continue?
|
||||||
|
end
|
||||||
|
|
||||||
|
def prev_path
|
||||||
|
api_v1_admin_trends_links_preview_card_providers_url(pagination_params(min_id: pagination_since_id)) unless @providers.empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_max_id
|
||||||
|
@providers.last.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_since_id
|
||||||
|
@providers.first.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def records_continue?
|
||||||
|
@providers.size == limit_param(LIMIT)
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_params(core_params)
|
||||||
|
params.slice(*PAGINATION_PARAMS).permit(*PAGINATION_PARAMS).merge(core_params)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,7 +1,36 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::Admin::Trends::LinksController < Api::V1::Trends::LinksController
|
class Api::V1::Admin::Trends::LinksController < Api::V1::Trends::LinksController
|
||||||
before_action -> { authorize_if_got_token! :'admin:read' }
|
include Authorization
|
||||||
|
|
||||||
|
before_action -> { authorize_if_got_token! :'admin:read' }, only: :index
|
||||||
|
before_action -> { authorize_if_got_token! :'admin:write' }, except: :index
|
||||||
|
|
||||||
|
after_action :verify_authorized, except: :index
|
||||||
|
|
||||||
|
def index
|
||||||
|
if current_user&.can?(:manage_taxonomies)
|
||||||
|
render json: @links, each_serializer: REST::Admin::Trends::LinkSerializer
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def approve
|
||||||
|
authorize :preview_card, :review?
|
||||||
|
|
||||||
|
link = PreviewCard.find(params[:id])
|
||||||
|
link.update(trendable: true)
|
||||||
|
render json: link, serializer: REST::Admin::Trends::LinkSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def reject
|
||||||
|
authorize :preview_card, :review?
|
||||||
|
|
||||||
|
link = PreviewCard.find(params[:id])
|
||||||
|
link.update(trendable: false)
|
||||||
|
render json: link, serializer: REST::Admin::Trends::LinkSerializer
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,36 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::Admin::Trends::StatusesController < Api::V1::Trends::StatusesController
|
class Api::V1::Admin::Trends::StatusesController < Api::V1::Trends::StatusesController
|
||||||
before_action -> { authorize_if_got_token! :'admin:read' }
|
include Authorization
|
||||||
|
|
||||||
|
before_action -> { authorize_if_got_token! :'admin:read' }, only: :index
|
||||||
|
before_action -> { authorize_if_got_token! :'admin:write' }, except: :index
|
||||||
|
|
||||||
|
after_action :verify_authorized, except: :index
|
||||||
|
|
||||||
|
def index
|
||||||
|
if current_user&.can?(:manage_taxonomies)
|
||||||
|
render json: @statuses, each_serializer: REST::Admin::Trends::StatusSerializer
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def approve
|
||||||
|
authorize [:admin, :status], :review?
|
||||||
|
|
||||||
|
status = Status.find(params[:id])
|
||||||
|
status.update(trendable: true)
|
||||||
|
render json: status, serializer: REST::Admin::Trends::StatusSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def reject
|
||||||
|
authorize [:admin, :status], :review?
|
||||||
|
|
||||||
|
status = Status.find(params[:id])
|
||||||
|
status.update(trendable: false)
|
||||||
|
render json: status, serializer: REST::Admin::Trends::StatusSerializer
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::Admin::Trends::TagsController < Api::V1::Trends::TagsController
|
class Api::V1::Admin::Trends::TagsController < Api::V1::Trends::TagsController
|
||||||
before_action -> { authorize_if_got_token! :'admin:read' }
|
include Authorization
|
||||||
|
|
||||||
|
before_action -> { authorize_if_got_token! :'admin:read' }, only: :index
|
||||||
|
before_action -> { authorize_if_got_token! :'admin:write' }, except: :index
|
||||||
|
|
||||||
|
after_action :verify_authorized, except: :index
|
||||||
|
|
||||||
def index
|
def index
|
||||||
if current_user&.can?(:manage_taxonomies)
|
if current_user&.can?(:manage_taxonomies)
|
||||||
|
@ -11,6 +16,22 @@ class Api::V1::Admin::Trends::TagsController < Api::V1::Trends::TagsController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def approve
|
||||||
|
authorize :tag, :review?
|
||||||
|
|
||||||
|
tag = Tag.find(params[:id])
|
||||||
|
tag.update(trendable: true, reviewed_at: Time.now.utc)
|
||||||
|
render json: tag, serializer: REST::Admin::TagSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def reject
|
||||||
|
authorize :tag, :review?
|
||||||
|
|
||||||
|
tag = Tag.find(params[:id])
|
||||||
|
tag.update(trendable: false, reviewed_at: Time.now.utc)
|
||||||
|
render json: tag, serializer: REST::Admin::TagSerializer
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def enabled?
|
def enabled?
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::CustomEmojisController < Api::BaseController
|
class Api::V1::CustomEmojisController < Api::BaseController
|
||||||
skip_before_action :set_cache_headers
|
|
||||||
|
|
||||||
def index
|
def index
|
||||||
expires_in 3.minutes, public: true
|
expires_in 3.minutes, public: true
|
||||||
render_with_cache(each_serializer: REST::CustomEmojiSerializer) { CustomEmoji.listed.includes(:category) }
|
render_with_cache(each_serializer: REST::CustomEmojiSerializer) { CustomEmoji.listed.includes(:category) }
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
class Api::V1::Instances::ActivityController < Api::BaseController
|
class Api::V1::Instances::ActivityController < Api::BaseController
|
||||||
before_action :require_enabled_api!
|
before_action :require_enabled_api!
|
||||||
|
|
||||||
skip_before_action :set_cache_headers
|
|
||||||
skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
|
skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
class Api::V1::Instances::PeersController < Api::BaseController
|
class Api::V1::Instances::PeersController < Api::BaseController
|
||||||
before_action :require_enabled_api!
|
before_action :require_enabled_api!
|
||||||
|
|
||||||
skip_before_action :set_cache_headers
|
|
||||||
skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
|
skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::InstancesController < Api::BaseController
|
class Api::V1::InstancesController < Api::BaseController
|
||||||
skip_before_action :set_cache_headers
|
|
||||||
skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
|
skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
|
|
@ -152,6 +152,6 @@ class Auth::RegistrationsController < Devise::RegistrationsController
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_cache_headers
|
def set_cache_headers
|
||||||
response.headers['Cache-Control'] = 'private, no-store'
|
response.cache_control.replace(private: true, no_store: true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -155,8 +155,16 @@ module CacheConcern
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class_methods do
|
||||||
|
def vary_by(value)
|
||||||
|
before_action do |controller|
|
||||||
|
response.headers['Vary'] = value.respond_to?(:call) ? controller.instance_exec(&value) : value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def render_with_cache(**options)
|
def render_with_cache(**options)
|
||||||
raise ArgumentError, 'only JSON render calls are supported' unless options.key?(:json) || block_given?
|
raise ArgumentError, 'Only JSON render calls are supported' unless options.key?(:json) || block_given?
|
||||||
|
|
||||||
key = options.delete(:key) || [[params[:controller], params[:action]].join('/'), options[:json].respond_to?(:cache_key) ? options[:json].cache_key : nil, options[:fields].nil? ? nil : options[:fields].join(',')].compact.join(':')
|
key = options.delete(:key) || [[params[:controller], params[:action]].join('/'), options[:json].respond_to?(:cache_key) ? options[:json].cache_key : nil, options[:fields].nil? ? nil : options[:fields].join(',')].compact.join(':')
|
||||||
expires_in = options.delete(:expires_in) || 3.minutes
|
expires_in = options.delete(:expires_in) || 3.minutes
|
||||||
|
@ -176,10 +184,6 @@ module CacheConcern
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_cache_headers
|
|
||||||
response.headers['Vary'] = public_fetch_mode? ? 'Accept' : 'Accept, Signature'
|
|
||||||
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)
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,8 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class CustomCssController < ApplicationController
|
class CustomCssController < ActionController::Base # rubocop:disable Rails/ApplicationController
|
||||||
skip_before_action :store_current_location
|
|
||||||
skip_before_action :require_functional!
|
|
||||||
skip_before_action :update_user_sign_in
|
|
||||||
skip_before_action :set_session_activity
|
|
||||||
|
|
||||||
skip_around_action :set_locale
|
|
||||||
|
|
||||||
before_action :set_cache_headers
|
|
||||||
|
|
||||||
def show
|
def show
|
||||||
expires_in 3.minutes, public: true
|
expires_in 3.minutes, public: true
|
||||||
request.session_options[:skip] = true
|
|
||||||
render content_type: 'text/css'
|
render content_type: 'text/css'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,10 +9,15 @@ class Disputes::BaseController < ApplicationController
|
||||||
|
|
||||||
before_action :set_body_classes
|
before_action :set_body_classes
|
||||||
before_action :authenticate_user!
|
before_action :authenticate_user!
|
||||||
|
before_action :set_cache_headers
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_body_classes
|
def set_body_classes
|
||||||
@body_classes = 'admin'
|
@body_classes = 'admin'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_cache_headers
|
||||||
|
response.cache_control.replace(private: true, no_store: true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,16 +2,13 @@
|
||||||
|
|
||||||
class EmojisController < ApplicationController
|
class EmojisController < ApplicationController
|
||||||
before_action :set_emoji
|
before_action :set_emoji
|
||||||
before_action :set_cache_headers
|
|
||||||
|
vary_by -> { 'Signature' if authorized_fetch_mode? }
|
||||||
|
|
||||||
def show
|
def show
|
||||||
respond_to do |format|
|
|
||||||
format.json do
|
|
||||||
expires_in 3.minutes, public: true
|
expires_in 3.minutes, public: true
|
||||||
render_with_cache json: @emoji, content_type: 'application/activity+json', serializer: ActivityPub::EmojiSerializer, adapter: ActivityPub::Adapter
|
render_with_cache json: @emoji, content_type: 'application/activity+json', serializer: ActivityPub::EmojiSerializer, adapter: ActivityPub::Adapter
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ class Filters::StatusesController < ApplicationController
|
||||||
before_action :set_filter
|
before_action :set_filter
|
||||||
before_action :set_status_filters
|
before_action :set_status_filters
|
||||||
before_action :set_body_classes
|
before_action :set_body_classes
|
||||||
|
before_action :set_cache_headers
|
||||||
|
|
||||||
PER_PAGE = 20
|
PER_PAGE = 20
|
||||||
|
|
||||||
|
@ -44,4 +45,8 @@ class Filters::StatusesController < ApplicationController
|
||||||
def set_body_classes
|
def set_body_classes
|
||||||
@body_classes = 'admin'
|
@body_classes = 'admin'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_cache_headers
|
||||||
|
response.cache_control.replace(private: true, no_store: true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,6 +6,7 @@ class FiltersController < ApplicationController
|
||||||
before_action :authenticate_user!
|
before_action :authenticate_user!
|
||||||
before_action :set_filter, only: [:edit, :update, :destroy]
|
before_action :set_filter, only: [:edit, :update, :destroy]
|
||||||
before_action :set_body_classes
|
before_action :set_body_classes
|
||||||
|
before_action :set_cache_headers
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@filters = current_account.custom_filters.includes(:keywords, :statuses).order(:phrase)
|
@filters = current_account.custom_filters.includes(:keywords, :statuses).order(:phrase)
|
||||||
|
@ -54,4 +55,8 @@ class FiltersController < ApplicationController
|
||||||
def set_body_classes
|
def set_body_classes
|
||||||
@body_classes = 'admin'
|
@body_classes = 'admin'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_cache_headers
|
||||||
|
response.cache_control.replace(private: true, no_store: true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,8 +5,9 @@ class FollowerAccountsController < ApplicationController
|
||||||
include SignatureVerification
|
include SignatureVerification
|
||||||
include WebAppControllerConcern
|
include WebAppControllerConcern
|
||||||
|
|
||||||
|
vary_by -> { public_fetch_mode? ? 'Accept' : 'Accept, Signature' }
|
||||||
|
|
||||||
before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
|
before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
|
||||||
before_action :set_cache_headers
|
|
||||||
|
|
||||||
skip_around_action :set_locale, if: -> { request.format == :json }
|
skip_around_action :set_locale, if: -> { request.format == :json }
|
||||||
skip_before_action :require_functional!, unless: :whitelist_mode?
|
skip_before_action :require_functional!, unless: :whitelist_mode?
|
||||||
|
|
|
@ -5,8 +5,9 @@ class FollowingAccountsController < ApplicationController
|
||||||
include SignatureVerification
|
include SignatureVerification
|
||||||
include WebAppControllerConcern
|
include WebAppControllerConcern
|
||||||
|
|
||||||
|
vary_by -> { public_fetch_mode? ? 'Accept' : 'Accept, Signature' }
|
||||||
|
|
||||||
before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
|
before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
|
||||||
before_action :set_cache_headers
|
|
||||||
|
|
||||||
skip_around_action :set_locale, if: -> { request.format == :json }
|
skip_around_action :set_locale, if: -> { request.format == :json }
|
||||||
skip_before_action :require_functional!, unless: :whitelist_mode?
|
skip_before_action :require_functional!, unless: :whitelist_mode?
|
||||||
|
|
|
@ -7,6 +7,7 @@ class InvitesController < ApplicationController
|
||||||
|
|
||||||
before_action :authenticate_user!
|
before_action :authenticate_user!
|
||||||
before_action :set_body_classes
|
before_action :set_body_classes
|
||||||
|
before_action :set_cache_headers
|
||||||
|
|
||||||
def index
|
def index
|
||||||
authorize :invite, :create?
|
authorize :invite, :create?
|
||||||
|
@ -49,4 +50,8 @@ class InvitesController < ApplicationController
|
||||||
def set_body_classes
|
def set_body_classes
|
||||||
@body_classes = 'admin'
|
@body_classes = 'admin'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_cache_headers
|
||||||
|
response.cache_control.replace(private: true, no_store: true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class ManifestsController < ApplicationController
|
class ManifestsController < ActionController::Base # rubocop:disable Rails/ApplicationController
|
||||||
skip_before_action :store_current_location
|
|
||||||
skip_before_action :require_functional!
|
|
||||||
|
|
||||||
def show
|
def show
|
||||||
expires_in 3.minutes, public: true
|
expires_in 3.minutes, public: true
|
||||||
render json: InstancePresenter.new, serializer: ManifestSerializer, root: 'instance'
|
render json: InstancePresenter.new, serializer: ManifestSerializer, root: 'instance'
|
||||||
|
|
|
@ -34,6 +34,6 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_cache_headers
|
def set_cache_headers
|
||||||
response.headers['Cache-Control'] = 'private, no-store'
|
response.cache_control.replace(private: true, no_store: true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,6 +7,7 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
|
||||||
before_action :authenticate_resource_owner!
|
before_action :authenticate_resource_owner!
|
||||||
before_action :require_not_suspended!, only: :destroy
|
before_action :require_not_suspended!, only: :destroy
|
||||||
before_action :set_body_classes
|
before_action :set_body_classes
|
||||||
|
before_action :set_cache_headers
|
||||||
|
|
||||||
skip_before_action :require_functional!
|
skip_before_action :require_functional!
|
||||||
|
|
||||||
|
@ -30,4 +31,8 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
|
||||||
def require_not_suspended!
|
def require_not_suspended!
|
||||||
forbidden if current_account.suspended?
|
forbidden if current_account.suspended?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_cache_headers
|
||||||
|
response.cache_control.replace(private: true, no_store: true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,6 +7,7 @@ class RelationshipsController < ApplicationController
|
||||||
before_action :set_accounts, only: :show
|
before_action :set_accounts, only: :show
|
||||||
before_action :set_relationships, only: :show
|
before_action :set_relationships, only: :show
|
||||||
before_action :set_body_classes
|
before_action :set_body_classes
|
||||||
|
before_action :set_cache_headers
|
||||||
|
|
||||||
helper_method :following_relationship?, :followed_by_relationship?, :mutual_relationship?
|
helper_method :following_relationship?, :followed_by_relationship?, :mutual_relationship?
|
||||||
|
|
||||||
|
@ -70,4 +71,8 @@ class RelationshipsController < ApplicationController
|
||||||
def set_body_classes
|
def set_body_classes
|
||||||
@body_classes = 'admin'
|
@body_classes = 'admin'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_cache_headers
|
||||||
|
response.cache_control.replace(private: true, no_store: true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,7 +14,7 @@ class Settings::BaseController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_cache_headers
|
def set_cache_headers
|
||||||
response.headers['Cache-Control'] = 'private, no-store'
|
response.cache_control.replace(private: true, no_store: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
def require_not_suspended!
|
def require_not_suspended!
|
||||||
|
|
|
@ -6,6 +6,7 @@ class StatusesCleanupController < ApplicationController
|
||||||
before_action :authenticate_user!
|
before_action :authenticate_user!
|
||||||
before_action :set_policy
|
before_action :set_policy
|
||||||
before_action :set_body_classes
|
before_action :set_body_classes
|
||||||
|
before_action :set_cache_headers
|
||||||
|
|
||||||
def show; end
|
def show; end
|
||||||
|
|
||||||
|
@ -36,4 +37,8 @@ class StatusesCleanupController < ApplicationController
|
||||||
def set_body_classes
|
def set_body_classes
|
||||||
@body_classes = 'admin'
|
@body_classes = 'admin'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_cache_headers
|
||||||
|
response.cache_control.replace(private: true, no_store: true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,11 +6,12 @@ class StatusesController < ApplicationController
|
||||||
include Authorization
|
include Authorization
|
||||||
include AccountOwnedConcern
|
include AccountOwnedConcern
|
||||||
|
|
||||||
|
vary_by -> { public_fetch_mode? ? 'Accept' : 'Accept, Signature' }
|
||||||
|
|
||||||
before_action :require_account_signature!, only: [:show, :activity], if: -> { request.format == :json && authorized_fetch_mode? }
|
before_action :require_account_signature!, only: [:show, :activity], if: -> { request.format == :json && authorized_fetch_mode? }
|
||||||
before_action :set_status
|
before_action :set_status
|
||||||
before_action :set_instance_presenter
|
before_action :set_instance_presenter
|
||||||
before_action :redirect_to_original, only: :show
|
before_action :redirect_to_original, only: :show
|
||||||
before_action :set_cache_headers
|
|
||||||
before_action :set_body_classes, only: :embed
|
before_action :set_body_classes, only: :embed
|
||||||
|
|
||||||
after_action :set_link_headers
|
after_action :set_link_headers
|
||||||
|
|
|
@ -7,6 +7,8 @@ class TagsController < ApplicationController
|
||||||
PAGE_SIZE = 20
|
PAGE_SIZE = 20
|
||||||
PAGE_SIZE_MAX = 200
|
PAGE_SIZE_MAX = 200
|
||||||
|
|
||||||
|
vary_by -> { public_fetch_mode? ? 'Accept' : 'Accept, Signature' }
|
||||||
|
|
||||||
before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
|
before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
|
||||||
before_action :authenticate_user!, if: :whitelist_mode?
|
before_action :authenticate_user!, if: :whitelist_mode?
|
||||||
before_action :set_local
|
before_action :set_local
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module WellKnown
|
module WellKnown
|
||||||
class HostMetaController < ActionController::Base
|
class HostMetaController < ActionController::Base # rubocop:disable Rails/ApplicationController
|
||||||
include RoutingHelper
|
include RoutingHelper
|
||||||
|
|
||||||
before_action { response.headers['Vary'] = 'Accept' }
|
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@webfinger_template = "#{webfinger_url}?resource={uri}"
|
@webfinger_template = "#{webfinger_url}?resource={uri}"
|
||||||
expires_in 3.days, public: true
|
expires_in 3.days, public: true
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module WellKnown
|
module WellKnown
|
||||||
class NodeInfoController < ActionController::Base
|
class NodeInfoController < ActionController::Base # rubocop:disable Rails/ApplicationController
|
||||||
include CacheConcern
|
include CacheConcern
|
||||||
|
|
||||||
before_action { response.headers['Vary'] = 'Accept' }
|
|
||||||
|
|
||||||
def index
|
def index
|
||||||
expires_in 3.days, public: true
|
expires_in 3.days, public: true
|
||||||
render_with_cache json: {}, serializer: NodeInfo::DiscoverySerializer, adapter: NodeInfo::Adapter, expires_in: 3.days, root: 'nodeinfo'
|
render_with_cache json: {}, serializer: NodeInfo::DiscoverySerializer, adapter: NodeInfo::Adapter, expires_in: 3.days, root: 'nodeinfo'
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module WellKnown
|
module WellKnown
|
||||||
class WebfingerController < ActionController::Base
|
class WebfingerController < ActionController::Base # rubocop:disable Rails/ApplicationController
|
||||||
include RoutingHelper
|
include RoutingHelper
|
||||||
|
|
||||||
before_action :set_account
|
before_action :set_account
|
||||||
|
@ -34,7 +34,12 @@ module WellKnown
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_account_suspension
|
def check_account_suspension
|
||||||
expires_in(3.minutes, public: true) && gone if @account.suspended_permanently?
|
gone if @account.suspended_permanently?
|
||||||
|
end
|
||||||
|
|
||||||
|
def gone
|
||||||
|
expires_in(3.minutes, public: true)
|
||||||
|
head 410
|
||||||
end
|
end
|
||||||
|
|
||||||
def bad_request
|
def bad_request
|
||||||
|
@ -46,9 +51,5 @@ module WellKnown
|
||||||
expires_in(3.minutes, public: true)
|
expires_in(3.minutes, public: true)
|
||||||
head 404
|
head 404
|
||||||
end
|
end
|
||||||
|
|
||||||
def gone
|
|
||||||
head 410
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -32,17 +32,14 @@ function ShortNumber({ value, renderer, children }) {
|
||||||
const shortNumber = toShortNumber(value);
|
const shortNumber = toShortNumber(value);
|
||||||
const [, division] = shortNumber;
|
const [, division] = shortNumber;
|
||||||
|
|
||||||
// eslint-disable-next-line eqeqeq
|
|
||||||
if (children != null && renderer != null) {
|
if (children != null && renderer != null) {
|
||||||
console.warn('Both renderer prop and renderer as a child provided. This is a mistake and you really should fix that. Only renderer passed as a child will be used.');
|
console.warn('Both renderer prop and renderer as a child provided. This is a mistake and you really should fix that. Only renderer passed as a child will be used.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line eqeqeq
|
|
||||||
const customRenderer = children != null ? children : renderer;
|
const customRenderer = children != null ? children : renderer;
|
||||||
|
|
||||||
const displayNumber = <ShortNumberCounter value={shortNumber} />;
|
const displayNumber = <ShortNumberCounter value={shortNumber} />;
|
||||||
|
|
||||||
// eslint-disable-next-line eqeqeq
|
|
||||||
return customRenderer != null
|
return customRenderer != null
|
||||||
? customRenderer(displayNumber, pluralReady(value, division))
|
? customRenderer(displayNumber, pluralReady(value, division))
|
||||||
: displayNumber;
|
: displayNumber;
|
||||||
|
|
|
@ -60,7 +60,6 @@ export function toShortNumber(sourceNumber) {
|
||||||
* // => 1790
|
* // => 1790
|
||||||
*/
|
*/
|
||||||
export function pluralReady(sourceNumber, division) {
|
export function pluralReady(sourceNumber, division) {
|
||||||
// eslint-disable-next-line eqeqeq
|
|
||||||
if (division == null || division < DECIMAL_UNITS.HUNDRED) {
|
if (division == null || division < DECIMAL_UNITS.HUNDRED) {
|
||||||
return sourceNumber;
|
return sourceNumber;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
class PreviewCardProvider < ApplicationRecord
|
class PreviewCardProvider < ApplicationRecord
|
||||||
|
include Paginable
|
||||||
include DomainNormalizable
|
include DomainNormalizable
|
||||||
include Attachmentable
|
include Attachmentable
|
||||||
|
|
||||||
|
|
9
app/serializers/rest/admin/trends/link_serializer.rb
Normal file
9
app/serializers/rest/admin/trends/link_serializer.rb
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class REST::Admin::Trends::LinkSerializer < REST::Trends::LinkSerializer
|
||||||
|
attributes :id, :requires_review
|
||||||
|
|
||||||
|
def requires_review
|
||||||
|
object.requires_review?
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,10 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class REST::Admin::Trends::Links::PreviewCardProviderSerializer < ActiveModel::Serializer
|
||||||
|
attributes :id, :domain, :trendable, :reviewed_at,
|
||||||
|
:requested_review_at, :requires_review
|
||||||
|
|
||||||
|
def requires_review
|
||||||
|
object.requires_review?
|
||||||
|
end
|
||||||
|
end
|
9
app/serializers/rest/admin/trends/status_serializer.rb
Normal file
9
app/serializers/rest/admin/trends/status_serializer.rb
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class REST::Admin::Trends::StatusSerializer < REST::StatusSerializer
|
||||||
|
attributes :requires_review
|
||||||
|
|
||||||
|
def requires_review
|
||||||
|
object.requires_review?
|
||||||
|
end
|
||||||
|
end
|
|
@ -43,6 +43,7 @@ require_relative '../lib/chewy/strategy/bypass_with_warning'
|
||||||
require_relative '../lib/webpacker/manifest_extensions'
|
require_relative '../lib/webpacker/manifest_extensions'
|
||||||
require_relative '../lib/webpacker/helper_extensions'
|
require_relative '../lib/webpacker/helper_extensions'
|
||||||
require_relative '../lib/rails/engine_extensions'
|
require_relative '../lib/rails/engine_extensions'
|
||||||
|
require_relative '../lib/action_controller/conditional_get_extensions'
|
||||||
require_relative '../lib/active_record/database_tasks_extensions'
|
require_relative '../lib/active_record/database_tasks_extensions'
|
||||||
require_relative '../lib/active_record/batches'
|
require_relative '../lib/active_record/batches'
|
||||||
require_relative '../lib/simple_navigation/item_extensions'
|
require_relative '../lib/simple_navigation/item_extensions'
|
||||||
|
|
|
@ -676,9 +676,33 @@ Rails.application.routes.draw do
|
||||||
resources :ip_blocks, only: [:index, :show, :update, :create, :destroy]
|
resources :ip_blocks, only: [:index, :show, :update, :create, :destroy]
|
||||||
|
|
||||||
namespace :trends do
|
namespace :trends do
|
||||||
resources :tags, only: [:index]
|
resources :tags, only: [:index] do
|
||||||
resources :links, only: [:index]
|
member do
|
||||||
resources :statuses, only: [:index]
|
post :approve
|
||||||
|
post :reject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
resources :links, only: [:index] do
|
||||||
|
member do
|
||||||
|
post :approve
|
||||||
|
post :reject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
resources :statuses, only: [:index] do
|
||||||
|
member do
|
||||||
|
post :approve
|
||||||
|
post :reject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
namespace :links do
|
||||||
|
resources :preview_card_providers, only: [:index], path: :publishers do
|
||||||
|
member do
|
||||||
|
post :approve
|
||||||
|
post :reject
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
post :measures, to: 'measures#create'
|
post :measures, to: 'measures#create'
|
||||||
|
|
15
lib/action_controller/conditional_get_extensions.rb
Normal file
15
lib/action_controller/conditional_get_extensions.rb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module ActionController
|
||||||
|
module ConditionalGetExtensions
|
||||||
|
def expires_in(*)
|
||||||
|
# This backports a fix from Rails 7 so that a more private Cache-Control
|
||||||
|
# can be overriden by calling expires_in on a specific controller action
|
||||||
|
response.cache_control.delete(:no_store)
|
||||||
|
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ActionController::ConditionalGet.prepend(ActionController::ConditionalGetExtensions)
|
|
@ -189,9 +189,10 @@ module Mastodon
|
||||||
user.disabled = true if options[:disable]
|
user.disabled = true if options[:disable]
|
||||||
user.approved = true if options[:approve]
|
user.approved = true if options[:approve]
|
||||||
user.otp_required_for_login = false if options[:disable_2fa]
|
user.otp_required_for_login = false if options[:disable_2fa]
|
||||||
user.confirm if options[:confirm]
|
|
||||||
|
|
||||||
if user.save
|
if user.save
|
||||||
|
user.confirm if options[:confirm]
|
||||||
|
|
||||||
say('OK', :green)
|
say('OK', :green)
|
||||||
say("New password: #{password}") if options[:reset_password]
|
say("New password: #{password}") if options[:reset_password]
|
||||||
else
|
else
|
||||||
|
|
|
@ -65,7 +65,7 @@
|
||||||
"fuzzysort": "^2.0.4",
|
"fuzzysort": "^2.0.4",
|
||||||
"glob": "^10.0.0",
|
"glob": "^10.0.0",
|
||||||
"history": "^4.10.1",
|
"history": "^4.10.1",
|
||||||
"http-link-header": "^1.1.0",
|
"http-link-header": "^1.1.1",
|
||||||
"immutable": "^4.3.0",
|
"immutable": "^4.3.0",
|
||||||
"imports-loader": "^1.2.0",
|
"imports-loader": "^1.2.0",
|
||||||
"intl": "^1.2.5",
|
"intl": "^1.2.5",
|
||||||
|
@ -83,7 +83,7 @@
|
||||||
"path-complete-extname": "^1.0.0",
|
"path-complete-extname": "^1.0.0",
|
||||||
"pg": "^8.5.0",
|
"pg": "^8.5.0",
|
||||||
"pg-connection-string": "^2.5.0",
|
"pg-connection-string": "^2.5.0",
|
||||||
"postcss": "^8.4.21",
|
"postcss": "^8.4.22",
|
||||||
"postcss-loader": "^4.3.0",
|
"postcss-loader": "^4.3.0",
|
||||||
"promise.prototype.finally": "^3.1.4",
|
"promise.prototype.finally": "^3.1.4",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
|
@ -113,7 +113,7 @@
|
||||||
"redux-thunk": "^2.4.2",
|
"redux-thunk": "^2.4.2",
|
||||||
"regenerator-runtime": "^0.13.11",
|
"regenerator-runtime": "^0.13.11",
|
||||||
"requestidlecallback": "^0.3.0",
|
"requestidlecallback": "^0.3.0",
|
||||||
"reselect": "^4.1.7",
|
"reselect": "^4.1.8",
|
||||||
"rimraf": "^5.0.0",
|
"rimraf": "^5.0.0",
|
||||||
"sass": "^1.61.0",
|
"sass": "^1.61.0",
|
||||||
"sass-loader": "^10.2.0",
|
"sass-loader": "^10.2.0",
|
||||||
|
|
|
@ -17,6 +17,10 @@ RSpec.describe AccountsController, type: :controller do
|
||||||
expect(session).to be_empty
|
expect(session).to be_empty
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns Vary header' do
|
||||||
|
expect(response.headers['Vary']).to include 'Accept'
|
||||||
|
end
|
||||||
|
|
||||||
it 'returns public Cache-Control header' do
|
it 'returns public Cache-Control header' do
|
||||||
expect(response.headers['Cache-Control']).to include 'public'
|
expect(response.headers['Cache-Control']).to include 'public'
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,6 +18,14 @@ describe Admin::BaseController, type: :controller do
|
||||||
expect(response).to have_http_status(403)
|
expect(response).to have_http_status(403)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns private cache control headers' do
|
||||||
|
routes.draw { get 'success' => 'admin/base#success' }
|
||||||
|
sign_in(Fabricate(:user, role: UserRole.find_by(name: 'Moderator')))
|
||||||
|
get :success
|
||||||
|
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
|
end
|
||||||
|
|
||||||
it 'renders admin layout as a moderator' do
|
it 'renders admin layout as a moderator' do
|
||||||
routes.draw { get 'success' => 'admin/base#success' }
|
routes.draw { get 'success' => 'admin/base#success' }
|
||||||
sign_in(Fabricate(:user, role: UserRole.find_by(name: 'Moderator')))
|
sign_in(Fabricate(:user, role: UserRole.find_by(name: 'Moderator')))
|
||||||
|
|
|
@ -15,6 +15,12 @@ describe Api::BaseController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns private cache control headers by default' do
|
||||||
|
routes.draw { get 'success' => 'api/base#success' }
|
||||||
|
get :success
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
|
end
|
||||||
|
|
||||||
describe 'forgery protection' do
|
describe 'forgery protection' do
|
||||||
before do
|
before do
|
||||||
routes.draw { post 'success' => 'api/base#success' }
|
routes.draw { post 'success' => 'api/base#success' }
|
||||||
|
|
|
@ -17,5 +17,9 @@ RSpec.describe Api::OEmbedController, type: :controller do
|
||||||
it 'returns http success' do
|
it 'returns http success' do
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns private cache control headers' do
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
describe Api::V1::Admin::Trends::Links::PreviewCardProvidersController do
|
||||||
|
render_views
|
||||||
|
|
||||||
|
let(:role) { UserRole.find_by(name: 'Admin') }
|
||||||
|
let(:user) { Fabricate(:user, role: role) }
|
||||||
|
let(:scopes) { 'admin:read admin:write' }
|
||||||
|
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||||
|
let(:account) { Fabricate(:account) }
|
||||||
|
let(:preview_card_provider) { Fabricate(:preview_card_provider) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(controller).to receive(:doorkeeper_token) { token }
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples 'forbidden for wrong scope' do |wrong_scope|
|
||||||
|
let(:scopes) { wrong_scope }
|
||||||
|
|
||||||
|
it 'returns http forbidden' do
|
||||||
|
expect(response).to have_http_status(403)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples 'forbidden for wrong role' do |wrong_role|
|
||||||
|
let(:role) { UserRole.find_by(name: wrong_role) }
|
||||||
|
|
||||||
|
it 'returns http forbidden' do
|
||||||
|
expect(response).to have_http_status(403)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'GET #index' do
|
||||||
|
it 'returns http success' do
|
||||||
|
get :index, params: { account_id: account.id, limit: 2 }
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST #approve' do
|
||||||
|
before do
|
||||||
|
post :approve, params: { id: preview_card_provider.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||||
|
it_behaves_like 'forbidden for wrong role', ''
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST #reject' do
|
||||||
|
before do
|
||||||
|
post :reject, params: { id: preview_card_provider.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||||
|
it_behaves_like 'forbidden for wrong role', ''
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -5,14 +5,33 @@ require 'rails_helper'
|
||||||
describe Api::V1::Admin::Trends::LinksController do
|
describe Api::V1::Admin::Trends::LinksController do
|
||||||
render_views
|
render_views
|
||||||
|
|
||||||
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
|
let(:role) { UserRole.find_by(name: 'Admin') }
|
||||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'admin:read') }
|
let(:user) { Fabricate(:user, role: role) }
|
||||||
|
let(:scopes) { 'admin:read admin:write' }
|
||||||
|
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||||
let(:account) { Fabricate(:account) }
|
let(:account) { Fabricate(:account) }
|
||||||
|
let(:preview_card) { Fabricate(:preview_card) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(controller).to receive(:doorkeeper_token) { token }
|
allow(controller).to receive(:doorkeeper_token) { token }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
shared_examples 'forbidden for wrong scope' do |wrong_scope|
|
||||||
|
let(:scopes) { wrong_scope }
|
||||||
|
|
||||||
|
it 'returns http forbidden' do
|
||||||
|
expect(response).to have_http_status(403)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples 'forbidden for wrong role' do |wrong_role|
|
||||||
|
let(:role) { UserRole.find_by(name: wrong_role) }
|
||||||
|
|
||||||
|
it 'returns http forbidden' do
|
||||||
|
expect(response).to have_http_status(403)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'GET #index' do
|
describe 'GET #index' do
|
||||||
it 'returns http success' do
|
it 'returns http success' do
|
||||||
get :index, params: { account_id: account.id, limit: 2 }
|
get :index, params: { account_id: account.id, limit: 2 }
|
||||||
|
@ -20,4 +39,30 @@ describe Api::V1::Admin::Trends::LinksController do
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'POST #approve' do
|
||||||
|
before do
|
||||||
|
post :approve, params: { id: preview_card.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||||
|
it_behaves_like 'forbidden for wrong role', ''
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST #reject' do
|
||||||
|
before do
|
||||||
|
post :reject, params: { id: preview_card.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||||
|
it_behaves_like 'forbidden for wrong role', ''
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,14 +5,33 @@ require 'rails_helper'
|
||||||
describe Api::V1::Admin::Trends::StatusesController do
|
describe Api::V1::Admin::Trends::StatusesController do
|
||||||
render_views
|
render_views
|
||||||
|
|
||||||
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
|
let(:role) { UserRole.find_by(name: 'Admin') }
|
||||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'admin:read') }
|
let(:user) { Fabricate(:user, role: role) }
|
||||||
|
let(:scopes) { 'admin:read admin:write' }
|
||||||
|
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||||
let(:account) { Fabricate(:account) }
|
let(:account) { Fabricate(:account) }
|
||||||
|
let(:status) { Fabricate(:status) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(controller).to receive(:doorkeeper_token) { token }
|
allow(controller).to receive(:doorkeeper_token) { token }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
shared_examples 'forbidden for wrong scope' do |wrong_scope|
|
||||||
|
let(:scopes) { wrong_scope }
|
||||||
|
|
||||||
|
it 'returns http forbidden' do
|
||||||
|
expect(response).to have_http_status(403)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples 'forbidden for wrong role' do |wrong_role|
|
||||||
|
let(:role) { UserRole.find_by(name: wrong_role) }
|
||||||
|
|
||||||
|
it 'returns http forbidden' do
|
||||||
|
expect(response).to have_http_status(403)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'GET #index' do
|
describe 'GET #index' do
|
||||||
it 'returns http success' do
|
it 'returns http success' do
|
||||||
get :index, params: { account_id: account.id, limit: 2 }
|
get :index, params: { account_id: account.id, limit: 2 }
|
||||||
|
@ -20,4 +39,30 @@ describe Api::V1::Admin::Trends::StatusesController do
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'POST #approve' do
|
||||||
|
before do
|
||||||
|
post :approve, params: { id: status.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||||
|
it_behaves_like 'forbidden for wrong role', ''
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST #reject' do
|
||||||
|
before do
|
||||||
|
post :reject, params: { id: status.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||||
|
it_behaves_like 'forbidden for wrong role', ''
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,14 +5,33 @@ require 'rails_helper'
|
||||||
describe Api::V1::Admin::Trends::TagsController do
|
describe Api::V1::Admin::Trends::TagsController do
|
||||||
render_views
|
render_views
|
||||||
|
|
||||||
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
|
let(:role) { UserRole.find_by(name: 'Admin') }
|
||||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'admin:read') }
|
let(:user) { Fabricate(:user, role: role) }
|
||||||
|
let(:scopes) { 'admin:read admin:write' }
|
||||||
|
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||||
let(:account) { Fabricate(:account) }
|
let(:account) { Fabricate(:account) }
|
||||||
|
let(:tag) { Fabricate(:tag) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(controller).to receive(:doorkeeper_token) { token }
|
allow(controller).to receive(:doorkeeper_token) { token }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
shared_examples 'forbidden for wrong scope' do |wrong_scope|
|
||||||
|
let(:scopes) { wrong_scope }
|
||||||
|
|
||||||
|
it 'returns http forbidden' do
|
||||||
|
expect(response).to have_http_status(403)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples 'forbidden for wrong role' do |wrong_role|
|
||||||
|
let(:role) { UserRole.find_by(name: wrong_role) }
|
||||||
|
|
||||||
|
it 'returns http forbidden' do
|
||||||
|
expect(response).to have_http_status(403)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'GET #index' do
|
describe 'GET #index' do
|
||||||
it 'returns http success' do
|
it 'returns http success' do
|
||||||
get :index, params: { account_id: account.id, limit: 2 }
|
get :index, params: { account_id: account.id, limit: 2 }
|
||||||
|
@ -20,4 +39,30 @@ describe Api::V1::Admin::Trends::TagsController do
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'POST #approve' do
|
||||||
|
before do
|
||||||
|
post :approve, params: { id: tag.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||||
|
it_behaves_like 'forbidden for wrong role', ''
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST #reject' do
|
||||||
|
before do
|
||||||
|
post :reject, params: { id: tag.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||||
|
it_behaves_like 'forbidden for wrong role', ''
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -33,27 +33,42 @@ RSpec.describe Auth::RegistrationsController, type: :controller do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET #edit' do
|
describe 'GET #edit' do
|
||||||
it 'returns http success' do
|
before do
|
||||||
request.env['devise.mapping'] = Devise.mappings[:user]
|
request.env['devise.mapping'] = Devise.mappings[:user]
|
||||||
sign_in(Fabricate(:user))
|
sign_in(Fabricate(:user))
|
||||||
get :edit
|
get :edit
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns private cache control header' do
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET #update' do
|
describe 'GET #update' do
|
||||||
it 'returns http success' do
|
let(:user) { Fabricate(:user) }
|
||||||
|
|
||||||
|
before do
|
||||||
request.env['devise.mapping'] = Devise.mappings[:user]
|
request.env['devise.mapping'] = Devise.mappings[:user]
|
||||||
sign_in(Fabricate(:user), scope: :user)
|
sign_in(user, scope: :user)
|
||||||
post :update
|
post :update
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns private cache control headers' do
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
|
end
|
||||||
|
|
||||||
context 'when suspended' do
|
context 'when suspended' do
|
||||||
|
let(:user) { Fabricate(:user, account_attributes: { username: 'test', suspended_at: Time.now.utc }) }
|
||||||
|
|
||||||
it 'returns http forbidden' do
|
it 'returns http forbidden' do
|
||||||
request.env['devise.mapping'] = Devise.mappings[:user]
|
|
||||||
sign_in(Fabricate(:user, account_attributes: { username: 'test', suspended_at: Time.now.utc }), scope: :user)
|
|
||||||
post :update
|
|
||||||
expect(response).to have_http_status(403)
|
expect(response).to have_http_status(403)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,9 +6,25 @@ describe CustomCssController do
|
||||||
render_views
|
render_views
|
||||||
|
|
||||||
describe 'GET #show' do
|
describe 'GET #show' do
|
||||||
it 'returns http success' do
|
before do
|
||||||
get :show
|
get :show
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns public cache control header' do
|
||||||
|
expect(response.headers['Cache-Control']).to include('public')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not set cookies' do
|
||||||
|
expect(response.cookies).to be_empty
|
||||||
|
expect(response.headers['Set-Cookies']).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not set sessions' do
|
||||||
|
expect(session).to be_empty
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,21 +18,27 @@ describe Filters::StatusesController do
|
||||||
|
|
||||||
context 'with a signed in user' do
|
context 'with a signed in user' do
|
||||||
context 'with the filter user signed in' do
|
context 'with the filter user signed in' do
|
||||||
before { sign_in(filter.account.user) }
|
before do
|
||||||
|
sign_in(filter.account.user)
|
||||||
|
get :index, params: { filter_id: filter }
|
||||||
|
end
|
||||||
|
|
||||||
it 'returns http success' do
|
it 'returns http success' do
|
||||||
get :index, params: { filter_id: filter }
|
|
||||||
|
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns private cache control headers' do
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with another user signed in' do
|
context 'with another user signed in' do
|
||||||
before { sign_in(Fabricate(:user)) }
|
before do
|
||||||
|
sign_in(Fabricate(:user))
|
||||||
|
get :index, params: { filter_id: filter }
|
||||||
|
end
|
||||||
|
|
||||||
it 'returns http not found' do
|
it 'returns http not found' do
|
||||||
get :index, params: { filter_id: filter }
|
|
||||||
|
|
||||||
expect(response).to have_http_status(404)
|
expect(response).to have_http_status(404)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,21 +7,28 @@ describe FiltersController do
|
||||||
|
|
||||||
describe 'GET #index' do
|
describe 'GET #index' do
|
||||||
context 'with signed out user' do
|
context 'with signed out user' do
|
||||||
it 'redirects' do
|
before do
|
||||||
get :index
|
get :index
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'redirects' do
|
||||||
expect(response).to be_redirect
|
expect(response).to be_redirect
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with a signed in user' do
|
context 'with a signed in user' do
|
||||||
before { sign_in(Fabricate(:user)) }
|
before do
|
||||||
|
sign_in(Fabricate(:user))
|
||||||
|
get :index
|
||||||
|
end
|
||||||
|
|
||||||
it 'returns http success' do
|
it 'returns http success' do
|
||||||
get :index
|
|
||||||
|
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns private cache control headers' do
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,35 +5,40 @@ require 'rails_helper'
|
||||||
describe InvitesController do
|
describe InvitesController do
|
||||||
render_views
|
render_views
|
||||||
|
|
||||||
|
let(:user) { Fabricate(:user) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
sign_in user
|
sign_in user
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET #index' do
|
describe 'GET #index' do
|
||||||
subject { get :index }
|
before do
|
||||||
|
Fabricate(:invite, user: user)
|
||||||
let(:user) { Fabricate(:user) }
|
end
|
||||||
let!(:invite) { Fabricate(:invite, user: user) }
|
|
||||||
|
|
||||||
context 'when everyone can invite' do
|
context 'when everyone can invite' do
|
||||||
before do
|
before do
|
||||||
UserRole.everyone.update(permissions: UserRole.everyone.permissions | UserRole::FLAGS[:invite_users])
|
UserRole.everyone.update(permissions: UserRole.everyone.permissions | UserRole::FLAGS[:invite_users])
|
||||||
|
get :index
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'renders index page' do
|
it 'returns http success' do
|
||||||
expect(subject).to render_template :index
|
expect(response).to have_http_status(:success)
|
||||||
expect(assigns(:invites)).to include invite
|
end
|
||||||
expect(assigns(:invites).count).to eq 1
|
|
||||||
|
it 'returns private cache control headers' do
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when not everyone can invite' do
|
context 'when not everyone can invite' do
|
||||||
before do
|
before do
|
||||||
UserRole.everyone.update(permissions: UserRole.everyone.permissions & ~UserRole::FLAGS[:invite_users])
|
UserRole.everyone.update(permissions: UserRole.everyone.permissions & ~UserRole::FLAGS[:invite_users])
|
||||||
|
get :index
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns 403' do
|
it 'returns http forbidden' do
|
||||||
expect(subject).to have_http_status 403
|
expect(response).to have_http_status(403)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -42,8 +47,6 @@ describe InvitesController do
|
||||||
subject { post :create, params: { invite: { max_uses: '10', expires_in: 1800 } } }
|
subject { post :create, params: { invite: { max_uses: '10', expires_in: 1800 } } }
|
||||||
|
|
||||||
context 'when everyone can invite' do
|
context 'when everyone can invite' do
|
||||||
let(:user) { Fabricate(:user) }
|
|
||||||
|
|
||||||
before do
|
before do
|
||||||
UserRole.everyone.update(permissions: UserRole.everyone.permissions | UserRole::FLAGS[:invite_users])
|
UserRole.everyone.update(permissions: UserRole.everyone.permissions | UserRole::FLAGS[:invite_users])
|
||||||
end
|
end
|
||||||
|
@ -56,26 +59,28 @@ describe InvitesController do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when not everyone can invite' do
|
context 'when not everyone can invite' do
|
||||||
let(:user) { Fabricate(:user) }
|
|
||||||
|
|
||||||
before do
|
before do
|
||||||
UserRole.everyone.update(permissions: UserRole.everyone.permissions & ~UserRole::FLAGS[:invite_users])
|
UserRole.everyone.update(permissions: UserRole.everyone.permissions & ~UserRole::FLAGS[:invite_users])
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns 403' do
|
it 'returns http forbidden' do
|
||||||
expect(subject).to have_http_status 403
|
expect(subject).to have_http_status(403)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'DELETE #create' do
|
describe 'DELETE #create' do
|
||||||
subject { delete :destroy, params: { id: invite.id } }
|
let(:invite) { Fabricate(:invite, user: user, expires_at: nil) }
|
||||||
|
|
||||||
let(:user) { Fabricate(:user) }
|
before do
|
||||||
let!(:invite) { Fabricate(:invite, user: user, expires_at: nil) }
|
delete :destroy, params: { id: invite.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'redirects' do
|
||||||
|
expect(response).to redirect_to invites_path
|
||||||
|
end
|
||||||
|
|
||||||
it 'expires invite' do
|
it 'expires invite' do
|
||||||
expect(subject).to redirect_to invites_path
|
|
||||||
expect(invite.reload).to be_expired
|
expect(invite.reload).to be_expired
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,11 +7,24 @@ describe ManifestsController do
|
||||||
|
|
||||||
describe 'GET #show' do
|
describe 'GET #show' do
|
||||||
before do
|
before do
|
||||||
get :show, format: :json
|
get :show
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns http success' do
|
it 'returns http success' do
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns public cache control header' do
|
||||||
|
expect(response.headers['Cache-Control']).to include('public')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not set cookies' do
|
||||||
|
expect(response.cookies).to be_empty
|
||||||
|
expect(response.headers['Set-Cookies']).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not set sessions' do
|
||||||
|
expect(session).to be_empty
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -31,6 +31,11 @@ RSpec.describe Oauth::AuthorizationsController, type: :controller do
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns private cache control headers' do
|
||||||
|
subject
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
|
end
|
||||||
|
|
||||||
it 'gives options to authorize and deny' do
|
it 'gives options to authorize and deny' do
|
||||||
subject
|
subject
|
||||||
expect(response.body).to match(/Authorize/)
|
expect(response.body).to match(/Authorize/)
|
||||||
|
|
|
@ -27,6 +27,11 @@ describe Oauth::AuthorizedApplicationsController do
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns private cache control headers' do
|
||||||
|
subject
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
|
end
|
||||||
|
|
||||||
include_examples 'stores location for user'
|
include_examples 'stores location for user'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -7,42 +7,39 @@ describe RelationshipsController do
|
||||||
|
|
||||||
let(:user) { Fabricate(:user) }
|
let(:user) { Fabricate(:user) }
|
||||||
|
|
||||||
shared_examples 'authenticate user' do
|
|
||||||
it 'redirects when not signed in' do
|
|
||||||
expect(subject).to redirect_to '/auth/sign_in'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe 'GET #show' do
|
describe 'GET #show' do
|
||||||
subject { get :show, params: { page: 2, relationship: 'followed_by' } }
|
context 'when signed in' do
|
||||||
|
before do
|
||||||
it 'assigns @accounts' do
|
|
||||||
Fabricate(:account, domain: 'old').follow!(user.account)
|
|
||||||
Fabricate(:account, domain: 'recent').follow!(user.account)
|
|
||||||
|
|
||||||
sign_in user, scope: :user
|
sign_in user, scope: :user
|
||||||
subject
|
get :show, params: { page: 2, relationship: 'followed_by' }
|
||||||
|
|
||||||
assigned = assigns(:accounts).per(1).to_a
|
|
||||||
expect(assigned.size).to eq 1
|
|
||||||
expect(assigned[0].domain).to eq 'old'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns http success' do
|
it 'returns http success' do
|
||||||
sign_in user, scope: :user
|
|
||||||
subject
|
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
include_examples 'authenticate user'
|
it 'returns private cache control headers' do
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when not signed in' do
|
||||||
|
before do
|
||||||
|
get :show, params: { page: 2, relationship: 'followed_by' }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'redirects when not signed in' do
|
||||||
|
expect(response).to redirect_to '/auth/sign_in'
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'PATCH #update' do
|
describe 'PATCH #update' do
|
||||||
let(:poopfeast) { Fabricate(:account, username: 'poopfeast', domain: 'example.com') }
|
let(:alice) { Fabricate(:account, username: 'alice', domain: 'example.com') }
|
||||||
|
|
||||||
shared_examples 'redirects back to followers page' do
|
shared_examples 'redirects back to followers page' do
|
||||||
it 'redirects back to followers page' do
|
it 'redirects back to followers page' do
|
||||||
poopfeast.follow!(user.account)
|
alice.follow!(user.account)
|
||||||
|
|
||||||
sign_in user, scope: :user
|
sign_in user, scope: :user
|
||||||
subject
|
subject
|
||||||
|
@ -58,27 +55,36 @@ describe RelationshipsController do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when select parameter is provided' do
|
context 'when select parameter is provided' do
|
||||||
subject { patch :update, params: { form_account_batch: { account_ids: [poopfeast.id] }, remove_domains_from_followers: '' } }
|
subject { patch :update, params: { form_account_batch: { account_ids: [alice.id] }, remove_domains_from_followers: '' } }
|
||||||
|
|
||||||
it 'soft-blocks followers from selected domains' do
|
it 'soft-blocks followers from selected domains' do
|
||||||
poopfeast.follow!(user.account)
|
alice.follow!(user.account)
|
||||||
|
|
||||||
sign_in user, scope: :user
|
sign_in user, scope: :user
|
||||||
subject
|
subject
|
||||||
|
|
||||||
expect(poopfeast.following?(user.account)).to be false
|
expect(alice.following?(user.account)).to be false
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not unfollow users from selected domains' do
|
it 'does not unfollow users from selected domains' do
|
||||||
user.account.follow!(poopfeast)
|
user.account.follow!(alice)
|
||||||
|
|
||||||
sign_in user, scope: :user
|
sign_in user, scope: :user
|
||||||
subject
|
subject
|
||||||
|
|
||||||
expect(user.account.following?(poopfeast)).to be true
|
expect(user.account.following?(alice)).to be true
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when not signed in' do
|
||||||
|
before do
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'redirects when not signed in' do
|
||||||
|
expect(response).to redirect_to '/auth/sign_in'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
include_examples 'authenticate user'
|
|
||||||
include_examples 'redirects back to followers page'
|
include_examples 'redirects back to followers page'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,10 +13,17 @@ describe Settings::AliasesController do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET #index' do
|
describe 'GET #index' do
|
||||||
it 'returns http success' do
|
before do
|
||||||
get :index
|
get :index
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns private cache control headers' do
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'POST #create' do
|
describe 'POST #create' do
|
||||||
|
|
|
@ -13,13 +13,17 @@ describe Settings::ApplicationsController do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET #index' do
|
describe 'GET #index' do
|
||||||
let!(:other_app) { Fabricate(:application) }
|
before do
|
||||||
|
Fabricate(:application)
|
||||||
it 'shows apps' do
|
|
||||||
get :index
|
get :index
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
expect(assigns(:applications)).to include(app)
|
end
|
||||||
expect(assigns(:applications)).to_not include(other_app)
|
|
||||||
|
it 'returns private cache control headers' do
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -11,20 +11,27 @@ describe Settings::DeletesController do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
sign_in user, scope: :user
|
sign_in user, scope: :user
|
||||||
|
get :show
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'renders confirmation page' do
|
it 'renders confirmation page' do
|
||||||
get :show
|
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns private cache control headers' do
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
|
end
|
||||||
|
|
||||||
context 'when suspended' do
|
context 'when suspended' do
|
||||||
let(:user) { Fabricate(:user, account_attributes: { suspended_at: Time.now.utc }) }
|
let(:user) { Fabricate(:user, account_attributes: { suspended_at: Time.now.utc }) }
|
||||||
|
|
||||||
it 'returns http forbidden' do
|
it 'returns http forbidden' do
|
||||||
get :show
|
|
||||||
expect(response).to have_http_status(403)
|
expect(response).to have_http_status(403)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns private cache control headers' do
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -11,16 +11,16 @@ describe Settings::ExportsController do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
sign_in user, scope: :user
|
sign_in user, scope: :user
|
||||||
|
get :show
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'renders export' do
|
it 'returns http success' do
|
||||||
get :show
|
|
||||||
|
|
||||||
export = assigns(:export)
|
|
||||||
expect(export).to be_instance_of Export
|
|
||||||
expect(export.account).to eq user.account
|
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns private cache control headers' do
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when not signed in' do
|
context 'when not signed in' do
|
||||||
|
|
|
@ -10,10 +10,17 @@ RSpec.describe Settings::ImportsController, type: :controller do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET #show' do
|
describe 'GET #show' do
|
||||||
it 'returns http success' do
|
before do
|
||||||
get :show
|
get :show
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns private cache control headers' do
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'POST #create' do
|
describe 'POST #create' do
|
||||||
|
|
|
@ -12,9 +12,16 @@ describe Settings::LoginActivitiesController do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET #index' do
|
describe 'GET #index' do
|
||||||
it 'returns http success' do
|
before do
|
||||||
get :index
|
get :index
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns private cache control headers' do
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,10 +12,17 @@ describe Settings::Migration::RedirectsController do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET #new' do
|
describe 'GET #new' do
|
||||||
it 'returns http success' do
|
before do
|
||||||
get :new
|
get :new
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns private cache control headers' do
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'POST #create' do
|
describe 'POST #create' do
|
||||||
|
|
|
@ -12,11 +12,17 @@ describe Settings::Preferences::AppearanceController do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET #show' do
|
describe 'GET #show' do
|
||||||
it 'returns http success' do
|
before do
|
||||||
get :show
|
get :show
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns private cache control headers' do
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'PUT #update' do
|
describe 'PUT #update' do
|
||||||
|
|
|
@ -12,10 +12,17 @@ describe Settings::Preferences::NotificationsController do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET #show' do
|
describe 'GET #show' do
|
||||||
it 'returns http success' do
|
before do
|
||||||
get :show
|
get :show
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns private cache control headers' do
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'PUT #update' do
|
describe 'PUT #update' do
|
||||||
|
|
|
@ -12,10 +12,17 @@ describe Settings::Preferences::OtherController do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET #show' do
|
describe 'GET #show' do
|
||||||
it 'returns http success' do
|
before do
|
||||||
get :show
|
get :show
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns private cache control headers' do
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'PUT #update' do
|
describe 'PUT #update' do
|
||||||
|
|
|
@ -13,10 +13,17 @@ RSpec.describe Settings::ProfilesController, type: :controller do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET #show' do
|
describe 'GET #show' do
|
||||||
it 'returns http success' do
|
before do
|
||||||
get :show
|
get :show
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns private cache control headers' do
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'PUT #update' do
|
describe 'PUT #update' do
|
||||||
|
|
|
@ -26,23 +26,25 @@ describe Settings::TwoFactorAuthenticationMethodsController do
|
||||||
describe 'when user has enabled otp' do
|
describe 'when user has enabled otp' do
|
||||||
before do
|
before do
|
||||||
user.update(otp_required_for_login: true)
|
user.update(otp_required_for_login: true)
|
||||||
|
get :index
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns http success' do
|
it 'returns http success' do
|
||||||
get :index
|
|
||||||
|
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns private cache control headers' do
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'when user has not enabled otp' do
|
describe 'when user has not enabled otp' do
|
||||||
before do
|
before do
|
||||||
user.update(otp_required_for_login: false)
|
user.update(otp_required_for_login: false)
|
||||||
|
get :index
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'redirects to enable otp' do
|
it 'redirects to enable otp' do
|
||||||
get :index
|
|
||||||
|
|
||||||
expect(response).to redirect_to(settings_otp_authentication_path)
|
expect(response).to redirect_to(settings_otp_authentication_path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,19 +11,32 @@ RSpec.describe StatusesCleanupController, type: :controller do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET #show' do
|
describe 'GET #show' do
|
||||||
it 'returns http success' do
|
before do
|
||||||
get :show
|
get :show
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns private cache control headers' do
|
||||||
|
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'PUT #update' do
|
describe 'PUT #update' do
|
||||||
it 'updates the account status cleanup policy' do
|
before do
|
||||||
put :update, params: { account_statuses_cleanup_policy: { enabled: true, min_status_age: 2.weeks.seconds, keep_direct: false, keep_polls: true } }
|
put :update, params: { account_statuses_cleanup_policy: { enabled: true, min_status_age: 2.weeks.seconds, keep_direct: false, keep_polls: true } }
|
||||||
expect(response).to redirect_to(statuses_cleanup_path)
|
end
|
||||||
|
|
||||||
|
it 'updates the account status cleanup policy' do
|
||||||
expect(@user.account.statuses_cleanup_policy.enabled).to be true
|
expect(@user.account.statuses_cleanup_policy.enabled).to be true
|
||||||
expect(@user.account.statuses_cleanup_policy.keep_direct).to be false
|
expect(@user.account.statuses_cleanup_policy.keep_direct).to be false
|
||||||
expect(@user.account.statuses_cleanup_policy.keep_polls).to be true
|
expect(@user.account.statuses_cleanup_policy.keep_polls).to be true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'redirects' do
|
||||||
|
expect(response).to redirect_to(statuses_cleanup_path)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,6 +15,10 @@ describe StatusesController do
|
||||||
expect(session).to be_empty
|
expect(session).to be_empty
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns Vary header' do
|
||||||
|
expect(response.headers['Vary']).to include 'Accept'
|
||||||
|
end
|
||||||
|
|
||||||
it 'returns public Cache-Control header' do
|
it 'returns public Cache-Control header' do
|
||||||
expect(response.headers['Cache-Control']).to include 'public'
|
expect(response.headers['Cache-Control']).to include 'public'
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,21 +6,50 @@ RSpec.describe TagsController, type: :controller do
|
||||||
render_views
|
render_views
|
||||||
|
|
||||||
describe 'GET #show' do
|
describe 'GET #show' do
|
||||||
let!(:tag) { Fabricate(:tag, name: 'test') }
|
let(:format) { 'html' }
|
||||||
let!(:local) { Fabricate(:status, tags: [tag], text: 'local #test') }
|
let(:tag) { Fabricate(:tag, name: 'test') }
|
||||||
let!(:remote) { Fabricate(:status, tags: [tag], text: 'remote #test', account: Fabricate(:account, domain: 'remote')) }
|
let(:tag_name) { tag&.name }
|
||||||
let!(:late) { Fabricate(:status, tags: [tag], text: 'late #test') }
|
|
||||||
|
before do
|
||||||
|
get :show, params: { id: tag_name, format: format }
|
||||||
|
end
|
||||||
|
|
||||||
context 'when tag exists' do
|
context 'when tag exists' do
|
||||||
|
context 'when requested as HTML' do
|
||||||
it 'returns http success' do
|
it 'returns http success' do
|
||||||
get :show, params: { id: 'test', max_id: late.id }
|
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns Vary header' do
|
||||||
|
expect(response.headers['Vary']).to eq 'Accept'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns public Cache-Control header' do
|
||||||
|
expect(response.headers['Cache-Control']).to include 'public'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when requested as JSON' do
|
||||||
|
let(:format) { 'json' }
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns Vary header' do
|
||||||
|
expect(response.headers['Vary']).to eq 'Accept'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns public Cache-Control header' do
|
||||||
|
expect(response.headers['Cache-Control']).to include 'public'
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when tag does not exist' do
|
context 'when tag does not exist' do
|
||||||
|
let(:tag_name) { 'hoge' }
|
||||||
|
|
||||||
it 'returns http not found' do
|
it 'returns http not found' do
|
||||||
get :show, params: { id: 'none' }
|
|
||||||
expect(response).to have_http_status(404)
|
expect(response).to have_http_status(404)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
34
yarn.lock
34
yarn.lock
|
@ -6032,10 +6032,10 @@ http-errors@~1.6.2:
|
||||||
setprototypeof "1.1.0"
|
setprototypeof "1.1.0"
|
||||||
statuses ">= 1.4.0 < 2"
|
statuses ">= 1.4.0 < 2"
|
||||||
|
|
||||||
http-link-header@^1.1.0:
|
http-link-header@^1.1.1:
|
||||||
version "1.1.0"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/http-link-header/-/http-link-header-1.1.0.tgz#a1ca87efdbcb7778d8d0d4525de1e6964ec1f129"
|
resolved "https://registry.yarnpkg.com/http-link-header/-/http-link-header-1.1.1.tgz#f0e6971b0ed86e858d2077066ecb7ba4f2e50de9"
|
||||||
integrity sha512-pj6N1yxOz/ANO8HHsWGg/OoIL1kmRYvQnXQ7PIRpgp+15AnEsRH8fmIJE6D1OdWG2Bov+BJHVla1fFXxg1JbbA==
|
integrity sha512-mW3N/rTYpCn99s1do0zx6nzFZSwLH9HGfUM4ZqLWJ16ylmYaC2v5eYGqrNTQlByx8AzUgGI+V/32gXPugs1+Sw==
|
||||||
|
|
||||||
http-parser-js@>=0.5.1:
|
http-parser-js@>=0.5.1:
|
||||||
version "0.5.3"
|
version "0.5.3"
|
||||||
|
@ -8005,10 +8005,10 @@ nan@^2.12.1:
|
||||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01"
|
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01"
|
||||||
integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==
|
integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==
|
||||||
|
|
||||||
nanoid@^3.3.4:
|
nanoid@^3.3.6:
|
||||||
version "3.3.4"
|
version "3.3.6"
|
||||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
|
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c"
|
||||||
integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
|
integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==
|
||||||
|
|
||||||
nanomatch@^1.2.9:
|
nanomatch@^1.2.9:
|
||||||
version "1.2.13"
|
version "1.2.13"
|
||||||
|
@ -9007,12 +9007,12 @@ postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0:
|
||||||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
|
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
|
||||||
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
||||||
|
|
||||||
postcss@^8.2.15, postcss@^8.4.21:
|
postcss@^8.2.15, postcss@^8.4.21, postcss@^8.4.22:
|
||||||
version "8.4.21"
|
version "8.4.22"
|
||||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4"
|
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.22.tgz#c29e6776b60ab3af602d4b513d5bd2ff9aa85dc1"
|
||||||
integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==
|
integrity sha512-XseknLAfRHzVWjCEtdviapiBtfLdgyzExD50Rg2ePaucEesyh8Wv4VPdW0nbyDa1ydbrAxV19jvMT4+LFmcNUA==
|
||||||
dependencies:
|
dependencies:
|
||||||
nanoid "^3.3.4"
|
nanoid "^3.3.6"
|
||||||
picocolors "^1.0.0"
|
picocolors "^1.0.0"
|
||||||
source-map-js "^1.0.2"
|
source-map-js "^1.0.2"
|
||||||
|
|
||||||
|
@ -9789,10 +9789,10 @@ requires-port@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
||||||
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
|
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
|
||||||
|
|
||||||
reselect@^4.1.7:
|
reselect@^4.1.8:
|
||||||
version "4.1.7"
|
version "4.1.8"
|
||||||
resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.7.tgz#56480d9ff3d3188970ee2b76527bd94a95567a42"
|
resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.8.tgz#3f5dc671ea168dccdeb3e141236f69f02eaec524"
|
||||||
integrity sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A==
|
integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==
|
||||||
|
|
||||||
resolve-cwd@^2.0.0:
|
resolve-cwd@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue