diff --git a/app/controllers/api/v1/accounts/labels_controller.rb b/app/controllers/api/v1/accounts/labels_controller.rb index c9f15bdae..5db0fb87b 100644 --- a/app/controllers/api/v1/accounts/labels_controller.rb +++ b/app/controllers/api/v1/accounts/labels_controller.rb @@ -1,10 +1,38 @@ class Api::V1::Accounts::LabelsController < Api::BaseController - # list all labels in account + before_action :current_account + before_action :fetch_label, except: [:index, :create] + before_action :check_authorization + def index - @labels = current_account.all_conversation_tags + @labels = policy_scope(current_account.labels) end - def most_used - @labels = ActsAsTaggableOn::Tag.most_used(params[:count] || 10) + def show; end + + def create + @label = current_account.labels.create!(permitted_params) + end + + def update + @label.update(permitted_params) + end + + def destroy + @label.destroy + head :ok + end + + private + + def fetch_label + @label = current_account.labels.find(params[:id]) + end + + def check_authorization + authorize(Label) + end + + def permitted_params + params.require(:label).permit(:title, :description, :color, :show_on_sidebar) end end diff --git a/app/models/account.rb b/app/models/account.rb index 42dcf75ae..dbae201d3 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -45,6 +45,7 @@ class Account < ApplicationRecord has_many :web_widgets, dependent: :destroy, class_name: '::Channel::WebWidget' has_many :canned_responses, dependent: :destroy has_many :webhooks, dependent: :destroy + has_many :labels, dependent: :destroy has_one :subscription, dependent: :destroy has_many :notification_settings, dependent: :destroy has_flags ACCOUNT_SETTINGS_FLAGS.merge(column: 'settings_flags').merge(DEFAULT_QUERY_SETTING) diff --git a/app/models/label.rb b/app/models/label.rb new file mode 100644 index 000000000..087e07637 --- /dev/null +++ b/app/models/label.rb @@ -0,0 +1,20 @@ +# == Schema Information +# +# Table name: labels +# +# id :bigint not null, primary key +# color :string +# description :text +# show_on_sidebar :boolean +# title :string +# created_at :datetime not null +# updated_at :datetime not null +# account_id :bigint +# +# Indexes +# +# index_labels_on_account_id (account_id) +# +class Label < ApplicationRecord + belongs_to :account +end diff --git a/app/policies/label_policy.rb b/app/policies/label_policy.rb new file mode 100644 index 000000000..986044ce6 --- /dev/null +++ b/app/policies/label_policy.rb @@ -0,0 +1,17 @@ +class LabelPolicy < ApplicationPolicy + def index? + @account_user.administrator? + end + + def update? + @account_user.administrator? + end + + def show? + @account_user.administrator? + end + + def create? + @account_user.administrator? + end +end diff --git a/app/views/api/v1/accounts/labels/create.json.jbuilder b/app/views/api/v1/accounts/labels/create.json.jbuilder new file mode 100644 index 000000000..edeff661f --- /dev/null +++ b/app/views/api/v1/accounts/labels/create.json.jbuilder @@ -0,0 +1,5 @@ +json.id @label.id +json.title @label.title +json.description @label.description +json.color @label.color +json.show_on_sidebar @label.show_on_sidebar diff --git a/app/views/api/v1/accounts/labels/index.json.jbuilder b/app/views/api/v1/accounts/labels/index.json.jbuilder index 13f99090d..ddff73eec 100644 --- a/app/views/api/v1/accounts/labels/index.json.jbuilder +++ b/app/views/api/v1/accounts/labels/index.json.jbuilder @@ -1,8 +1,9 @@ -json.data do - json.meta do - end - - json.payload do - json.labels @labels +json.payload do + json.array! @labels do |label| + json.id label.id + json.title label.title + json.description label.description + json.color label.color + json.show_on_sidebar label.show_on_sidebar end end diff --git a/app/views/api/v1/accounts/labels/most_used.json.jbuilder b/app/views/api/v1/accounts/labels/most_used.json.jbuilder deleted file mode 100644 index c411b47ed..000000000 --- a/app/views/api/v1/accounts/labels/most_used.json.jbuilder +++ /dev/null @@ -1,3 +0,0 @@ -json.payload do - json.labels @labels -end diff --git a/app/views/api/v1/accounts/labels/show.json.jbuilder b/app/views/api/v1/accounts/labels/show.json.jbuilder new file mode 100644 index 000000000..edeff661f --- /dev/null +++ b/app/views/api/v1/accounts/labels/show.json.jbuilder @@ -0,0 +1,5 @@ +json.id @label.id +json.title @label.title +json.description @label.description +json.color @label.color +json.show_on_sidebar @label.show_on_sidebar diff --git a/app/views/api/v1/accounts/labels/update.json.jbuilder b/app/views/api/v1/accounts/labels/update.json.jbuilder new file mode 100644 index 000000000..edeff661f --- /dev/null +++ b/app/views/api/v1/accounts/labels/update.json.jbuilder @@ -0,0 +1,5 @@ +json.id @label.id +json.title @label.title +json.description @label.description +json.color @label.color +json.show_on_sidebar @label.show_on_sidebar diff --git a/config/routes.rb b/config/routes.rb index 60b5c9736..dc1172660 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -76,12 +76,8 @@ Rails.application.routes.draw do post :set_agent_bot, on: :member end resources :inbox_members, only: [:create, :show], param: :inbox_id - resources :labels, only: [:index] do - collection do - get :most_used - end - end + resources :labels, only: [:index, :show, :create, :update, :destroy] resources :notifications, only: [:index, :update] resource :notification_settings, only: [:show, :update] diff --git a/db/migrate/20200606132552_create_labels.rb b/db/migrate/20200606132552_create_labels.rb new file mode 100644 index 000000000..81ac698e9 --- /dev/null +++ b/db/migrate/20200606132552_create_labels.rb @@ -0,0 +1,13 @@ +class CreateLabels < ActiveRecord::Migration[6.0] + def change + create_table :labels do |t| + t.string :title + t.text :description + t.string :color + t.boolean :show_on_sidebar + t.references :account, index: true + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 1509a912a..1ef9c48e1 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.define(version: 2020_05_22_115645) do +ActiveRecord::Schema.define(version: 2020_06_06_132552) do # These are extensions that must be enabled in order to support this database enable_extension "pg_stat_statements" @@ -256,6 +256,17 @@ ActiveRecord::Schema.define(version: 2020_05_22_115645) do t.index ["name", "created_at"], name: "index_installation_configs_on_name_and_created_at", unique: true end + create_table "labels", force: :cascade do |t| + t.string "title" + t.text "description" + t.string "color" + t.boolean "show_on_sidebar" + t.bigint "account_id" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["account_id"], name: "index_labels_on_account_id" + end + create_table "messages", id: :serial, force: :cascade do |t| t.text "content" t.integer "account_id", null: false diff --git a/spec/controllers/api/v1/accounts/labels_controller_spec.rb b/spec/controllers/api/v1/accounts/labels_controller_spec.rb index a3d6fb347..3958390ab 100644 --- a/spec/controllers/api/v1/accounts/labels_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/labels_controller_spec.rb @@ -1,12 +1,8 @@ require 'rails_helper' RSpec.describe 'Label API', type: :request do - let(:account) { create(:account) } - let(:conversation) { create(:conversation, account: account) } - - before do - conversation.update_labels('label1, label2') - end + let!(:account) { create(:account) } + let!(:label) { create(:label, account: account) } describe 'GET /api/v1/accounts/{account.id}/labels' do context 'when it is an unauthenticated user' do @@ -18,7 +14,7 @@ RSpec.describe 'Label API', type: :request do end context 'when it is an authenticated user' do - let(:agent) { create(:user, account: account, role: :agent) } + let(:agent) { create(:user, account: account, role: :administrator) } it 'returns all the labels in account' do get "/api/v1/accounts/#{account.id}/labels", @@ -26,33 +22,82 @@ RSpec.describe 'Label API', type: :request do as: :json expect(response).to have_http_status(:success) - expect(response.body).to include('label1') - expect(response.body).to include('label2') + expect(response.body).to include(label.title) end end end - describe 'GET /api/v1/accounts/{account.id}/labels/most_used' do + describe 'GET /api/v1/accounts/{account.id}/labels/:id' do context 'when it is an unauthenticated user' do it 'returns unauthorized' do - get "/api/v1/accounts/#{account.id}/labels" + get "/api/v1/accounts/#{account.id}/labels/#{label.id}" expect(response).to have_http_status(:unauthorized) end end context 'when it is an authenticated user' do - let(:agent) { create(:user, account: account, role: :agent) } + let(:admin) { create(:user, account: account, role: :administrator) } - it 'returns most used labels' do - get "/api/v1/accounts/#{account.id}/labels/most_used", - headers: agent.create_new_auth_token, - params: { count: 1 }, + it 'shows the contact' do + get "/api/v1/accounts/#{account.id}/labels/#{label.id}", + headers: admin.create_new_auth_token, as: :json expect(response).to have_http_status(:success) - expect(response.body).to include('label1') - expect(response.body).not_to include('label2') + expect(response.body).to include(label.title) + end + end + end + + describe 'POST /api/v1/accounts/{account.id}/labels' do + let(:valid_params) { { label: { title: 'test' } } } + + context 'when it is an unauthenticated user' do + it 'returns unauthorized' do + expect { post "/api/v1/accounts/#{account.id}/labels", params: valid_params }.to change(Label, :count).by(0) + + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated user' do + let(:admin) { create(:user, account: account, role: :administrator) } + + it 'creates the contact' do + expect do + post "/api/v1/accounts/#{account.id}/labels", headers: admin.create_new_auth_token, + params: valid_params + end.to change(Label, :count).by(1) + + expect(response).to have_http_status(:success) + end + end + end + + describe 'PATCH /api/v1/accounts/{account.id}/labels/:id' do + let(:valid_params) { { title: 'Test 2' } } + + context 'when it is an unauthenticated user' do + it 'returns unauthorized' do + put "/api/v1/accounts/#{account.id}/labels/#{label.id}", + params: valid_params + + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated user' do + let(:admin) { create(:user, account: account, role: :administrator) } + + it 'updates the label' do + patch "/api/v1/accounts/#{account.id}/labels/#{label.id}", + headers: admin.create_new_auth_token, + params: valid_params, + as: :json + + expect(response).to have_http_status(:success) + expect(label.reload.title).to eq('Test 2') end end end diff --git a/spec/factories/labels.rb b/spec/factories/labels.rb new file mode 100644 index 000000000..4602a8d1d --- /dev/null +++ b/spec/factories/labels.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :label do + account + sequence(:title) { |n| "Label #{n}" } + end +end diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb new file mode 100644 index 000000000..f44b4e07e --- /dev/null +++ b/spec/models/label_spec.rb @@ -0,0 +1,7 @@ +require 'rails_helper' + +RSpec.describe Label, type: :model do + describe 'associations' do + it { is_expected.to belong_to(:account) } + end +end