fix(captain): allow agents to manage FAQs
This commit is contained in:
parent
d670c5644b
commit
689cc114f8
@ -1,6 +1,6 @@
|
|||||||
class Api::V1::Accounts::Captain::AssistantResponsesController < Api::V1::Accounts::BaseController
|
class Api::V1::Accounts::Captain::AssistantResponsesController < Api::V1::Accounts::BaseController
|
||||||
before_action :current_account
|
before_action :current_account
|
||||||
before_action -> { check_authorization(Captain::Assistant) }
|
before_action -> { check_authorization(Captain::AssistantResponse) }
|
||||||
|
|
||||||
before_action :set_current_page, only: [:index]
|
before_action :set_current_page, only: [:index]
|
||||||
before_action :set_assistant, only: [:create]
|
before_action :set_assistant, only: [:create]
|
||||||
@ -21,6 +21,7 @@ class Api::V1::Accounts::Captain::AssistantResponsesController < Api::V1::Accoun
|
|||||||
@response = Current.account.captain_assistant_responses.new(response_params)
|
@response = Current.account.captain_assistant_responses.new(response_params)
|
||||||
@response.documentable = Current.user
|
@response.documentable = Current.user
|
||||||
@response.save!
|
@response.save!
|
||||||
|
Captain::Llm::UpdateEmbeddingJob.perform_now(@response, "#{@response.question}: #{@response.answer}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@ -28,7 +29,7 @@ class Api::V1::Accounts::Captain::AssistantResponsesController < Api::V1::Accoun
|
|||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
@response.destroy!
|
@response.destroy
|
||||||
head :no_content
|
head :no_content
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
class Api::V1::Accounts::Captain::BulkActionsController < Api::V1::Accounts::BaseController
|
class Api::V1::Accounts::Captain::BulkActionsController < Api::V1::Accounts::BaseController
|
||||||
before_action :current_account
|
before_action :current_account
|
||||||
before_action -> { check_authorization(Captain::Assistant) }
|
before_action -> { check_authorization(Captain::AssistantResponse) }
|
||||||
before_action :validate_params
|
before_action :validate_params
|
||||||
before_action :type_matches?
|
before_action :type_matches?
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ class Api::V1::Accounts::Captain::BulkActionsController < Api::V1::Accounts::Bas
|
|||||||
end
|
end
|
||||||
|
|
||||||
def type_matches?
|
def type_matches?
|
||||||
return false if MODEL_TYPE.include?(params[:type])
|
return if MODEL_TYPE.include?(params[:type])
|
||||||
|
|
||||||
render json: { success: false }, status: :unprocessable_entity
|
render json: { success: false }, status: :unprocessable_entity
|
||||||
end
|
end
|
||||||
@ -37,7 +37,7 @@ class Api::V1::Accounts::Captain::BulkActionsController < Api::V1::Accounts::Bas
|
|||||||
|
|
||||||
case params[:fields][:status]
|
case params[:fields][:status]
|
||||||
when 'approve'
|
when 'approve'
|
||||||
responses.pending.update!(status: 'approved')
|
responses.pending.update(status: 'approved')
|
||||||
responses
|
responses
|
||||||
when 'delete'
|
when 'delete'
|
||||||
responses.destroy_all
|
responses.destroy_all
|
||||||
|
|||||||
33
enterprise/app/policies/captain/assistant_response_policy.rb
Normal file
33
enterprise/app/policies/captain/assistant_response_policy.rb
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
class Captain::AssistantResponsePolicy < ApplicationPolicy
|
||||||
|
def index?
|
||||||
|
@account_user.administrator? || @account_user.agent?
|
||||||
|
end
|
||||||
|
|
||||||
|
def show?
|
||||||
|
index?
|
||||||
|
end
|
||||||
|
|
||||||
|
def create?
|
||||||
|
manage?
|
||||||
|
end
|
||||||
|
|
||||||
|
def update?
|
||||||
|
manage?
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy?
|
||||||
|
manage?
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def manage?
|
||||||
|
return true if @account_user.administrator?
|
||||||
|
|
||||||
|
if @account_user.custom_role.present?
|
||||||
|
return @account_user.custom_role.permissions.include?('knowledge_base_manage')
|
||||||
|
end
|
||||||
|
|
||||||
|
@account_user.agent?
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -6,6 +6,7 @@ RSpec.describe 'Api::V1::Accounts::Captain::AssistantResponses', type: :request
|
|||||||
let(:document) { create(:captain_document, assistant: assistant, account: account) }
|
let(:document) { create(:captain_document, assistant: assistant, account: account) }
|
||||||
let(:admin) { create(:user, account: account, role: :administrator) }
|
let(:admin) { create(:user, account: account, role: :administrator) }
|
||||||
let(:agent) { create(:user, account: account, role: :agent) }
|
let(:agent) { create(:user, account: account, role: :agent) }
|
||||||
|
let(:agent_with_custom_role) { create(:user, account: account, role: :agent) }
|
||||||
let(:another_assistant) { create(:captain_assistant, account: account) }
|
let(:another_assistant) { create(:captain_assistant, account: account) }
|
||||||
let(:another_document) { create(:captain_document, account: account, assistant: assistant) }
|
let(:another_document) { create(:captain_document, account: account, assistant: assistant) }
|
||||||
|
|
||||||
@ -179,6 +180,46 @@ RSpec.describe 'Api::V1::Accounts::Captain::AssistantResponses', type: :request
|
|||||||
expect(json_response[:answer]).to eq('Test answer')
|
expect(json_response[:answer]).to eq('Test answer')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'creates a new response if the user is an agent' do
|
||||||
|
expect do
|
||||||
|
post "/api/v1/accounts/#{account.id}/captain/assistant_responses",
|
||||||
|
params: valid_params,
|
||||||
|
headers: agent.create_new_auth_token,
|
||||||
|
as: :json
|
||||||
|
end.to change(Captain::AssistantResponse, :count).by(1)
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
expect(json_response[:question]).to eq('Test question?')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'creates a new response if the user has a custom role with knowledge base permission' do
|
||||||
|
custom_role = create(:custom_role, account: account, permissions: ['knowledge_base_manage'])
|
||||||
|
AccountUser.find_by!(account: account, user: agent_with_custom_role).update!(custom_role: custom_role)
|
||||||
|
|
||||||
|
expect do
|
||||||
|
post "/api/v1/accounts/#{account.id}/captain/assistant_responses",
|
||||||
|
params: valid_params,
|
||||||
|
headers: agent_with_custom_role.create_new_auth_token,
|
||||||
|
as: :json
|
||||||
|
end.to change(Captain::AssistantResponse, :count).by(1)
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not create a response if the custom role lacks knowledge base permission' do
|
||||||
|
custom_role = create(:custom_role, account: account, permissions: ['conversation_manage'])
|
||||||
|
AccountUser.find_by!(account: account, user: agent_with_custom_role).update!(custom_role: custom_role)
|
||||||
|
|
||||||
|
expect do
|
||||||
|
post "/api/v1/accounts/#{account.id}/captain/assistant_responses",
|
||||||
|
params: valid_params,
|
||||||
|
headers: agent_with_custom_role.create_new_auth_token,
|
||||||
|
as: :json
|
||||||
|
end.not_to change(Captain::AssistantResponse, :count)
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:forbidden)
|
||||||
|
end
|
||||||
|
|
||||||
context 'with invalid params' do
|
context 'with invalid params' do
|
||||||
let(:invalid_params) do
|
let(:invalid_params) do
|
||||||
{
|
{
|
||||||
@ -197,22 +238,6 @@ RSpec.describe 'Api::V1::Accounts::Captain::AssistantResponses', type: :request
|
|||||||
|
|
||||||
expect(response).to have_http_status(:unprocessable_entity)
|
expect(response).to have_http_status(:unprocessable_entity)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns unprocessable entity when question exceeds 255 characters' do
|
|
||||||
long_question = 'a' * 256
|
|
||||||
post "/api/v1/accounts/#{account.id}/captain/assistant_responses",
|
|
||||||
params: {
|
|
||||||
assistant_response: {
|
|
||||||
question: long_question,
|
|
||||||
answer: 'Test answer',
|
|
||||||
assistant_id: assistant.id
|
|
||||||
}
|
|
||||||
},
|
|
||||||
headers: admin.create_new_auth_token,
|
|
||||||
as: :json
|
|
||||||
|
|
||||||
expect(response).to have_http_status(:unprocessable_entity)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -239,6 +264,16 @@ RSpec.describe 'Api::V1::Accounts::Captain::AssistantResponses', type: :request
|
|||||||
expect(json_response[:answer]).to eq('Updated answer')
|
expect(json_response[:answer]).to eq('Updated answer')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'updates the response if the user is an agent' do
|
||||||
|
patch "/api/v1/accounts/#{account.id}/captain/assistant_responses/#{response_record.id}",
|
||||||
|
params: update_params,
|
||||||
|
headers: agent.create_new_auth_token,
|
||||||
|
as: :json
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
expect(json_response[:question]).to eq('Updated question?')
|
||||||
|
end
|
||||||
|
|
||||||
context 'with invalid params' do
|
context 'with invalid params' do
|
||||||
let(:invalid_params) do
|
let(:invalid_params) do
|
||||||
{
|
{
|
||||||
@ -266,7 +301,7 @@ RSpec.describe 'Api::V1::Accounts::Captain::AssistantResponses', type: :request
|
|||||||
it 'deletes the response' do
|
it 'deletes the response' do
|
||||||
expect do
|
expect do
|
||||||
delete "/api/v1/accounts/#{account.id}/captain/assistant_responses/#{response_record.id}",
|
delete "/api/v1/accounts/#{account.id}/captain/assistant_responses/#{response_record.id}",
|
||||||
headers: admin.create_new_auth_token,
|
headers: agent.create_new_auth_token,
|
||||||
as: :json
|
as: :json
|
||||||
end.to change(Captain::AssistantResponse, :count).by(-1)
|
end.to change(Captain::AssistantResponse, :count).by(-1)
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@ RSpec.describe 'Api::V1::Accounts::Captain::BulkActions', type: :request do
|
|||||||
let(:assistant) { create(:captain_assistant, account: account) }
|
let(:assistant) { create(:captain_assistant, account: account) }
|
||||||
let(:admin) { create(:user, account: account, role: :administrator) }
|
let(:admin) { create(:user, account: account, role: :administrator) }
|
||||||
let(:agent) { create(:user, account: account, role: :agent) }
|
let(:agent) { create(:user, account: account, role: :agent) }
|
||||||
|
let(:agent_with_custom_role) { create(:user, account: account, role: :agent) }
|
||||||
let!(:pending_responses) do
|
let!(:pending_responses) do
|
||||||
create_list(
|
create_list(
|
||||||
:captain_assistant_response,
|
:captain_assistant_response,
|
||||||
@ -32,7 +33,7 @@ RSpec.describe 'Api::V1::Accounts::Captain::BulkActions', type: :request do
|
|||||||
it 'approves the responses and returns the updated records' do
|
it 'approves the responses and returns the updated records' do
|
||||||
post "/api/v1/accounts/#{account.id}/captain/bulk_actions",
|
post "/api/v1/accounts/#{account.id}/captain/bulk_actions",
|
||||||
params: valid_params,
|
params: valid_params,
|
||||||
headers: admin.create_new_auth_token,
|
headers: agent.create_new_auth_token,
|
||||||
as: :json
|
as: :json
|
||||||
|
|
||||||
expect(response).to have_http_status(:ok)
|
expect(response).to have_http_status(:ok)
|
||||||
@ -59,7 +60,7 @@ RSpec.describe 'Api::V1::Accounts::Captain::BulkActions', type: :request do
|
|||||||
expect do
|
expect do
|
||||||
post "/api/v1/accounts/#{account.id}/captain/bulk_actions",
|
post "/api/v1/accounts/#{account.id}/captain/bulk_actions",
|
||||||
params: delete_params,
|
params: delete_params,
|
||||||
headers: admin.create_new_auth_token,
|
headers: agent.create_new_auth_token,
|
||||||
as: :json
|
as: :json
|
||||||
end.to change(Captain::AssistantResponse, :count).by(-2)
|
end.to change(Captain::AssistantResponse, :count).by(-2)
|
||||||
|
|
||||||
@ -73,6 +74,40 @@ RSpec.describe 'Api::V1::Accounts::Captain::BulkActions', type: :request do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when the user has a custom role' do
|
||||||
|
let(:approve_params) do
|
||||||
|
{
|
||||||
|
type: 'AssistantResponse',
|
||||||
|
ids: pending_responses.map(&:id),
|
||||||
|
fields: { status: 'approve' }
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'allows bulk actions with knowledge base permission' do
|
||||||
|
custom_role = create(:custom_role, account: account, permissions: ['knowledge_base_manage'])
|
||||||
|
AccountUser.find_by!(account: account, user: agent_with_custom_role).update!(custom_role: custom_role)
|
||||||
|
|
||||||
|
post "/api/v1/accounts/#{account.id}/captain/bulk_actions",
|
||||||
|
params: approve_params,
|
||||||
|
headers: agent_with_custom_role.create_new_auth_token,
|
||||||
|
as: :json
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects bulk actions without knowledge base permission' do
|
||||||
|
custom_role = create(:custom_role, account: account, permissions: ['conversation_manage'])
|
||||||
|
AccountUser.find_by!(account: account, user: agent_with_custom_role).update!(custom_role: custom_role)
|
||||||
|
|
||||||
|
post "/api/v1/accounts/#{account.id}/captain/bulk_actions",
|
||||||
|
params: approve_params,
|
||||||
|
headers: agent_with_custom_role.create_new_auth_token,
|
||||||
|
as: :json
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:forbidden)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'with invalid type' do
|
context 'with invalid type' do
|
||||||
let(:invalid_params) do
|
let(:invalid_params) do
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user