diff --git a/app/controllers/api/v1/accounts/portals_controller.rb b/app/controllers/api/v1/accounts/portals_controller.rb index fe9a03ef5..6cfed161f 100644 --- a/app/controllers/api/v1/accounts/portals_controller.rb +++ b/app/controllers/api/v1/accounts/portals_controller.rb @@ -9,11 +9,6 @@ class Api::V1::Accounts::PortalsController < Api::V1::Accounts::BaseController @portals = Current.account.portals end - def add_members - agents = Current.account.agents.where(id: portal_member_params[:member_ids]) - @portal.members << agents - end - def show @all_articles = @portal.articles @articles = @all_articles.search(locale: params[:locale]) @@ -85,10 +80,6 @@ class Api::V1::Accounts::PortalsController < Api::V1::Accounts::BaseController { channel_web_widget_id: inbox.channel.id } end - def portal_member_params - params.require(:portal).permit(:account_id, member_ids: []) - end - def set_current_page @current_page = params[:page] || 1 end diff --git a/app/controllers/api/v2/accounts/reports_controller.rb b/app/controllers/api/v2/accounts/reports_controller.rb index af3655e59..6e2d0ff4c 100644 --- a/app/controllers/api/v2/accounts/reports_controller.rb +++ b/app/controllers/api/v2/accounts/reports_controller.rb @@ -66,9 +66,7 @@ class Api::V2::Accounts::ReportsController < Api::V1::Accounts::BaseController end def check_authorization - return if Current.account_user.administrator? - - raise Pundit::NotAuthorizedError + authorize :report, :view? end def common_params @@ -137,5 +135,3 @@ class Api::V2::Accounts::ReportsController < Api::V1::Accounts::BaseController V2::ReportBuilder.new(Current.account, conversation_params).conversation_metrics end end - -Api::V2::Accounts::ReportsController.prepend_mod_with('Api::V2::Accounts::ReportsController') diff --git a/app/models/account.rb b/app/models/account.rb index 1cd59e1a4..decfc9d2e 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -2,20 +2,19 @@ # # Table name: accounts # -# id :integer not null, primary key -# auto_resolve_duration :integer -# contactable_contacts_count :integer default(0) -# custom_attributes :jsonb -# domain :string(100) -# feature_flags :bigint default(0), not null -# internal_attributes :jsonb not null -# limits :jsonb -# locale :integer default("en") -# name :string not null -# status :integer default("active") -# support_email :string(100) -# created_at :datetime not null -# updated_at :datetime not null +# id :integer not null, primary key +# auto_resolve_duration :integer +# custom_attributes :jsonb +# domain :string(100) +# feature_flags :bigint default(0), not null +# internal_attributes :jsonb not null +# limits :jsonb +# locale :integer default("en") +# name :string not null +# status :integer default("active") +# support_email :string(100) +# created_at :datetime not null +# updated_at :datetime not null # # Indexes # diff --git a/app/models/portal.rb b/app/models/portal.rb index cc64be1fd..cb87929f5 100644 --- a/app/models/portal.rb +++ b/app/models/portal.rb @@ -30,14 +30,6 @@ class Portal < ApplicationRecord has_many :categories, dependent: :destroy_async has_many :folders, through: :categories has_many :articles, dependent: :destroy_async - has_many :portal_members, - class_name: :PortalMember, - dependent: :destroy_async - has_many :members, - through: :portal_members, - class_name: :User, - dependent: :nullify, - source: :user has_one_attached :logo has_many :inboxes, dependent: :nullify belongs_to :channel_web_widget, class_name: 'Channel::WebWidget', optional: true @@ -49,8 +41,6 @@ class Portal < ApplicationRecord validates :custom_domain, uniqueness: true, allow_nil: true validate :config_json_format - accepts_nested_attributes_for :members - scope :active, -> { where(archived: false) } CONFIG_JSON_KEYS = %w[allowed_locales default_locale website_token].freeze diff --git a/app/models/portal_member.rb b/app/models/portal_member.rb deleted file mode 100644 index e0e687ae1..000000000 --- a/app/models/portal_member.rb +++ /dev/null @@ -1,20 +0,0 @@ -# == Schema Information -# -# Table name: portal_members -# -# id :bigint not null, primary key -# created_at :datetime not null -# updated_at :datetime not null -# portal_id :bigint -# user_id :bigint -# -# Indexes -# -# index_portal_members_on_portal_id_and_user_id (portal_id,user_id) UNIQUE -# index_portal_members_on_user_id_and_portal_id (user_id,portal_id) UNIQUE -# -class PortalMember < ApplicationRecord - belongs_to :portal, class_name: 'Portal' - belongs_to :user, class_name: 'User' - validates :user_id, uniqueness: { scope: :portal_id } -end diff --git a/app/models/user.rb b/app/models/user.rb index faadb3271..5594b0ca6 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -95,10 +95,6 @@ class User < ApplicationRecord has_many :team_members, dependent: :destroy_async has_many :teams, through: :team_members has_many :articles, foreign_key: 'author_id', dependent: :nullify, inverse_of: :author - has_many :portal_members, class_name: :PortalMember, dependent: :destroy_async - has_many :portals, through: :portal_members, source: :portal, - class_name: :Portal, - dependent: :nullify # rubocop:disable Rails/HasManyOrHasOneDependent # we are handling this in `remove_macros` callback has_many :macros, foreign_key: 'created_by_id', inverse_of: :created_by diff --git a/app/policies/article_policy.rb b/app/policies/article_policy.rb index e48442337..282a507be 100644 --- a/app/policies/article_policy.rb +++ b/app/policies/article_policy.rb @@ -1,37 +1,31 @@ class ArticlePolicy < ApplicationPolicy def index? - @account_user.administrator? || @account.users.include?(@user) + @account.users.include?(@user) end def update? - @account_user.administrator? || portal_member? + @account_user.administrator? end def show? - @account_user.administrator? || portal_member? + @account_user.administrator? end def edit? - @account_user.administrator? || portal_member? + @account_user.administrator? end def create? - @account_user.administrator? || portal_member? + @account_user.administrator? end def destroy? - @account_user.administrator? || portal_member? + @account_user.administrator? end def reorder? - @account_user.administrator? || portal_member? - end - - private - - def portal_member? - @record.first.portal.members.include?(@user) + @account_user.administrator? end end -ArticlePolicy.prepend_mod_with('Enterprise::ArticlePolicy') +ArticlePolicy.prepend_mod_with('ArticlePolicy') diff --git a/app/policies/category_policy.rb b/app/policies/category_policy.rb index 3dca6b847..104022595 100644 --- a/app/policies/category_policy.rb +++ b/app/policies/category_policy.rb @@ -1,33 +1,27 @@ class CategoryPolicy < ApplicationPolicy def index? - @account_user.administrator? || @account.users.include?(@user) + @account.users.include?(@user) end def update? - @account_user.administrator? || portal_member? + @account_user.administrator? end def show? - @account_user.administrator? || portal_member? + @account_user.administrator? end def edit? - @account_user.administrator? || portal_member? + @account_user.administrator? end def create? - @account_user.administrator? || portal_member? + @account_user.administrator? end def destroy? - @account_user.administrator? || portal_member? - end - - private - - def portal_member? - @record.first.portal.members.include?(@user) + @account_user.administrator? end end -CategoryPolicy.prepend_mod_with('Enterprise::CategoryPolicy') +CategoryPolicy.prepend_mod_with('CategoryPolicy') diff --git a/app/policies/portal_policy.rb b/app/policies/portal_policy.rb index c52b44cac..1e09c41f6 100644 --- a/app/policies/portal_policy.rb +++ b/app/policies/portal_policy.rb @@ -1,6 +1,6 @@ class PortalPolicy < ApplicationPolicy def index? - @account_user.administrator? || @account.users.include?(@user) + @account.users.include?(@user) end def update? @@ -8,7 +8,7 @@ class PortalPolicy < ApplicationPolicy end def show? - @account_user.administrator? || portal_member? + @account.users.include?(@user) end def edit? @@ -23,19 +23,9 @@ class PortalPolicy < ApplicationPolicy @account_user.administrator? end - def add_members? - @account_user.administrator? - end - def logo? @account_user.administrator? end - - private - - def portal_member? - @record.first.members.include?(@user) - end end -PortalPolicy.prepend_mod_with('Enterprise::PortalPolicy') +PortalPolicy.prepend_mod_with('PortalPolicy') diff --git a/app/policies/report_policy.rb b/app/policies/report_policy.rb index a52607a67..a2701ffd2 100644 --- a/app/policies/report_policy.rb +++ b/app/policies/report_policy.rb @@ -4,4 +4,4 @@ class ReportPolicy < ApplicationPolicy end end -ReportPolicy.prepend_mod_with('Enterprise::ReportPolicy') +ReportPolicy.prepend_mod_with('ReportPolicy') diff --git a/app/views/api/v1/accounts/portals/_portal.json.jbuilder b/app/views/api/v1/accounts/portals/_portal.json.jbuilder index 199ab352f..5e267f60c 100644 --- a/app/views/api/v1/accounts/portals/_portal.json.jbuilder +++ b/app/views/api/v1/accounts/portals/_portal.json.jbuilder @@ -25,14 +25,6 @@ end json.logo portal.file_base_data if portal.logo.present? -json.portal_members do - if portal.members.any? - json.array! portal.members.each do |member| - json.partial! 'api/v1/models/agent', formats: [:json], resource: member - end - end -end - json.meta do json.all_articles_count articles.try(:size) json.archived_articles_count articles.try(:archived).try(:size) diff --git a/config/routes.rb b/config/routes.rb index 3ec088890..46199db12 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -264,7 +264,6 @@ Rails.application.routes.draw do resources :portals do member do patch :archive - put :add_members delete :logo end resources :categories diff --git a/db/migrate/20250402233933_remove_portal_members.rb b/db/migrate/20250402233933_remove_portal_members.rb new file mode 100644 index 000000000..f145f5288 --- /dev/null +++ b/db/migrate/20250402233933_remove_portal_members.rb @@ -0,0 +1,16 @@ +class RemovePortalMembers < ActiveRecord::Migration[7.0] + def up + drop_table :portal_members + end + + def down + create_table :portal_members do |t| + t.references :portal, index: false + t.references :user, index: false + t.timestamps + end + + add_index :portal_members, [:portal_id, :user_id], unique: true + add_index :portal_members, [:user_id, :portal_id], unique: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 1f7217cd8..e4706342e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2025_03_26_034635) do +ActiveRecord::Schema[7.0].define(version: 2025_04_02_233933) do # These extensions should be enabled to support this database enable_extension "pg_stat_statements" enable_extension "pg_trgm" @@ -871,15 +871,6 @@ ActiveRecord::Schema[7.0].define(version: 2025_03_26_034635) do t.datetime "updated_at", null: false end - create_table "portal_members", force: :cascade do |t| - t.bigint "portal_id" - t.bigint "user_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["portal_id", "user_id"], name: "index_portal_members_on_portal_id_and_user_id", unique: true - t.index ["user_id", "portal_id"], name: "index_portal_members_on_user_id_and_portal_id", unique: true - end - create_table "portals", force: :cascade do |t| t.integer "account_id", null: false t.string "name", null: false diff --git a/enterprise/app/controllers/enterprise/api/v2/accounts/reports_controller.rb b/enterprise/app/controllers/enterprise/api/v2/accounts/reports_controller.rb deleted file mode 100644 index b5e2a9efe..000000000 --- a/enterprise/app/controllers/enterprise/api/v2/accounts/reports_controller.rb +++ /dev/null @@ -1,7 +0,0 @@ -module Enterprise::Api::V2::Accounts::ReportsController - def check_authorization - return if Current.account_user.custom_role&.permissions&.include?('report_manage') - - super - end -end diff --git a/enterprise/app/policies/enterprise/portal_policy.rb b/enterprise/app/policies/enterprise/portal_policy.rb index 45c3ea140..73e911efb 100644 --- a/enterprise/app/policies/enterprise/portal_policy.rb +++ b/enterprise/app/policies/enterprise/portal_policy.rb @@ -1,32 +1,12 @@ module Enterprise::PortalPolicy - def index? - @account_user.custom_role&.permissions&.include?('knowledge_base_manage') || super - end - def update? @account_user.custom_role&.permissions&.include?('knowledge_base_manage') || super end - def show? - @account_user.custom_role&.permissions&.include?('knowledge_base_manage') || super - end - def edit? @account_user.custom_role&.permissions&.include?('knowledge_base_manage') || super end - def create? - @account_user.custom_role&.permissions&.include?('knowledge_base_manage') || super - end - - def destroy? - @account_user.custom_role&.permissions&.include?('knowledge_base_manage') || super - end - - def add_members? - @account_user.custom_role&.permissions&.include?('knowledge_base_manage') || super - end - def logo? @account_user.custom_role&.permissions&.include?('knowledge_base_manage') || super end diff --git a/spec/controllers/api/v1/accounts/articles_controller_spec.rb b/spec/controllers/api/v1/accounts/articles_controller_spec.rb index 754629b7b..42fd062dc 100644 --- a/spec/controllers/api/v1/accounts/articles_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/articles_controller_spec.rb @@ -3,12 +3,11 @@ require 'rails_helper' RSpec.describe 'Api::V1::Accounts::Articles', type: :request do let(:account) { create(:account) } let(:agent) { create(:user, account: account, role: :agent) } + let(:admin) { create(:user, account: account, role: :administrator) } let!(:portal) { create(:portal, name: 'test_portal', account_id: account.id) } let!(:category) { create(:category, name: 'category', portal: portal, account_id: account.id, locale: 'en', slug: 'category_slug') } let!(:article) { create(:article, category: category, portal: portal, account_id: account.id, author_id: agent.id) } - before { create(:portal_member, user: agent, portal: portal) } - describe 'POST /api/v1/accounts/{account.id}/portals/{portal.slug}/articles' do context 'when it is an unauthenticated user' do it 'returns unauthorized' do @@ -33,7 +32,7 @@ RSpec.describe 'Api::V1::Accounts::Articles', type: :request do } post "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/articles", params: article_params, - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token expect(response).to have_http_status(:success) json_response = response.parsed_body expect(json_response['payload']['title']).to eql('MyTitle') @@ -56,7 +55,7 @@ RSpec.describe 'Api::V1::Accounts::Articles', type: :request do } post "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/articles", params: article_params, - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token expect(response).to have_http_status(:success) json_response = response.parsed_body expect(json_response['payload']['title']).to eql('MyTitle') @@ -84,7 +83,7 @@ RSpec.describe 'Api::V1::Accounts::Articles', type: :request do } post "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/articles", params: article_params, - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token expect(response).to have_http_status(:success) json_response = response.parsed_body expect(json_response['payload']['title']).to eql('MyTitle') @@ -110,7 +109,7 @@ RSpec.describe 'Api::V1::Accounts::Articles', type: :request do } post "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/articles", params: article_params, - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token expect(response).to have_http_status(:success) json_response = response.parsed_body expect(json_response['payload']['title']).to eql('MyTitle') @@ -144,7 +143,7 @@ RSpec.describe 'Api::V1::Accounts::Articles', type: :request do put "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/articles/#{article.id}", params: article_params, - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token expect(response).to have_http_status(:success) json_response = response.parsed_body expect(json_response['payload']['title']).to eql(article_params[:article][:title]) @@ -165,7 +164,7 @@ RSpec.describe 'Api::V1::Accounts::Articles', type: :request do context 'when it is an authenticated user' do it 'deletes category' do delete "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/articles/#{article.id}", - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token expect(response).to have_http_status(:success) deleted_article = Article.find_by(id: article.id) expect(deleted_article).to be_nil @@ -187,7 +186,7 @@ RSpec.describe 'Api::V1::Accounts::Articles', type: :request do expect(article2.id).not_to be_nil get "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/articles", - headers: agent.create_new_auth_token, + headers: admin.create_new_auth_token, params: {} expect(response).to have_http_status(:success) json_response = response.parsed_body @@ -199,7 +198,7 @@ RSpec.describe 'Api::V1::Accounts::Articles', type: :request do expect(article2.id).not_to be_nil get "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/articles", - headers: agent.create_new_auth_token, + headers: admin.create_new_auth_token, params: {} expect(response).to have_http_status(:success) json_response = response.parsed_body @@ -213,7 +212,7 @@ RSpec.describe 'Api::V1::Accounts::Articles', type: :request do expect(article2.id).not_to be_nil get "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/articles", - headers: agent.create_new_auth_token, + headers: admin.create_new_auth_token, params: { category_slug: category.slug } expect(response).to have_http_status(:success) json_response = response.parsed_body @@ -230,14 +229,14 @@ RSpec.describe 'Api::V1::Accounts::Articles', type: :request do expect(article2.id).not_to be_nil get "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/articles", - headers: agent.create_new_auth_token, + headers: admin.create_new_auth_token, params: { query: 'funny' } expect(response).to have_http_status(:success) json_response = response.parsed_body expect(json_response['payload'].count).to be 1 expect(json_response['meta']['all_articles_count']).to be 2 expect(json_response['meta']['articles_count']).to be 1 - expect(json_response['meta']['mine_articles_count']).to be 1 + expect(json_response['meta']['mine_articles_count']).to be 0 end end @@ -247,7 +246,7 @@ RSpec.describe 'Api::V1::Accounts::Articles', type: :request do expect(article2.id).not_to be_nil get "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/articles/#{article2.id}", - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token expect(response).to have_http_status(:success) json_response = response.parsed_body @@ -263,7 +262,7 @@ RSpec.describe 'Api::V1::Accounts::Articles', type: :request do associated_article_id: root_article.id) get "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/articles/#{root_article.id}", - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token expect(response).to have_http_status(:success) json_response = response.parsed_body diff --git a/spec/controllers/api/v1/accounts/categories_controller_spec.rb b/spec/controllers/api/v1/accounts/categories_controller_spec.rb index 03e658aac..48cc001e3 100644 --- a/spec/controllers/api/v1/accounts/categories_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/categories_controller_spec.rb @@ -3,6 +3,7 @@ require 'rails_helper' RSpec.describe 'Api::V1::Accounts::Categories', type: :request do let(:account) { create(:account) } let(:agent) { create(:user, account: account, role: :agent) } + let(:admin) { create(:user, account: account, role: :administrator) } let!(:portal) { create(:portal, name: 'test_portal', account_id: account.id, config: { allowed_locales: %w[en es] }) } let!(:category) { create(:category, name: 'category', portal: portal, account_id: account.id, slug: 'category_slug', position: 1) } let!(:category_to_associate) do @@ -15,8 +16,6 @@ RSpec.describe 'Api::V1::Accounts::Categories', type: :request do create(:category, name: 'related category 2', portal: portal, account_id: account.id, slug: 'category_slug_2', position: 4) end - before { create(:portal_member, user: agent, portal: portal) } - describe 'POST /api/v1/accounts/{account.id}/portals/{portal.slug}/categories' do context 'when it is an unauthenticated user' do it 'returns unauthorized' do @@ -59,7 +58,7 @@ RSpec.describe 'Api::V1::Accounts::Categories', type: :request do it 'creates category' do post "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/categories", params: category_params, - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token expect(response).to have_http_status(:success) json_response = response.parsed_body @@ -75,11 +74,11 @@ RSpec.describe 'Api::V1::Accounts::Categories', type: :request do it 'creates multiple sub_categories under one parent_category' do post "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/categories", params: category_params, - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token post "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/categories", params: category_params_2, - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token expect(response).to have_http_status(:success) expect(category.reload.sub_category_ids).to eql(Category.last(2).pluck(:id)) @@ -88,11 +87,11 @@ RSpec.describe 'Api::V1::Accounts::Categories', type: :request do it 'creates multiple associated_categories with one category' do post "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/categories", params: category_params, - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token post "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/categories", params: category_params_2, - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token expect(response).to have_http_status(:success) expect(category_to_associate.reload.associated_category_ids).to eql(Category.last(2).pluck(:id)) @@ -101,11 +100,11 @@ RSpec.describe 'Api::V1::Accounts::Categories', type: :request do it 'will throw an error on locale, category_id uniqueness' do post "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/categories", params: category_params, - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token post "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/categories", params: category_params, - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token expect(response).to have_http_status(:unprocessable_entity) json_response = response.parsed_body expect(json_response['message']).to eql('Locale should be unique in the category and portal') @@ -123,7 +122,7 @@ RSpec.describe 'Api::V1::Accounts::Categories', type: :request do post "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/categories", params: category_params, - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token expect(response).to have_http_status(:unprocessable_entity) json_response = response.parsed_body @@ -158,7 +157,7 @@ RSpec.describe 'Api::V1::Accounts::Categories', type: :request do put "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/categories/#{category.id}", params: category_params, - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token json_response = response.parsed_body @@ -181,7 +180,7 @@ RSpec.describe 'Api::V1::Accounts::Categories', type: :request do put "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/categories/#{category.id}", params: category_params, - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token expect(response).to have_http_status(:success) @@ -209,7 +208,7 @@ RSpec.describe 'Api::V1::Accounts::Categories', type: :request do put "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/categories/#{related_category_2.id}", params: category_params, - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token expect(response).to have_http_status(:success) @@ -230,7 +229,7 @@ RSpec.describe 'Api::V1::Accounts::Categories', type: :request do context 'when it is an authenticated user' do it 'deletes category' do delete "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/categories/#{category.id}", - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token expect(response).to have_http_status(:success) deleted_category = Category.find_by(id: category.id) expect(deleted_category).to be_nil @@ -255,7 +254,7 @@ RSpec.describe 'Api::V1::Accounts::Categories', type: :request do expect(category2.id).not_to be_nil get "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/categories", - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token expect(response).to have_http_status(:success) json_response = response.parsed_body expect(json_response['payload'].count).to be(category_count + 1) diff --git a/spec/controllers/api/v1/accounts/portals_controller_spec.rb b/spec/controllers/api/v1/accounts/portals_controller_spec.rb index 7da6bf52f..aeec9cab4 100644 --- a/spec/controllers/api/v1/accounts/portals_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/portals_controller_spec.rb @@ -8,8 +8,6 @@ RSpec.describe 'Api::V1::Accounts::Portals', type: :request do let(:agent_2) { create(:user, account: account, role: :agent) } let!(:portal) { create(:portal, slug: 'portal-1', name: 'test_portal', account_id: account.id) } - before { create(:portal_member, user: agent, portal: portal) } - describe 'GET /api/v1/accounts/{account.id}/portals' do context 'when it is an unauthenticated user' do it 'returns unauthorized' do @@ -23,7 +21,7 @@ RSpec.describe 'Api::V1::Accounts::Portals', type: :request do portal2 = create(:portal, name: 'test_portal_2', account_id: account.id, slug: 'portal-2') expect(portal2.id).not_to be_nil get "/api/v1/accounts/#{account.id}/portals", - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token expect(response).to have_http_status(:success) json_response = response.parsed_body @@ -45,7 +43,7 @@ RSpec.describe 'Api::V1::Accounts::Portals', type: :request do context 'when it is an authenticated user' do it 'get one portals' do get "/api/v1/accounts/#{account.id}/portals/#{portal.slug}", - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token expect(response).to have_http_status(:success) json_response = response.parsed_body @@ -62,7 +60,7 @@ RSpec.describe 'Api::V1::Accounts::Portals', type: :request do create(:article, category_id: es_cat.id, portal_id: portal.id, author_id: agent.id) get "/api/v1/accounts/#{account.id}/portals/#{portal.slug}?locale=en", - headers: agent.create_new_auth_token + headers: admin.create_new_auth_token expect(response).to have_http_status(:success) json_response = response.parsed_body @@ -178,38 +176,7 @@ RSpec.describe 'Api::V1::Accounts::Portals', type: :request do end end - describe 'PUT /api/v1/accounts/{account.id}/portals/{portal.slug}/add_members' do - let(:new_account) { create(:account) } - let(:new_agent) { create(:user, account: new_account, role: :agent) } - - context 'when it is an unauthenticated user' do - it 'returns unauthorized' do - put "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/add_members", params: {} - - expect(response).to have_http_status(:unauthorized) - end - end - - context 'when it is an authenticated user' do - it 'add members to the portal' do - portal_params = { - portal: { - member_ids: [agent_1.id, agent_2.id] - } - } - expect(portal.members.count).to be(1) - - put "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/add_members", - params: portal_params, - headers: admin.create_new_auth_token - - expect(response).to have_http_status(:success) - json_response = response.parsed_body - expect(portal.reload.member_ids).to include(agent_1.id) - expect(json_response['portal_members'].length).to be(3) - end - end - end + # Portal members endpoint removed describe 'DELETE /api/v1/accounts/{account.id}/portals/{portal.slug}/logo' do context 'when it is an unauthenticated user' do diff --git a/spec/enterprise/controllers/enterprise/api/v1/accounts/articles_controller_spec.rb b/spec/enterprise/controllers/enterprise/api/v1/accounts/articles_controller_spec.rb new file mode 100644 index 000000000..43d6fc02d --- /dev/null +++ b/spec/enterprise/controllers/enterprise/api/v1/accounts/articles_controller_spec.rb @@ -0,0 +1,103 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Enterprise Articles API', type: :request do + let(:account) { create(:account) } + let(:admin) { create(:user, :administrator, account: account) } + let(:agent) { create(:user, account: account, role: :agent) } + let!(:portal) { create(:portal, name: 'test_portal', account_id: account.id) } + let!(:category) { create(:category, name: 'category', portal: portal, account_id: account.id, locale: 'en', slug: 'category_slug') } + let!(:article) { create(:article, category: category, portal: portal, account_id: account.id, author_id: admin.id) } + + # Create a custom role with knowledge_base_manage permission + let!(:custom_role) { create(:custom_role, account: account, permissions: ['knowledge_base_manage']) } + # Create user without account + let!(:agent_with_role) { create(:user) } + # Then create account_user association with custom_role + let(:agent_with_role_account_user) do + create(:account_user, user: agent_with_role, account: account, role: :agent, custom_role: custom_role) + end + + # Ensure the account_user with custom role is created before tests run + before do + agent_with_role_account_user + end + + describe 'GET /api/v1/accounts/:account_id/portals/:portal_slug/articles/:id' do + context 'when it is an authenticated user' do + it 'returns success for agents with knowledge_base_manage permission' do + get "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/articles/#{article.id}", + headers: agent_with_role.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + end + end + end + + describe 'POST /api/v1/accounts/:account_id/portals/:portal_slug/articles' do + let(:article_params) do + { + article: { + category_id: category.id, + title: 'New Article', + slug: 'new-article', + content: 'This is a new article', + author_id: agent_with_role.id, + status: 'draft' + } + } + end + + context 'when it is an authenticated user' do + it 'returns success for agents with knowledge_base_manage permission' do + post "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/articles", + params: article_params, + headers: agent_with_role.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + json_response = response.parsed_body + expect(json_response['payload']['title']).to eq('New Article') + end + end + end + + describe 'PUT /api/v1/accounts/:account_id/portals/:portal_slug/articles/:id' do + let(:article_params) do + { + article: { + title: 'Updated Article', + content: 'This is an updated article' + } + } + end + + context 'when it is an authenticated user' do + it 'returns success for agents with knowledge_base_manage permission' do + put "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/articles/#{article.id}", + params: article_params, + headers: agent_with_role.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + json_response = response.parsed_body + expect(json_response['payload']['title']).to eq('Updated Article') + end + end + end + + describe 'DELETE /api/v1/accounts/:account_id/portals/:portal_slug/articles/:id' do + context 'when it is an authenticated user' do + it 'returns success for agents with knowledge_base_manage permission' do + delete "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/articles/#{article.id}", + headers: agent_with_role.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + expect(Article.find_by(id: article.id)).to be_nil + end + end + end +end diff --git a/spec/enterprise/controllers/enterprise/api/v1/accounts/categories_controller_spec.rb b/spec/enterprise/controllers/enterprise/api/v1/accounts/categories_controller_spec.rb new file mode 100644 index 000000000..f83542743 --- /dev/null +++ b/spec/enterprise/controllers/enterprise/api/v1/accounts/categories_controller_spec.rb @@ -0,0 +1,111 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Enterprise Categories API', type: :request do + let(:account) { create(:account) } + let(:admin) { create(:user, account: account, role: :administrator) } + let(:agent) { create(:user, account: account, role: :agent) } + let!(:portal) { create(:portal, name: 'test_portal', account_id: account.id, config: { allowed_locales: %w[en es] }) } + let!(:category) { create(:category, name: 'category', portal: portal, account_id: account.id, slug: 'category_slug', position: 1) } + + # Create a custom role with knowledge_base_manage permission + let!(:custom_role) { create(:custom_role, account: account, permissions: ['knowledge_base_manage']) } + let!(:agent_with_role) { create(:user) } + let(:agent_with_role_account_user) do + create(:account_user, user: agent_with_role, account: account, role: :agent, custom_role: custom_role) + end + + # Ensure the account_user with custom role is created before tests run + before do + agent_with_role_account_user + end + + describe 'GET /api/v1/accounts/:account_id/portals/:portal_slug/categories' do + context 'when it is an authenticated user' do + it 'returns success for agents with knowledge_base_manage permission' do + get "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/categories", + headers: agent_with_role.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + end + end + end + + describe 'GET /api/v1/accounts/:account_id/portals/:portal_slug/categories/:id' do + context 'when it is an authenticated user' do + it 'returns success for agents with knowledge_base_manage permission' do + get "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/categories/#{category.id}", + headers: agent_with_role.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + json_response = response.parsed_body + expect(json_response['payload']['name']).to eq('category') + end + end + end + + describe 'POST /api/v1/accounts/:account_id/portals/:portal_slug/categories' do + let(:category_params) do + { + category: { + name: 'New Category', + slug: 'new-category', + locale: 'en', + description: 'This is a new category' + } + } + end + + context 'when it is an authenticated user' do + it 'returns success for agents with knowledge_base_manage permission' do + post "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/categories", + params: category_params, + headers: agent_with_role.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + json_response = response.parsed_body + expect(json_response['payload']['name']).to eq('New Category') + end + end + end + + describe 'PUT /api/v1/accounts/:account_id/portals/:portal_slug/categories/:id' do + let(:category_params) do + { + category: { + name: 'Updated Category', + description: 'This is an updated category' + } + } + end + + context 'when it is an authenticated user' do + it 'returns success for agents with knowledge_base_manage permission' do + put "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/categories/#{category.id}", + params: category_params, + headers: agent_with_role.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + json_response = response.parsed_body + expect(json_response['payload']['name']).to eq('Updated Category') + end + end + end + + describe 'DELETE /api/v1/accounts/:account_id/portals/:portal_slug/categories/:id' do + context 'when it is an authenticated user' do + it 'returns success for agents with knowledge_base_manage permission' do + delete "/api/v1/accounts/#{account.id}/portals/#{portal.slug}/categories/#{category.id}", + headers: agent_with_role.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + end + end + end +end diff --git a/enterprise/spec/controllers/api/v1/accounts/contacts/conversations_controller_spec.rb b/spec/enterprise/controllers/enterprise/api/v1/accounts/contacts/conversations_controller_spec.rb similarity index 100% rename from enterprise/spec/controllers/api/v1/accounts/contacts/conversations_controller_spec.rb rename to spec/enterprise/controllers/enterprise/api/v1/accounts/contacts/conversations_controller_spec.rb diff --git a/spec/enterprise/controllers/enterprise/api/v1/accounts/portals_controller_spec.rb b/spec/enterprise/controllers/enterprise/api/v1/accounts/portals_controller_spec.rb new file mode 100644 index 000000000..cb296494c --- /dev/null +++ b/spec/enterprise/controllers/enterprise/api/v1/accounts/portals_controller_spec.rb @@ -0,0 +1,90 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Enterprise Portal API', type: :request do + let(:account) { create(:account) } + let(:admin) { create(:user, :administrator, account: account) } + let(:agent) { create(:user, account: account, role: :agent) } + let!(:portal) { create(:portal, name: 'test_portal', account_id: account.id) } + + # Create a custom role with knowledge_base_manage permission + let!(:custom_role) { create(:custom_role, account: account, permissions: ['knowledge_base_manage']) } + # Create user without account + let!(:agent_with_role) { create(:user) } + # Then create account_user association with custom_role + let(:agent_with_role_account_user) do + create(:account_user, user: agent_with_role, account: account, role: :agent, custom_role: custom_role) + end + + # Ensure the account_user with custom role is created before tests run + before do + agent_with_role_account_user + end + + describe 'GET /api/v1/accounts/:account_id/portals' do + context 'when it is an authenticated user' do + it 'returns success for agents with knowledge_base_manage permission' do + get "/api/v1/accounts/#{account.id}/portals", + headers: agent_with_role.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + end + end + end + + describe 'GET /api/v1/accounts/:account_id/portals/:portal_slug' do + context 'when it is an authenticated user' do + it 'returns success for agents with knowledge_base_manage permission' do + get "/api/v1/accounts/#{account.id}/portals/#{portal.slug}", + headers: agent_with_role.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + json_response = response.parsed_body + expect(json_response['name']).to eq('test_portal') + end + end + end + + describe 'POST /api/v1/accounts/:account_id/portals' do + let(:portal_params) do + { portal: { + name: 'test_portal', + slug: 'test_kbase', + custom_domain: 'https://support.chatwoot.dev' + } } + end + + context 'when it is an authenticated user' do + it 'restricts portal creation for agents with knowledge_base_manage permission' do + post "/api/v1/accounts/#{account.id}/portals", + params: portal_params, + headers: agent_with_role.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:unauthorized) + end + end + end + + describe 'PUT /api/v1/accounts/:account_id/portals/:portal_slug' do + let(:portal_params) do + { portal: { name: 'updated_portal' } } + end + + context 'when it is an authenticated user' do + it 'returns success for agents with knowledge_base_manage permission' do + put "/api/v1/accounts/#{account.id}/portals/#{portal.slug}", + params: portal_params, + headers: agent_with_role.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + json_response = response.parsed_body + expect(json_response['name']).to eq('updated_portal') + end + end + end +end diff --git a/spec/enterprise/controllers/enterprise/api/v2/accounts/reports_controller_spec.rb b/spec/enterprise/controllers/enterprise/api/v2/accounts/reports_controller_spec.rb new file mode 100644 index 000000000..ff05af909 --- /dev/null +++ b/spec/enterprise/controllers/enterprise/api/v2/accounts/reports_controller_spec.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Enterprise Reports API', type: :request do + let(:account) { create(:account) } + let(:agent) { create(:user, account: account, role: :agent) } + + # Create a custom role with report_manage permission + let!(:custom_role) { create(:custom_role, account: account, permissions: ['report_manage']) } + let!(:agent_with_role) { create(:user) } + let(:agent_with_role_account_user) do + create(:account_user, user: agent_with_role, account: account, role: :agent, custom_role: custom_role) + end + + let(:default_timezone) { 'UTC' } + let(:start_of_today) { Time.current.in_time_zone(default_timezone).beginning_of_day.to_i } + let(:end_of_today) { Time.current.in_time_zone(default_timezone).end_of_day.to_i } + let(:params) { { timezone_offset: Time.zone.utc_offset } } + + before do + agent_with_role_account_user + end + + describe 'GET /api/v2/accounts/:account_id/reports' do + context 'when it is an authenticated user' do + let(:params) do + super().merge( + metric: 'conversations_count', + type: :account, + since: start_of_today.to_s, + until: end_of_today.to_s + ) + end + + it 'returns success for agents with report_manage permission' do + get "/api/v2/accounts/#{account.id}/reports", + params: params, + headers: agent_with_role.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + end + end + end + + describe 'GET /api/v2/accounts/:account_id/reports/summary' do + context 'when it is an authenticated user' do + let(:params) do + super().merge( + type: :account, + since: start_of_today.to_s, + until: end_of_today.to_s + ) + end + + it 'returns success for agents with report_manage permission' do + get "/api/v2/accounts/#{account.id}/reports/summary", + params: params, + headers: agent_with_role.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + end + end + end +end diff --git a/spec/enterprise/policies/article_policy_spec.rb b/spec/enterprise/policies/article_policy_spec.rb new file mode 100644 index 000000000..2417ab9e2 --- /dev/null +++ b/spec/enterprise/policies/article_policy_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Enterprise::ArticlePolicy', type: :policy do + subject(:article_policy) { ArticlePolicy } + + let(:account) { create(:account) } + let(:agent) { create(:user, account: account) } # Needed for author + let(:portal) { create(:portal, account: account) } + let(:article) { create(:article, account: account, portal: portal, author: agent) } + + # Create a custom role with knowledge_base_manage permission + let(:custom_role) { create(:custom_role, account: account, permissions: ['knowledge_base_manage']) } + let(:agent_with_role) { create(:user) } # Create without account + let(:agent_with_role_account_user) do + create(:account_user, user: agent_with_role, account: account, role: :agent, custom_role: custom_role) + end + let(:agent_with_role_context) do + { user: agent_with_role, account: account, account_user: agent_with_role_account_user } + end + + permissions :index?, :update?, :show?, :edit?, :create?, :destroy?, :reorder? do + context 'when agent with knowledge_base_manage permission' do + it { expect(article_policy).to permit(agent_with_role_context, article) } + end + end +end diff --git a/spec/enterprise/policies/category_policy_spec.rb b/spec/enterprise/policies/category_policy_spec.rb new file mode 100644 index 000000000..004428a2b --- /dev/null +++ b/spec/enterprise/policies/category_policy_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Enterprise::CategoryPolicy', type: :policy do + subject(:category_policy) { CategoryPolicy } + + let(:account) { create(:account) } + let(:portal) { create(:portal, account: account) } + let(:category) { create(:category, account: account, portal: portal, slug: 'test-category') } + + # Create a custom role with knowledge_base_manage permission + let(:custom_role) { create(:custom_role, account: account, permissions: ['knowledge_base_manage']) } + let(:agent_with_role) { create(:user) } # Create without account + let(:agent_with_role_account_user) do + create(:account_user, user: agent_with_role, account: account, role: :agent, custom_role: custom_role) + end + let(:agent_with_role_context) do + { user: agent_with_role, account: account, account_user: agent_with_role_account_user } + end + + permissions :index?, :update?, :show?, :edit?, :create?, :destroy? do + context 'when agent with knowledge_base_manage permission' do + it { expect(category_policy).to permit(agent_with_role_context, category) } + end + end +end diff --git a/spec/enterprise/policies/portal_policy_spec.rb b/spec/enterprise/policies/portal_policy_spec.rb new file mode 100644 index 000000000..1e419b02c --- /dev/null +++ b/spec/enterprise/policies/portal_policy_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Enterprise::PortalPolicy', type: :policy do + subject(:portal_policy) { PortalPolicy } + + let(:account) { create(:account) } + let(:portal) { create(:portal, account: account) } + + # Create a custom role with knowledge_base_manage permission + let(:custom_role) { create(:custom_role, account: account, permissions: ['knowledge_base_manage']) } + let(:agent_with_role) { create(:user) } # Create without account + let(:agent_with_role_account_user) do + create(:account_user, user: agent_with_role, account: account, role: :agent, custom_role: custom_role) + end + let(:agent_with_role_context) do + { user: agent_with_role, account: account, account_user: agent_with_role_account_user } + end + + permissions :update?, :edit?, :logo? do + context 'when agent with knowledge_base_manage permission' do + it { expect(portal_policy).to permit(agent_with_role_context, portal) } + end + end + + permissions :create?, :destroy? do + context 'when agent with knowledge_base_manage permission' do + it { expect(portal_policy).not_to permit(agent_with_role_context, portal) } + end + end +end diff --git a/spec/enterprise/policies/report_policy_spec.rb b/spec/enterprise/policies/report_policy_spec.rb new file mode 100644 index 000000000..0d87c22d7 --- /dev/null +++ b/spec/enterprise/policies/report_policy_spec.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Enterprise::ReportPolicy', type: :policy do + subject(:report_policy) { ReportPolicy } + + let(:account) { create(:account) } + let(:report) { :report } + + # Create a custom role with report_manage permission + let(:custom_role) { create(:custom_role, account: account, permissions: ['report_manage']) } + let(:agent_with_role) { create(:user) } # Create without account + let(:agent_with_role_account_user) do + create(:account_user, user: agent_with_role, account: account, role: :agent, custom_role: custom_role) + end + let(:agent_with_role_context) do + { user: agent_with_role, account: account, account_user: agent_with_role_account_user } + end + + permissions :view? do + context 'when agent with report_manage permission' do + it { expect(report_policy).to permit(agent_with_role_context, report) } + end + end +end diff --git a/enterprise/spec/services/enterprise/conversations/permission_filter_service_spec.rb b/spec/enterprise/services/enterprise/conversations/permission_filter_service_spec.rb similarity index 100% rename from enterprise/spec/services/enterprise/conversations/permission_filter_service_spec.rb rename to spec/enterprise/services/enterprise/conversations/permission_filter_service_spec.rb diff --git a/spec/factories/portal_members.rb b/spec/factories/portal_members.rb deleted file mode 100644 index 9cab7b054..000000000 --- a/spec/factories/portal_members.rb +++ /dev/null @@ -1,6 +0,0 @@ -FactoryBot.define do - factory :portal_member do - portal - user - end -end diff --git a/spec/models/portal_member_spec.rb b/spec/models/portal_member_spec.rb deleted file mode 100644 index 646ff9c27..000000000 --- a/spec/models/portal_member_spec.rb +++ /dev/null @@ -1,8 +0,0 @@ -require 'rails_helper' - -RSpec.describe PortalMember do - describe 'associations' do - it { is_expected.to belong_to(:portal) } - it { is_expected.to belong_to(:user) } - end -end diff --git a/spec/models/portal_spec.rb b/spec/models/portal_spec.rb index 1b33c8d90..1a108bbd6 100644 --- a/spec/models/portal_spec.rb +++ b/spec/models/portal_spec.rb @@ -12,8 +12,6 @@ RSpec.describe Portal do it { is_expected.to have_many(:categories) } it { is_expected.to have_many(:folders) } it { is_expected.to have_many(:articles) } - it { is_expected.to have_many(:portal_members) } - it { is_expected.to have_many(:members) } it { is_expected.to have_many(:inboxes) } end diff --git a/spec/policies/article_policy_spec.rb b/spec/policies/article_policy_spec.rb new file mode 100644 index 000000000..2c1b5f9d1 --- /dev/null +++ b/spec/policies/article_policy_spec.rb @@ -0,0 +1,34 @@ +require 'rails_helper' + +RSpec.describe ArticlePolicy, type: :policy do + subject(:article_policy) { described_class } + + let(:account) { create(:account) } + let(:administrator) { create(:user, :administrator, account: account) } + let(:agent) { create(:user, account: account) } + let(:portal) { create(:portal, account: account) } + let(:article) { create(:article, account: account, portal: portal, author: administrator) } + + let(:administrator_context) { { user: administrator, account: account, account_user: account.account_users.first } } + let(:agent_context) { { user: agent, account: account, account_user: account.account_users.first } } + + permissions :index? do + context 'when administrator' do + it { expect(article_policy).to permit(administrator_context, article) } + end + + context 'when agent' do + it { expect(article_policy).to permit(agent_context, article) } + end + end + + permissions :update?, :show?, :edit?, :create?, :destroy?, :reorder? do + context 'when administrator' do + it { expect(article_policy).to permit(administrator_context, article) } + end + + context 'when agent' do + it { expect(article_policy).not_to permit(agent_context, article) } + end + end +end diff --git a/spec/policies/category_policy_spec.rb b/spec/policies/category_policy_spec.rb new file mode 100644 index 000000000..933348635 --- /dev/null +++ b/spec/policies/category_policy_spec.rb @@ -0,0 +1,34 @@ +require 'rails_helper' + +RSpec.describe CategoryPolicy, type: :policy do + subject(:category_policy) { described_class } + + let(:account) { create(:account) } + let(:administrator) { create(:user, :administrator, account: account) } + let(:agent) { create(:user, account: account) } + let(:portal) { create(:portal, account: account) } + let(:category) { create(:category, account: account, portal: portal, slug: 'test-category') } + + let(:administrator_context) { { user: administrator, account: account, account_user: account.account_users.first } } + let(:agent_context) { { user: agent, account: account, account_user: account.account_users.first } } + + permissions :index? do + context 'when administrator' do + it { expect(category_policy).to permit(administrator_context, category) } + end + + context 'when agent' do + it { expect(category_policy).to permit(agent_context, category) } + end + end + + permissions :update?, :show?, :edit?, :create?, :destroy? do + context 'when administrator' do + it { expect(category_policy).to permit(administrator_context, category) } + end + + context 'when agent' do + it { expect(category_policy).not_to permit(agent_context, category) } + end + end +end diff --git a/spec/policies/portal_policy_spec.rb b/spec/policies/portal_policy_spec.rb new file mode 100644 index 000000000..061e8b97e --- /dev/null +++ b/spec/policies/portal_policy_spec.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe PortalPolicy, type: :policy do + subject(:portal_policy) { described_class } + + let(:account) { create(:account) } + let(:administrator) { create(:user, :administrator, account: account) } + let(:agent) { create(:user, account: account) } + let(:portal) { create(:portal, account: account) } + + let(:administrator_context) { { user: administrator, account: account, account_user: account.account_users.first } } + let(:agent_context) { { user: agent, account: account, account_user: account.account_users.first } } + + permissions :index?, :show? do + context 'when administrator' do + it { expect(portal_policy).to permit(administrator_context, portal) } + end + + context 'when agent' do + it { expect(portal_policy).to permit(agent_context, portal) } + end + end + + permissions :update?, :edit?, :create?, :destroy?, :logo? do + context 'when administrator' do + it { expect(portal_policy).to permit(administrator_context, portal) } + end + + context 'when agent' do + it { expect(portal_policy).not_to permit(agent_context, portal) } + end + end +end diff --git a/spec/policies/report_policy_spec.rb b/spec/policies/report_policy_spec.rb new file mode 100644 index 000000000..fde467bd8 --- /dev/null +++ b/spec/policies/report_policy_spec.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe ReportPolicy, type: :policy do + subject(:report_policy) { described_class } + + let(:account) { create(:account) } + let(:administrator) { create(:user, :administrator, account: account) } + let(:agent) { create(:user, account: account) } + let(:report) { :report } + + let(:administrator_context) { { user: administrator, account: account, account_user: account.account_users.first } } + let(:agent_context) { { user: agent, account: account, account_user: account.account_users.first } } + + permissions :view? do + context 'when administrator' do + it { expect(report_policy).to permit(administrator_context, report) } + end + + context 'when agent' do + it { expect(report_policy).not_to permit(agent_context, report) } + end + end +end