~cytrogen/masto-fe

4db8230194258a9a1c3d17d7261608515f3f2067 — Robert R George 3 years ago 1153531
Add trend management to admin API (#24257)

A app/controllers/api/v1/admin/trends/links/preview_card_providers_controller.rb => app/controllers/api/v1/admin/trends/links/preview_card_providers_controller.rb +72 -0
@@ 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

M app/controllers/api/v1/admin/trends/links_controller.rb => app/controllers/api/v1/admin/trends/links_controller.rb +30 -1
@@ 1,7 1,36 @@
# frozen_string_literal: true

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


M app/controllers/api/v1/admin/trends/statuses_controller.rb => app/controllers/api/v1/admin/trends/statuses_controller.rb +30 -1
@@ 1,7 1,36 @@
# frozen_string_literal: true

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


M app/controllers/api/v1/admin/trends/tags_controller.rb => app/controllers/api/v1/admin/trends/tags_controller.rb +22 -1
@@ 1,7 1,12 @@
# frozen_string_literal: true

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
    if current_user&.can?(:manage_taxonomies)


@@ 11,6 16,22 @@ class Api::V1::Admin::Trends::TagsController < Api::V1::Trends::TagsController
    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

  def enabled?

M app/models/preview_card_provider.rb => app/models/preview_card_provider.rb +1 -0
@@ 18,6 18,7 @@
#

class PreviewCardProvider < ApplicationRecord
  include Paginable
  include DomainNormalizable
  include Attachmentable


A app/serializers/rest/admin/trends/link_serializer.rb => app/serializers/rest/admin/trends/link_serializer.rb +9 -0
@@ 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

A app/serializers/rest/admin/trends/links/preview_card_provider_serializer.rb => app/serializers/rest/admin/trends/links/preview_card_provider_serializer.rb +10 -0
@@ 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

A app/serializers/rest/admin/trends/status_serializer.rb => app/serializers/rest/admin/trends/status_serializer.rb +9 -0
@@ 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

M config/routes.rb => config/routes.rb +27 -3
@@ 660,9 660,33 @@ Rails.application.routes.draw do
        resources :ip_blocks, only: [:index, :show, :update, :create, :destroy]

        namespace :trends do
          resources :tags, only: [:index]
          resources :links, only: [:index]
          resources :statuses, only: [:index]
          resources :tags, only: [:index] do
            member do
              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

        post :measures, to: 'measures#create'

A spec/controllers/api/v1/admin/trends/links/preview_card_providers_controller_spec.rb => spec/controllers/api/v1/admin/trends/links/preview_card_providers_controller_spec.rb +68 -0
@@ 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

M spec/controllers/api/v1/admin/trends/links_controller_spec.rb => spec/controllers/api/v1/admin/trends/links_controller_spec.rb +47 -2
@@ 5,14 5,33 @@ require 'rails_helper'
describe Api::V1::Admin::Trends::LinksController do
  render_views

  let(:user)    { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
  let(:token)   { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'admin:read') }
  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) { Fabricate(:preview_card) }

  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 }


@@ 20,4 39,30 @@ describe Api::V1::Admin::Trends::LinksController do
      expect(response).to have_http_status(200)
    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

M spec/controllers/api/v1/admin/trends/statuses_controller_spec.rb => spec/controllers/api/v1/admin/trends/statuses_controller_spec.rb +47 -2
@@ 5,14 5,33 @@ require 'rails_helper'
describe Api::V1::Admin::Trends::StatusesController do
  render_views

  let(:user)    { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
  let(:token)   { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'admin:read') }
  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(:status)  { Fabricate(:status) }

  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 }


@@ 20,4 39,30 @@ describe Api::V1::Admin::Trends::StatusesController do
      expect(response).to have_http_status(200)
    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

M spec/controllers/api/v1/admin/trends/tags_controller_spec.rb => spec/controllers/api/v1/admin/trends/tags_controller_spec.rb +47 -2
@@ 5,14 5,33 @@ require 'rails_helper'
describe Api::V1::Admin::Trends::TagsController do
  render_views

  let(:user)    { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
  let(:token)   { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'admin:read') }
  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(:tag)     { Fabricate(:tag) }

  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 }


@@ 20,4 39,30 @@ describe Api::V1::Admin::Trends::TagsController do
      expect(response).to have_http_status(200)
    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