Fixes #2777: Knowledge Base - Attachments not working for internal readers.
This commit is contained in:
parent
86a90d287c
commit
d24a7c5584
6 changed files with 232 additions and 4 deletions
|
@ -1,5 +1,6 @@
|
||||||
class AttachmentsController < ApplicationController
|
class AttachmentsController < ApplicationController
|
||||||
prepend_before_action :authentication_check, except: :show
|
prepend_before_action :authentication_check, except: %i[show destroy]
|
||||||
|
prepend_before_action :authentication_check_only, only: %i[show destroy]
|
||||||
before_action :verify_object_permissions, only: %i[show destroy]
|
before_action :verify_object_permissions, only: %i[show destroy]
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
|
|
@ -10,6 +10,10 @@ module CanBePublished
|
||||||
can_be_published_aasm.published?
|
can_be_published_aasm.published?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def visible_internally?
|
||||||
|
can_be_published_aasm.internal? || visible?
|
||||||
|
end
|
||||||
|
|
||||||
class_methods do
|
class_methods do
|
||||||
def inverse_relation_name(scope_name)
|
def inverse_relation_name(scope_name)
|
||||||
"can_be_published_#{scope_name}_#{model_name.plural}"
|
"can_be_published_#{scope_name}_#{model_name.plural}"
|
||||||
|
|
|
@ -6,12 +6,15 @@ module HasKnowledgeBaseAttachmentPermissions
|
||||||
def can_show_attachment?(file, user)
|
def can_show_attachment?(file, user)
|
||||||
return true if user_kb_editor?(user)
|
return true if user_kb_editor?(user)
|
||||||
|
|
||||||
find(file.o_id)&.visible?
|
object = find(file.o_id)
|
||||||
|
|
||||||
|
return object&.visible_internally? if user_kb_reader?(user)
|
||||||
|
|
||||||
|
object&.visible?
|
||||||
end
|
end
|
||||||
|
|
||||||
def can_destroy_attachment?(file, user)
|
def can_destroy_attachment?(_file, user)
|
||||||
return if !user_kb_editor?(user)
|
return if !user_kb_editor?(user)
|
||||||
return if !HasRichText.attachment_inline?(file)
|
|
||||||
|
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
@ -21,6 +24,12 @@ module HasKnowledgeBaseAttachmentPermissions
|
||||||
|
|
||||||
user.permissions? %w[knowledge_base.editor]
|
user.permissions? %w[knowledge_base.editor]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def user_kb_reader?(user)
|
||||||
|
return false if user.nil?
|
||||||
|
|
||||||
|
user.permissions? %w[knowledge_base.reader]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
included do
|
included do
|
||||||
|
|
|
@ -15,6 +15,10 @@ class KnowledgeBase::Answer::Translation::Content < ApplicationModel
|
||||||
translation.answer.visible?
|
translation.answer.visible?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def visible_internally?
|
||||||
|
translation.answer.visible_internally?
|
||||||
|
end
|
||||||
|
|
||||||
delegate :created_by_id, to: :translation
|
delegate :created_by_id, to: :translation
|
||||||
|
|
||||||
def attributes_with_association_ids
|
def attributes_with_association_ids
|
||||||
|
|
206
spec/requests/knowledge_base/attachments_spec.rb
Normal file
206
spec/requests/knowledge_base/attachments_spec.rb
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe 'KnowledgeBase attachments', type: :request do
|
||||||
|
include_context 'basic Knowledge Base'
|
||||||
|
|
||||||
|
let(:attachment) do
|
||||||
|
attachment_file = File.open 'spec/fixtures/upload/hello_world.txt'
|
||||||
|
|
||||||
|
Store.add(
|
||||||
|
object: object.class.to_s,
|
||||||
|
o_id: object.id,
|
||||||
|
data: attachment_file.read,
|
||||||
|
filename: 'hello_world.txt',
|
||||||
|
preferences: {},
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:endpoint) { "/api/v1/attachments/#{attachment.id}" }
|
||||||
|
|
||||||
|
describe 'visible when attached to' do
|
||||||
|
shared_examples 'a visible resource' do
|
||||||
|
it 'and returns correct status code' do
|
||||||
|
get endpoint
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples 'a non-existent resource' do
|
||||||
|
it 'and returns correct status code' do
|
||||||
|
get endpoint
|
||||||
|
expect(response).to have_http_status(:not_found)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'draft answer' do
|
||||||
|
let(:object) { draft_answer }
|
||||||
|
|
||||||
|
describe 'as agent', authenticated_as: :agent_user do
|
||||||
|
it_behaves_like 'a non-existent resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as admin', authenticated_as: :admin_user do
|
||||||
|
it_behaves_like 'a visible resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as customer', authenticated_as: :customer_user do
|
||||||
|
it_behaves_like 'a non-existent resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as guest' do
|
||||||
|
it_behaves_like 'a non-existent resource'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'internal answer' do
|
||||||
|
let(:object) { internal_answer }
|
||||||
|
|
||||||
|
describe 'as agent', authenticated_as: :agent_user do
|
||||||
|
it_behaves_like 'a visible resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as admin', authenticated_as: :admin_user do
|
||||||
|
it_behaves_like 'a visible resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as customer', authenticated_as: :customer_user do
|
||||||
|
it_behaves_like 'a non-existent resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as guest' do
|
||||||
|
it_behaves_like 'a non-existent resource'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'published answer' do
|
||||||
|
let(:object) { published_answer }
|
||||||
|
|
||||||
|
describe 'as agent', authenticated_as: :agent_user do
|
||||||
|
it_behaves_like 'a visible resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as admin', authenticated_as: :admin_user do
|
||||||
|
it_behaves_like 'a visible resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as customer', authenticated_as: :customer_user do
|
||||||
|
it_behaves_like 'a visible resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as guest' do
|
||||||
|
it_behaves_like 'a visible resource'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'archived answer' do
|
||||||
|
let(:object) { archived_answer }
|
||||||
|
|
||||||
|
describe 'as agent', authenticated_as: :agent_user do
|
||||||
|
it_behaves_like 'a non-existent resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as admin', authenticated_as: :admin_user do
|
||||||
|
it_behaves_like 'a visible resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as customer', authenticated_as: :customer_user do
|
||||||
|
it_behaves_like 'a non-existent resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as guest' do
|
||||||
|
it_behaves_like 'a non-existent resource'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'deletable when attached to' do
|
||||||
|
shared_examples 'a deletable resource' do
|
||||||
|
it { expect { delete endpoint }.to change { Store.exists? attachment.id }.from(true).to(false) }
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples 'a non-deletable resource' do
|
||||||
|
it { expect { delete endpoint }.not_to change { Store.exists? attachment.id }.from(true) }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'draft answer' do
|
||||||
|
let(:object) { draft_answer }
|
||||||
|
|
||||||
|
describe 'as agent', authenticated_as: :agent_user do
|
||||||
|
it_behaves_like 'a non-deletable resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as admin', authenticated_as: :admin_user do
|
||||||
|
it_behaves_like 'a deletable resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as customer', authenticated_as: :customer_user do
|
||||||
|
it_behaves_like 'a non-deletable resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as guest' do
|
||||||
|
it_behaves_like 'a non-deletable resource'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'internal answer' do
|
||||||
|
let(:object) { internal_answer }
|
||||||
|
|
||||||
|
describe 'as agent', authenticated_as: :agent_user do
|
||||||
|
it_behaves_like 'a non-deletable resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as admin', authenticated_as: :admin_user do
|
||||||
|
it_behaves_like 'a deletable resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as customer', authenticated_as: :customer_user do
|
||||||
|
it_behaves_like 'a non-deletable resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as guest' do
|
||||||
|
it_behaves_like 'a non-deletable resource'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'published answer' do
|
||||||
|
let(:object) { published_answer }
|
||||||
|
|
||||||
|
describe 'as agent', authenticated_as: :agent_user do
|
||||||
|
it_behaves_like 'a non-deletable resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as admin', authenticated_as: :admin_user do
|
||||||
|
it_behaves_like 'a deletable resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as customer', authenticated_as: :customer_user do
|
||||||
|
it_behaves_like 'a non-deletable resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as guest' do
|
||||||
|
it_behaves_like 'a non-deletable resource'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'archived answer' do
|
||||||
|
let(:object) { archived_answer }
|
||||||
|
|
||||||
|
describe 'as agent', authenticated_as: :agent_user do
|
||||||
|
it_behaves_like 'a non-deletable resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as admin', authenticated_as: :admin_user do
|
||||||
|
it_behaves_like 'a deletable resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as customer', authenticated_as: :customer_user do
|
||||||
|
it_behaves_like 'a non-deletable resource'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as guest' do
|
||||||
|
it_behaves_like 'a non-deletable resource'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -26,4 +26,8 @@ RSpec.shared_context 'basic Knowledge Base', current_user_id: 1 do
|
||||||
let :internal_answer do
|
let :internal_answer do
|
||||||
create(:knowledge_base_answer, category: category, internal_at: 1.week.ago)
|
create(:knowledge_base_answer, category: category, internal_at: 1.week.ago)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
let :archived_answer do
|
||||||
|
create(:knowledge_base_answer, category: category, archived_at: 1.week.ago)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue