Add trend management to admin API (#24257)

pull/2192/head
Robert R George 2023-04-18 02:33:30 -07:00 committed by GitHub
parent 1153531e92
commit 4db8230194
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 419 additions and 12 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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?

View File

@ -18,6 +18,7 @@
# #
class PreviewCardProvider < ApplicationRecord class PreviewCardProvider < ApplicationRecord
include Paginable
include DomainNormalizable include DomainNormalizable
include Attachmentable include Attachmentable

View 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

View File

@ -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

View 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

View File

@ -660,9 +660,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'

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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