fix: require admin for dashboard app mutations (#14831)
## Summary Restricts account-wide Dashboard App creation, updates, and deletion to administrators while keeping read access available to authenticated account users. ## Why Dashboard Apps are account-level integrations displayed in conversation views. Agents should be able to use them, but only administrators should be able to change their configuration. ## What changed - authorize Dashboard App actions through `DashboardAppPolicy` - allow index and show access for authenticated account users - restrict create, update, and destroy actions to administrators - add request coverage for administrator and agent mutation behavior ## Validation `bundle exec rspec spec/controllers/api/v1/accounts/dashboard_apps_controller_spec.rb` 17 examples, 0 failures. `bundle exec rubocop app/controllers/api/v1/accounts/dashboard_apps_controller.rb app/policies/dashboard_app_policy.rb` 2 files inspected, no offenses detected. --------- Co-authored-by: Gaurav Singhal <gauravsinghal@Gauravs-Mac-mini.local> Co-authored-by: Sojan Jose <sojan@pepalo.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
class Api::V1::Accounts::DashboardAppsController < Api::V1::Accounts::BaseController
|
class Api::V1::Accounts::DashboardAppsController < Api::V1::Accounts::BaseController
|
||||||
|
before_action :check_authorization
|
||||||
before_action :fetch_dashboard_apps, except: [:create]
|
before_action :fetch_dashboard_apps, except: [:create]
|
||||||
before_action :fetch_dashboard_app, only: [:show, :update, :destroy]
|
before_action :fetch_dashboard_app, only: [:show, :update, :destroy]
|
||||||
|
|
||||||
|
|||||||
21
app/policies/dashboard_app_policy.rb
Normal file
21
app/policies/dashboard_app_policy.rb
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
class DashboardAppPolicy < ApplicationPolicy
|
||||||
|
def index?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def show?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def create?
|
||||||
|
@account_user.administrator?
|
||||||
|
end
|
||||||
|
|
||||||
|
def update?
|
||||||
|
@account_user.administrator?
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy?
|
||||||
|
@account_user.administrator?
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -70,8 +70,8 @@ RSpec.describe 'DashboardAppsController', type: :request do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when it is an authenticated user' do
|
context 'when it is an authenticated administrator' do
|
||||||
let(:user) { create(:user, account: account) }
|
let(:user) { create(:user, account: account, role: :administrator) }
|
||||||
|
|
||||||
it 'creates the dashboard app' do
|
it 'creates the dashboard app' do
|
||||||
expect do
|
expect do
|
||||||
@@ -130,11 +130,26 @@ RSpec.describe 'DashboardAppsController', type: :request do
|
|||||||
expect(response).to have_http_status(:unprocessable_entity)
|
expect(response).to have_http_status(:unprocessable_entity)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when it is an authenticated agent' do
|
||||||
|
let(:agent) { create(:user, account: account, role: :agent) }
|
||||||
|
|
||||||
|
it 'does not create account-wide dashboard apps' do
|
||||||
|
expect do
|
||||||
|
post "/api/v1/accounts/#{account.id}/dashboard_apps",
|
||||||
|
headers: agent.create_new_auth_token,
|
||||||
|
params: payload,
|
||||||
|
as: :json
|
||||||
|
end.not_to change(DashboardApp, :count)
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:unauthorized)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'PATCH /api/v1/accounts/{account.id}/dashboard_apps/:id' do
|
describe 'PATCH /api/v1/accounts/{account.id}/dashboard_apps/:id' do
|
||||||
let(:payload) { { dashboard_app: { title: 'CRM Dashboard', content: [{ type: 'frame', url: 'https://link.com' }] } } }
|
let(:payload) { { dashboard_app: { title: 'CRM Dashboard', content: [{ type: 'frame', url: 'https://link.com' }] } } }
|
||||||
let(:user) { create(:user, account: account) }
|
let(:user) { create(:user, account: account, role: :administrator) }
|
||||||
let!(:dashboard_app) { create(:dashboard_app, user: user, account: account) }
|
let!(:dashboard_app) { create(:dashboard_app, user: user, account: account) }
|
||||||
|
|
||||||
context 'when it is an unauthenticated user' do
|
context 'when it is an unauthenticated user' do
|
||||||
@@ -160,10 +175,24 @@ RSpec.describe 'DashboardAppsController', type: :request do
|
|||||||
expect(json_response['content'][0]['type']).to eq payload[:dashboard_app][:content][0][:type]
|
expect(json_response['content'][0]['type']).to eq payload[:dashboard_app][:content][0][:type]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when it is an authenticated agent' do
|
||||||
|
let(:agent) { create(:user, account: account, role: :agent) }
|
||||||
|
|
||||||
|
it 'does not update account-wide dashboard apps' do
|
||||||
|
patch "/api/v1/accounts/#{account.id}/dashboard_apps/#{dashboard_app.id}",
|
||||||
|
headers: agent.create_new_auth_token,
|
||||||
|
params: payload,
|
||||||
|
as: :json
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:unauthorized)
|
||||||
|
expect(dashboard_app.reload.title).not_to eq('CRM Dashboard')
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'DELETE /api/v1/accounts/{account.id}/dashboard_apps/:id' do
|
describe 'DELETE /api/v1/accounts/{account.id}/dashboard_apps/:id' do
|
||||||
let(:user) { create(:user, account: account) }
|
let(:user) { create(:user, account: account, role: :administrator) }
|
||||||
let!(:dashboard_app) { create(:dashboard_app, user: user, account: account) }
|
let!(:dashboard_app) { create(:dashboard_app, user: user, account: account) }
|
||||||
|
|
||||||
context 'when it is an unauthenticated user' do
|
context 'when it is an unauthenticated user' do
|
||||||
@@ -182,5 +211,18 @@ RSpec.describe 'DashboardAppsController', type: :request do
|
|||||||
expect(user.dashboard_apps.count).to be 0
|
expect(user.dashboard_apps.count).to be 0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when it is an authenticated agent' do
|
||||||
|
let(:agent) { create(:user, account: account, role: :agent) }
|
||||||
|
|
||||||
|
it 'does not delete account-wide dashboard apps' do
|
||||||
|
delete "/api/v1/accounts/#{account.id}/dashboard_apps/#{dashboard_app.id}",
|
||||||
|
headers: agent.create_new_auth_token,
|
||||||
|
as: :json
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:unauthorized)
|
||||||
|
expect(DashboardApp.exists?(dashboard_app.id)).to be(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user