chore: Apply fixes for items in rubocop_todo [CW-1806] (#8864)

This PR addresses several items listed in our rubocop_todo by implementing the necessary corrections and enhancements. As a result, we are now able to remove the rubocop_todo file entirely, streamlining our codebase and ensuring adherence to our coding standards.

fixes: https://linear.app/chatwoot/issue/CW-1806/chore-rubocop-audit
This commit is contained in:
Sojan Jose
2024-02-07 13:36:04 +04:00
committed by GitHub
parent 3abb887445
commit 7776b74126
21 changed files with 67 additions and 398 deletions

View File

@@ -2,7 +2,6 @@ require:
- rubocop-performance - rubocop-performance
- rubocop-rails - rubocop-rails
- rubocop-rspec - rubocop-rspec
inherit_from: .rubocop_todo.yml
Layout/LineLength: Layout/LineLength:
Max: 150 Max: 150
@@ -12,7 +11,8 @@ Metrics/ClassLength:
Exclude: Exclude:
- 'app/models/message.rb' - 'app/models/message.rb'
- 'app/models/conversation.rb' - 'app/models/conversation.rb'
Metrics/MethodLength:
Max: 19
RSpec/ExampleLength: RSpec/ExampleLength:
Max: 25 Max: 25
Style/Documentation: Style/Documentation:
@@ -50,6 +50,7 @@ Lint/OrAssignmentToConstant:
Exclude: Exclude:
- 'lib/redis/config.rb' - 'lib/redis/config.rb'
Metrics/BlockLength: Metrics/BlockLength:
Max: 30
Exclude: Exclude:
- spec/**/* - spec/**/*
- '**/routes.rb' - '**/routes.rb'
@@ -102,84 +103,31 @@ RSpec/FactoryBot/SyntaxMethods:
Enabled: false Enabled: false
Naming/VariableNumber: Naming/VariableNumber:
Enabled: false Enabled: false
Metrics/MethodLength: Naming/MemoizedInstanceVariableName:
Exclude: Exclude:
- 'db/migrate/20161123131628_devise_token_auth_create_users.rb' - 'app/models/message.rb'
- 'db/migrate/20211219031453_update_foreign_keys_on_delete.rb'
Rails/CreateTableWithTimestamps:
Exclude:
- 'db/migrate/20170207092002_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb'
Style/GuardClause: Style/GuardClause:
Exclude: Exclude:
- 'app/builders/account_builder.rb' - 'app/builders/account_builder.rb'
- 'app/models/attachment.rb' - 'app/models/attachment.rb'
- 'app/models/message.rb' - 'app/models/message.rb'
- 'db/migrate/20190819005836_add_missing_indexes_on_taggings.acts_as_taggable_on_engine.rb'
Metrics/AbcSize: Metrics/AbcSize:
Max: 26
Exclude: Exclude:
- 'app/controllers/concerns/auth_helper.rb' - 'app/controllers/concerns/auth_helper.rb'
- 'db/migrate/20190819005836_add_missing_indexes_on_taggings.acts_as_taggable_on_engine.rb'
- 'db/migrate/20161123131628_devise_token_auth_create_users.rb'
- 'app/controllers/api/v1/accounts/inboxes_controller.rb'
- 'db/migrate/20211219031453_update_foreign_keys_on_delete.rb'
Metrics/CyclomaticComplexity:
Max: 7
Exclude:
- 'db/migrate/20190819005836_add_missing_indexes_on_taggings.acts_as_taggable_on_engine.rb'
Rails/ReversibleMigration:
Exclude:
- 'db/migrate/20161025070152_removechannelsfrommodels.rb'
- 'db/migrate/20161025070645_remchannel.rb'
- 'db/migrate/20161025070645_remchannel.rb'
- 'db/migrate/20161110102609_removeinboxid.rb'
- 'db/migrate/20170519091539_add_avatar_to_fb.rb'
- 'db/migrate/20191020085608_rename_old_tables.rb'
- 'db/migrate/20191126185833_update_user_invite_foreign_key.rb'
- 'db/migrate/20191130164019_add_template_type_to_messages.rb'
- 'db/migrate/20210513083044_remove_not_null_from_webhook_url_channel_api.rb'
Rails/BulkChangeTable:
Exclude:
- 'db/migrate/20161025070152_removechannelsfrommodels.rb'
- 'db/migrate/20200121190901_create_account_users.rb'
- 'db/migrate/20170211092540_notnullableusers.rb'
- 'db/migrate/20170403095203_contactadder.rb'
- 'db/migrate/20170406104018_add_default_status_conv.rb'
- 'db/migrate/20170511134418_latlong.rb'
- 'db/migrate/20191027054756_create_contact_inboxes.rb'
- 'db/migrate/20191130164019_add_template_type_to_messages.rb'
- 'db/migrate/20210425093724_convert_integration_hook_settings_field.rb'
Rails/UniqueValidationWithoutIndex: Rails/UniqueValidationWithoutIndex:
Exclude: Exclude:
- 'app/models/channel/twitter_profile.rb' - 'app/models/channel/twitter_profile.rb'
- 'app/models/webhook.rb' - 'app/models/webhook.rb'
- 'app/models/contact.rb' - 'app/models/contact.rb'
- 'app/models/integrations/hook.rb' - 'app/models/integrations/hook.rb'
- 'app/models/canned_response.rb'
- 'app/models/telegram_bot.rb'
Rails/RenderInline: Rails/RenderInline:
Exclude: Exclude:
- 'app/controllers/swagger_controller.rb' - 'app/controllers/swagger_controller.rb'
Performance/CollectionLiteralInLoop:
Exclude:
- 'db/migrate/20210315101919_enable_email_channel.rb'
Rails/ThreeStateBooleanColumn: Rails/ThreeStateBooleanColumn:
Exclude: Exclude:
- 'db/migrate/20200509044639_add_hide_input_flag_to_bot_config.rb'
- 'db/migrate/20200605130625_agent_away_message_to_auto_reply.rb'
- 'db/migrate/20200606132552_create_labels.rb'
- 'db/migrate/20201027135006_create_working_hours.rb'
- 'db/migrate/20210112174124_add_hmac_token_to_inbox.rb'
- 'db/migrate/20210114202310_create_teams.rb'
- 'db/migrate/20210212154240_add_request_for_email_on_channel_web_widget.rb'
- 'db/migrate/20210428135041_add_campaigns.rb'
- 'db/migrate/20210602182058_add_hmac_to_api_channel.rb'
- 'db/migrate/20210609133433_add_email_collect_to_inboxes.rb'
- 'db/migrate/20210618095823_add_csat_toggle_for_inbox.rb'
- 'db/migrate/20210927062350_add_trigger_only_during_business_hours_collect_to_campaigns.rb'
- 'db/migrate/20211027073553_add_imap_smtp_config_to_channel_email.rb'
- 'db/migrate/20211109143122_add_tweet_enabled_flag_to_twitter_channel.rb'
- 'db/migrate/20211216110209_add_allow_messages_after_resolved_to_inbox.rb'
- 'db/migrate/20220116103902_add_open_ssl_verify_mode_to_channel_email.rb'
- 'db/migrate/20220216151613_add_open_all_day_to_working_hour.rb'
- 'db/migrate/20220511072655_add_archive_column_to_portal.rb'
- 'db/migrate/20230503101201_create_sla_policies.rb' - 'db/migrate/20230503101201_create_sla_policies.rb'
RSpec/IndexedLet: RSpec/IndexedLet:
Enabled: false Enabled: false
@@ -187,6 +135,8 @@ RSpec/NamedSubject:
Enabled: false Enabled: false
# we should bring this down # we should bring this down
RSpec/MultipleExpectations:
Max: 7
RSpec/MultipleMemoizedHelpers: RSpec/MultipleMemoizedHelpers:
Max: 14 Max: 14

View File

@@ -1,287 +0,0 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2019-10-23 16:47:02 +0530 using RuboCop version 0.73.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
# Offense count: 1
Lint/DuplicateMethods:
Exclude:
- 'app/controllers/api/v1/reports_controller.rb'
# Offense count: 1
Lint/RescueException:
Exclude:
- 'app/builders/messages/message_builder.rb'
# Offense count: 4
Lint/ShadowingOuterLocalVariable:
Exclude:
- 'app/controllers/api/v1/reports_controller.rb'
# Offense count: 3
# Configuration parameters: AllowKeywordBlockArguments.
Lint/UnderscorePrefixedVariableName:
Exclude:
- 'app/models/account.rb'
- 'deploy/before_symlink.rb'
# Offense count: 18
Lint/UselessAssignment:
Exclude:
- 'app/controllers/api/v1/callbacks_controller.rb'
- 'app/controllers/api/v1/facebook_indicators_controller.rb'
- 'app/listeners/action_cable_listener.rb'
- 'app/listeners/reporting_listener.rb'
- 'app/models/channel/facebook_page.rb'
- 'app/models/facebook_page.rb'
# Offense count: 14
Metrics/AbcSize:
Max: 26
# Offense count: 1
# Configuration parameters: CountComments, ExcludedMethods.
# ExcludedMethods: refine
Metrics/BlockLength:
Max: 30
# Offense count: 2
Metrics/CyclomaticComplexity:
Max: 7
# Offense count: 10
# Configuration parameters: CountComments, ExcludedMethods.
Metrics/MethodLength:
Max: 19
# Offense count: 1
Metrics/PerceivedComplexity:
Max: 8
# Offense count: 6
Naming/AccessorMethodName:
Exclude:
- 'app/builders/report_builder.rb'
- 'app/controllers/api/v1/accounts_controller.rb'
- 'app/controllers/api/v1/callbacks_controller.rb'
- 'app/controllers/api/v1/conversations_controller.rb'
# Offense count: 9
# Configuration parameters: EnforcedStyleForLeadingUnderscores.
# SupportedStylesForLeadingUnderscores: disallowed, required, optional
Naming/MemoizedInstanceVariableName:
Exclude:
- 'app/controllers/api/base_controller.rb'
- 'app/controllers/api/v1/conversations_controller.rb'
- 'app/controllers/api/v1/webhooks_controller.rb'
- 'app/controllers/application_controller.rb'
- 'app/models/message.rb'
- 'lib/integrations/widget/outgoing_message_builder.rb'
# Offense count: 4
# Cop supports --auto-correct.
# Configuration parameters: MaxKeyValuePairs.
Performance/RedundantMerge:
Exclude:
- 'app/controllers/api/v1/callbacks_controller.rb'
- 'app/models/message.rb'
# Offense count: 1
# Cop supports --auto-correct.
Performance/StringReplacement:
Exclude:
- 'lib/events/base.rb'
# Offense count: 4
# Configuration parameters: Prefixes.
# Prefixes: when, with, without
RSpec/ContextWording:
Exclude:
- 'spec/models/contact_spec.rb'
- 'spec/models/user_spec.rb'
# Offense count: 1
RSpec/DescribeClass:
Exclude:
- 'spec/mailers/confirmation_instructions_spec.rb'
# Offense count: 1
RSpec/DescribeSymbol:
Exclude:
- 'spec/mailers/confirmation_instructions_spec.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: AllowConsecutiveOneLiners.
RSpec/EmptyLineAfterExample:
Exclude:
- 'spec/models/user_spec.rb'
# Offense count: 1
# Configuration parameters: Max.
RSpec/ExampleLength:
Exclude:
- 'spec/models/conversation_spec.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: single_line_only, single_statement_only, disallow
RSpec/ImplicitSubject:
Exclude:
- 'spec/models/user_spec.rb'
# Offense count: 7
# Configuration parameters: AggregateFailuresByDefault.
RSpec/MultipleExpectations:
Max: 7
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: not_to, to_not
RSpec/NotToNot:
Exclude:
- 'spec/mailers/confirmation_instructions_spec.rb'
# Offense count: 1
# Configuration parameters: IgnoreNameless, IgnoreSymbolicNames.
RSpec/VerifiedDoubles:
Exclude:
- 'spec/models/conversation_spec.rb'
# Offense count: 4
# Cop supports --auto-correct.
Rails/ActiveRecordAliases:
Exclude:
- 'app/controllers/api/v1/agents_controller.rb'
- 'app/controllers/api/v1/callbacks_controller.rb'
- 'app/controllers/api/v1/canned_responses_controller.rb'
- 'app/controllers/api/v1/contacts_controller.rb'
# Offense count: 2
# Cop supports --auto-correct.
Rails/BelongsTo:
Exclude:
- 'app/models/message.rb'
- 'app/models/user.rb'
# Offense count: 6
# Cop supports --auto-correct.
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/EnumHash:
Exclude:
- 'app/models/attachment.rb'
- 'app/models/conversation.rb'
- 'app/models/message.rb'
- 'app/models/user.rb'
# Offense count: 1
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/HasManyOrHasOneDependent:
Exclude:
- 'app/models/user.rb'
# Offense count: 1
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/InverseOf:
Exclude:
- 'app/models/user.rb'
# Offense count: 1
# Configuration parameters: Include.
# Include: app/controllers/**/*.rb
Rails/LexicallyScopedActionFilter:
Exclude:
- 'app/controllers/home_controller.rb'
# Offense count: 2
# Configuration parameters: Include.
# Include: app/**/*.rb, config/**/*.rb, db/**/*.rb, lib/**/*.rb
Rails/Output:
Exclude:
- 'app/bot/bot.rb'
- 'app/builders/account_builder.rb'
# Offense count: 7
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: strict, flexible
Rails/TimeZone:
Exclude:
- 'app/builders/report_builder.rb'
- 'lib/reports/update_account_identity.rb'
- 'lib/reports/update_agent_identity.rb'
- 'lib/reports/update_identity.rb'
- 'spec/models/conversation_spec.rb'
# Offense count: 8
# Cop supports --auto-correct.
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/Validation:
Exclude:
- 'app/models/canned_response.rb'
- 'app/models/channel/facebook_page.rb'
- 'app/models/facebook_page.rb'
- 'app/models/telegram_bot.rb'
- 'app/models/user.rb'
# Offense count: 15
# Cop supports --auto-correct.
# Configuration parameters: AutoCorrect, EnforcedStyle.
# SupportedStyles: nested, compact
Style/ClassAndModuleChildren:
Exclude:
- 'app/builders/messages/message_builder.rb'
- 'app/controllers/api/v1/inbox_members_controller.rb'
- 'app/models/channel/facebook_page.rb'
- 'app/models/channel/web_widget.rb'
- 'app/presenters/conversations/event_data_presenter.rb'
- 'app/services/facebook/send_reply_service.rb'
- 'lib/integrations/facebook/delivery_status.rb'
- 'lib/integrations/facebook/message_creator.rb'
- 'lib/integrations/facebook/message_parser.rb'
- 'lib/integrations/widget/incoming_message_builder.rb'
# Offense count: 4
Style/CommentedKeyword:
Exclude:
- 'app/controllers/api/v1/callbacks_controller.rb'
- 'app/controllers/api/v1/conversations/assignments_controller.rb'
- 'app/controllers/api/v1/conversations/labels_controller.rb'
- 'app/controllers/api/v1/labels_controller.rb'
# Offense count: 1
# Configuration parameters: AllowIfModifier.
Style/IfInsideElse:
Exclude:
- 'app/finders/conversation_finder.rb'
# Offense count: 1
Style/MixinUsage:
Exclude:
- 'app/bot/bot.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: AutoCorrect, EnforcedStyle, IgnoredMethods.
# SupportedStyles: predicate, comparison
Style/NumericPredicate:
Exclude:
- 'spec/**/*'
- 'app/controllers/api/v1/callbacks_controller.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: implicit, explicit
Style/RescueStandardError:
Exclude:
- 'app/models/channel/facebook_page.rb'

View File

@@ -15,7 +15,7 @@ class AccountBuilder
end end
[@user, @account] [@user, @account]
rescue StandardError => e rescue StandardError => e
puts e.inspect Rails.logger.debug e.inspect
raise e raise e
end end

View File

@@ -40,7 +40,7 @@ class Api::V1::AccountsController < Api::BaseController
def cache_keys def cache_keys
expires_in 10.seconds, public: false, stale_while_revalidate: 5.minutes expires_in 10.seconds, public: false, stale_while_revalidate: 5.minutes
render json: { cache_keys: get_cache_keys }, status: :ok render json: { cache_keys: cache_keys_for_account }, status: :ok
end end
def update def update
@@ -66,7 +66,7 @@ class Api::V1::AccountsController < Api::BaseController
raise CustomExceptions::Account::InvalidParams.new({}) raise CustomExceptions::Account::InvalidParams.new({})
end end
def get_cache_keys def cache_keys_for_account
{ {
label: fetch_value_for_key(params[:id], Label.name.underscore), label: fetch_value_for_key(params[:id], Label.name.underscore),
inbox: fetch_value_for_key(params[:id], Inbox.name.underscore), inbox: fetch_value_for_key(params[:id], Inbox.name.underscore),

View File

@@ -100,7 +100,7 @@ class Account < ApplicationRecord
.where(context: 'labels', .where(context: 'labels',
taggable_type: 'Conversation', taggable_type: 'Conversation',
taggable_id: conversation_ids) taggable_id: conversation_ids)
.map { |_| _.tag.name } .map { |tagging| tagging.tag.name }
end end
def webhook_data def webhook_data

View File

@@ -43,7 +43,7 @@ class Article < ApplicationRecord
belongs_to :account belongs_to :account
belongs_to :category, optional: true belongs_to :category, optional: true
belongs_to :portal belongs_to :portal
belongs_to :author, class_name: 'User' belongs_to :author, class_name: 'User', inverse_of: :articles
before_validation :ensure_account_id before_validation :ensure_account_id
before_validation :ensure_article_slug before_validation :ensure_article_slug

View File

@@ -38,7 +38,8 @@ class Attachment < ApplicationRecord
has_one_attached :file has_one_attached :file
validate :acceptable_file validate :acceptable_file
validates :external_url, length: { maximum: Limits::URL_LENGTH_LIMIT } validates :external_url, length: { maximum: Limits::URL_LENGTH_LIMIT }
enum file_type: [:image, :audio, :video, :file, :location, :fallback, :share, :story_mention, :contact] enum file_type: { :image => 0, :audio => 1, :video => 2, :file => 3, :location => 4, :fallback => 5, :share => 6, :story_mention => 7,
:contact => 8 }
def push_event_data def push_event_data
return unless file_type return unless file_type

View File

@@ -11,10 +11,10 @@
# #
class CannedResponse < ApplicationRecord class CannedResponse < ApplicationRecord
validates_presence_of :content validates :content, presence: true
validates_presence_of :short_code validates :short_code, presence: true
validates_presence_of :account validates :account, presence: true
validates_uniqueness_of :short_code, scope: :account_id validates :short_code, uniqueness: { scope: :account_id }
belongs_to :account belongs_to :account

View File

@@ -46,20 +46,20 @@ class Channel::FacebookPage < ApplicationRecord
def subscribe def subscribe
# ref https://developers.facebook.com/docs/messenger-platform/reference/webhook-events # ref https://developers.facebook.com/docs/messenger-platform/reference/webhook-events
response = Facebook::Messenger::Subscriptions.subscribe( Facebook::Messenger::Subscriptions.subscribe(
access_token: page_access_token, access_token: page_access_token,
subscribed_fields: %w[ subscribed_fields: %w[
messages message_deliveries message_echoes message_reads standby messaging_handovers messages message_deliveries message_echoes message_reads standby messaging_handovers
] ]
) )
rescue => e rescue StandardError => e
Rails.logger.debug { "Rescued: #{e.inspect}" } Rails.logger.debug { "Rescued: #{e.inspect}" }
true true
end end
def unsubscribe def unsubscribe
Facebook::Messenger::Subscriptions.unsubscribe(access_token: page_access_token) Facebook::Messenger::Subscriptions.unsubscribe(access_token: page_access_token)
rescue => e rescue StandardError => e
Rails.logger.debug { "Rescued: #{e.inspect}" } Rails.logger.debug { "Rescued: #{e.inspect}" }
true true
end end
@@ -73,6 +73,7 @@ class Channel::FacebookPage < ApplicationRecord
delete_instagram_story(message) if story_link.blank? delete_instagram_story(message) if story_link.blank?
story_link story_link
rescue Koala::Facebook::ClientError => e rescue Koala::Facebook::ClientError => e
Rails.logger.debug { "Instagram Story Expired: #{e.inspect}" }
delete_instagram_story(message) delete_instagram_story(message)
end end

View File

@@ -89,7 +89,7 @@ class Conversation < ApplicationRecord
belongs_to :account belongs_to :account
belongs_to :inbox belongs_to :inbox
belongs_to :assignee, class_name: 'User', optional: true belongs_to :assignee, class_name: 'User', optional: true, inverse_of: :assigned_conversations
belongs_to :contact belongs_to :contact
belongs_to :contact_inbox belongs_to :contact_inbox
belongs_to :team, optional: true belongs_to :team, optional: true

View File

@@ -26,7 +26,7 @@ class CsatSurveyResponse < ApplicationRecord
belongs_to :conversation belongs_to :conversation
belongs_to :contact belongs_to :contact
belongs_to :message belongs_to :message
belongs_to :assigned_agent, class_name: 'User', optional: true belongs_to :assigned_agent, class_name: 'User', optional: true, inverse_of: :csat_survey_responses
validates :rating, presence: true, inclusion: { in: [1, 2, 3, 4, 5] } validates :rating, presence: true, inclusion: { in: [1, 2, 3, 4, 5] }
validates :account_id, presence: true validates :account_id, presence: true

View File

@@ -21,7 +21,7 @@ class Macro < ApplicationRecord
belongs_to :account belongs_to :account
belongs_to :created_by, belongs_to :created_by,
class_name: :User, optional: true class_name: :User, optional: true, inverse_of: :macros
belongs_to :updated_by, belongs_to :updated_by,
class_name: :User, optional: true class_name: :User, optional: true
has_many_attached :files has_many_attached :files

View File

@@ -118,7 +118,7 @@ class Message < ApplicationRecord
belongs_to :account belongs_to :account
belongs_to :inbox belongs_to :inbox
belongs_to :conversation, touch: true belongs_to :conversation, touch: true
belongs_to :sender, polymorphic: true, required: false belongs_to :sender, polymorphic: true, optional: true
has_many :attachments, dependent: :destroy, autosave: true, before_add: :validate_attachments_limit has_many :attachments, dependent: :destroy, autosave: true, before_add: :validate_attachments_limit
has_one :csat_survey_response, dependent: :destroy_async has_one :csat_survey_response, dependent: :destroy_async
@@ -139,8 +139,8 @@ class Message < ApplicationRecord
conversation_id: conversation.display_id, conversation_id: conversation.display_id,
conversation: conversation_push_event_data conversation: conversation_push_event_data
) )
data.merge!(echo_id: echo_id) if echo_id.present? data[:echo_id] = echo_id if echo_id.present?
data.merge!(attachments: attachments.map(&:push_event_data)) if attachments.present? data[:attachments] = attachments.map(&:push_event_data) if attachments.present?
merge_sender_attributes(data) merge_sender_attributes(data)
end end
@@ -163,8 +163,8 @@ class Message < ApplicationRecord
end end
def merge_sender_attributes(data) def merge_sender_attributes(data)
data.merge!(sender: sender.push_event_data) if sender && !sender.is_a?(AgentBot) data[:sender] = sender.push_event_data if sender && !sender.is_a?(AgentBot)
data.merge!(sender: sender.push_event_data(inbox)) if sender.is_a?(AgentBot) data[:sender] = sender.push_event_data(inbox) if sender.is_a?(AgentBot)
data data
end end
@@ -184,7 +184,7 @@ class Message < ApplicationRecord
sender: sender.try(:webhook_data), sender: sender.try(:webhook_data),
source_id: source_id source_id: source_id
} }
data.merge!(attachments: attachments.map(&:push_event_data)) if attachments.present? data[:attachments] = attachments.map(&:push_event_data) if attachments.present?
data data
end end

View File

@@ -13,5 +13,5 @@
class TelegramBot < ApplicationRecord class TelegramBot < ApplicationRecord
belongs_to :account belongs_to :account
has_one :inbox, as: :channel, dependent: :destroy_async has_one :inbox, as: :channel, dependent: :destroy_async
validates_uniqueness_of :auth_key, scope: :account_id validates :auth_key, uniqueness: { scope: :account_id }
end end

View File

@@ -74,15 +74,15 @@ class User < ApplicationRecord
has_many :accounts, through: :account_users has_many :accounts, through: :account_users
accepts_nested_attributes_for :account_users accepts_nested_attributes_for :account_users
has_many :assigned_conversations, foreign_key: 'assignee_id', class_name: 'Conversation', dependent: :nullify has_many :assigned_conversations, foreign_key: 'assignee_id', class_name: 'Conversation', dependent: :nullify, inverse_of: :assignee
alias_attribute :conversations, :assigned_conversations alias_attribute :conversations, :assigned_conversations
has_many :csat_survey_responses, foreign_key: 'assigned_agent_id', dependent: :nullify has_many :csat_survey_responses, foreign_key: 'assigned_agent_id', dependent: :nullify, inverse_of: :assigned_agent
has_many :conversation_participants, dependent: :destroy_async has_many :conversation_participants, dependent: :destroy_async
has_many :participating_conversations, through: :conversation_participants, source: :conversation has_many :participating_conversations, through: :conversation_participants, source: :conversation
has_many :inbox_members, dependent: :destroy_async has_many :inbox_members, dependent: :destroy_async
has_many :inboxes, through: :inbox_members, source: :inbox has_many :inboxes, through: :inbox_members, source: :inbox
has_many :messages, as: :sender has_many :messages, as: :sender, dependent: :nullify
has_many :invitees, through: :account_users, class_name: 'User', foreign_key: 'inviter_id', source: :inviter, dependent: :nullify has_many :invitees, through: :account_users, class_name: 'User', foreign_key: 'inviter_id', source: :inviter, dependent: :nullify
has_many :custom_filters, dependent: :destroy_async has_many :custom_filters, dependent: :destroy_async
@@ -94,12 +94,16 @@ class User < ApplicationRecord
has_many :notifications, dependent: :destroy_async has_many :notifications, dependent: :destroy_async
has_many :team_members, dependent: :destroy_async has_many :team_members, dependent: :destroy_async
has_many :teams, through: :team_members has_many :teams, through: :team_members
has_many :articles, foreign_key: 'author_id', dependent: :nullify has_many :articles, foreign_key: 'author_id', dependent: :nullify, inverse_of: :author
has_many :portal_members, class_name: :PortalMember, dependent: :destroy_async has_many :portal_members, class_name: :PortalMember, dependent: :destroy_async
has_many :portals, through: :portal_members, source: :portal, has_many :portals, through: :portal_members, source: :portal,
class_name: :Portal, class_name: :Portal,
dependent: :nullify dependent: :nullify
has_many :macros, foreign_key: 'created_by_id' # rubocop:disable Rails/HasManyOrHasOneDependent
# we are handling this in `remove_macros` callback
has_many :macros, foreign_key: 'created_by_id', inverse_of: :created_by
# rubocop:enable Rails/HasManyOrHasOneDependent
before_validation :set_password_and_uid, on: :create before_validation :set_password_and_uid, on: :create
after_destroy :remove_macros after_destroy :remove_macros

View File

@@ -9,6 +9,6 @@ class Events::Base
end end
def method_name def method_name
name.to_s.gsub('.', '_') name.to_s.tr('.', '_')
end end
end end

View File

@@ -16,7 +16,7 @@ class Integrations::Widget::OutgoingMessageBuilder
def perform def perform
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
build_conversation conversation
build_message build_message
end end
end end
@@ -31,19 +31,19 @@ class Integrations::Widget::OutgoingMessageBuilder
@user ||= Contact.find(options[:user_id]) @user ||= Contact.find(options[:user_id])
end end
def build_conversation def conversation
@conversation ||= Conversation.find(options[:conversation_id]) @conversation ||= Conversation.find(options[:conversation_id])
end end
def build_message def build_message
@message = @conversation.messages.new(message_params) @message = conversation.messages.new(message_params)
@message.save! @message.save!
end end
def message_params def message_params
{ {
account_id: @conversation.account_id, account_id: conversation.account_id,
inbox_id: @conversation.inbox_id, inbox_id: conversation.inbox_id,
message_type: 1, message_type: 1,
content: options[:content], content: options[:content],
sender: user sender: user

View File

@@ -2,8 +2,8 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe 'Confirmation Instructions' do RSpec.describe 'Devise::Mailer' do
describe :notify do describe 'notify' do
let(:account) { create(:account) } let(:account) { create(:account) }
let!(:confirmable_user) { create(:user, inviter: inviter_val, account: account) } let!(:confirmable_user) { create(:user, inviter: inviter_val, account: account) }
let(:inviter_val) { nil } let(:inviter_val) { nil }
@@ -26,7 +26,7 @@ RSpec.describe 'Confirmation Instructions' do
end end
it 'does not refer to the inviter and their account' do it 'does not refer to the inviter and their account' do
expect(mail.body).to_not match('has invited you to try out Chatwoot!') expect(mail.body).not_to match('has invited you to try out Chatwoot!')
expect(mail.body).to match('We have a suite of powerful tools ready for you to explore.') expect(mail.body).to match('We have a suite of powerful tools ready for you to explore.')
end end

View File

@@ -5,11 +5,11 @@ require 'rails_helper'
require Rails.root.join 'spec/models/concerns/avatarable_shared.rb' require Rails.root.join 'spec/models/concerns/avatarable_shared.rb'
RSpec.describe Contact do RSpec.describe Contact do
context 'validations' do context 'with validations' do
it { is_expected.to validate_presence_of(:account_id) } it { is_expected.to validate_presence_of(:account_id) }
end end
context 'associations' do context 'with associations' do
it { is_expected.to belong_to(:account) } it { is_expected.to belong_to(:account) }
it { is_expected.to have_many(:conversations).dependent(:destroy_async) } it { is_expected.to have_many(:conversations).dependent(:destroy_async) }
end end
@@ -18,7 +18,7 @@ RSpec.describe Contact do
it_behaves_like 'avatarable' it_behaves_like 'avatarable'
end end
context 'prepare contact attributes before validation' do context 'when prepare contact attributes before validation' do
it 'sets email to lowercase' do it 'sets email to lowercase' do
contact = create(:contact, email: 'Test@test.com') contact = create(:contact, email: 'Test@test.com')
expect(contact.email).to eq('test@test.com') expect(contact.email).to eq('test@test.com')

View File

@@ -115,7 +115,7 @@ RSpec.describe Conversation do
let!(:conversation) do let!(:conversation) do
create(:conversation, status: 'open', account: account, assignee: old_assignee) create(:conversation, status: 'open', account: account, assignee: old_assignee)
end end
let(:assignment_mailer) { double(deliver: true) } let(:assignment_mailer) { instance_double(AssignmentMailer, deliver: true) }
let(:label) { create(:label, account: account) } let(:label) { create(:label, account: account) }
before do before do
@@ -142,7 +142,7 @@ RSpec.describe Conversation do
it 'runs after_update callbacks' do it 'runs after_update callbacks' do
conversation.update( conversation.update(
status: :resolved, status: :resolved,
contact_last_seen_at: Time.now, contact_last_seen_at: Time.zone.now,
assignee: new_assignee assignee: new_assignee
) )
status_change = conversation.status_change status_change = conversation.status_change
@@ -193,7 +193,7 @@ RSpec.describe Conversation do
it 'creates conversation activities' do it 'creates conversation activities' do
conversation.update( conversation.update(
status: :resolved, status: :resolved,
contact_last_seen_at: Time.now, contact_last_seen_at: Time.zone.now,
assignee: new_assignee, assignee: new_assignee,
label_list: [label.title] label_list: [label.title]
) )
@@ -611,7 +611,7 @@ RSpec.describe Conversation do
account: conversation.account, account: conversation.account,
inbox: facebook_inbox, inbox: facebook_inbox,
conversation: conversation, conversation: conversation,
created_at: Time.now - 48.hours created_at: 48.hours.ago
) )
expect(conversation.can_reply?).to be true expect(conversation.can_reply?).to be true
@@ -626,7 +626,7 @@ RSpec.describe Conversation do
account: conversation.account, account: conversation.account,
inbox: facebook_inbox, inbox: facebook_inbox,
conversation: conversation, conversation: conversation,
created_at: Time.now - 48.hours created_at: 48.hours.ago
) )
expect(conversation.can_reply?).to be false expect(conversation.can_reply?).to be false
@@ -646,7 +646,7 @@ RSpec.describe Conversation do
account: conversation.account, account: conversation.account,
inbox: api_channel.inbox, inbox: api_channel.inbox,
conversation: conversation, conversation: conversation,
created_at: Time.now - 13.hours created_at: 13.hours.ago
) )
expect(api_channel.additional_attributes['agent_reply_time_window']).to be_nil expect(api_channel.additional_attributes['agent_reply_time_window']).to be_nil
@@ -662,7 +662,7 @@ RSpec.describe Conversation do
account: conversation.account, account: conversation.account,
inbox: api_channel_with_limit.inbox, inbox: api_channel_with_limit.inbox,
conversation: conversation, conversation: conversation,
created_at: Time.now - 13.hours created_at: 13.hours.ago
) )
expect(api_channel_with_limit.additional_attributes['agent_reply_time_window']).to eq '12' expect(api_channel_with_limit.additional_attributes['agent_reply_time_window']).to eq '12'

View File

@@ -7,11 +7,11 @@ require Rails.root.join 'spec/models/concerns/avatarable_shared.rb'
RSpec.describe User do RSpec.describe User do
let!(:user) { create(:user) } let!(:user) { create(:user) }
context 'validations' do context 'with validations' do
it { is_expected.to validate_presence_of(:email) } it { is_expected.to validate_presence_of(:email) }
end end
context 'associations' do context 'with associations' do
it { is_expected.to have_many(:accounts).through(:account_users) } it { is_expected.to have_many(:accounts).through(:account_users) }
it { is_expected.to have_many(:account_users) } it { is_expected.to have_many(:account_users) }
it { is_expected.to have_many(:assigned_conversations).class_name('Conversation').dependent(:nullify) } it { is_expected.to have_many(:assigned_conversations).class_name('Conversation').dependent(:nullify) }
@@ -33,7 +33,7 @@ RSpec.describe User do
it { expect(user.pubsub_token).not_to be_nil } it { expect(user.pubsub_token).not_to be_nil }
it { expect(user.saved_changes.keys).not_to eq('pubsub_token') } it { expect(user.saved_changes.keys).not_to eq('pubsub_token') }
context 'rotates the pubsub_token' do context 'with rotate the pubsub_token' do
it 'changes the pubsub_token when password changes' do it 'changes the pubsub_token when password changes' do
pubsub_token = user.pubsub_token pubsub_token = user.pubsub_token
user.password = Faker::Internet.password(special_characters: true) user.password = Faker::Internet.password(special_characters: true)
@@ -68,7 +68,7 @@ RSpec.describe User do
end end
end end
context 'sso_auth_token' do context 'with sso_auth_token' do
it 'can generate multiple sso tokens which can be validated' do it 'can generate multiple sso tokens which can be validated' do
sso_auth_token1 = user.generate_sso_auth_token sso_auth_token1 = user.generate_sso_auth_token
sso_auth_token2 = user.generate_sso_auth_token sso_auth_token2 = user.generate_sso_auth_token