chore: Upgrade to Rails 7 (#6719)

fixes: #6736
This commit is contained in:
Sojan Jose
2023-05-06 10:44:52 +05:30
committed by GitHub
parent 59433d9d3c
commit 022383d942
53 changed files with 1696 additions and 682 deletions

View File

@@ -7,7 +7,7 @@ defaults: &defaults
working_directory: ~/build
docker:
# specify the version you desire here
- image: cimg/ruby:3.1.3-browsers
- image: cimg/ruby:3.2.2-browsers
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images

View File

@@ -30,7 +30,7 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
npm
# Install rbenv and ruby
ARG RUBY_VERSION="3.1.3"
ARG RUBY_VERSION="3.2.2"
RUN git clone https://github.com/rbenv/rbenv.git ~/.rbenv \
&& echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc \
&& echo 'eval "$(rbenv init -)"' >> ~/.bashrc

7
.gitignore vendored
View File

@@ -67,3 +67,10 @@ test/cypress/videos/*
# yalc for local testing
.yalc
yalc.lock
/public/packs
/public/packs-test
/node_modules
/yarn-error.log
yarn-debug.log*
.yarn-integrity

View File

@@ -164,6 +164,39 @@ Performance/CollectionLiteralInLoop:
- 'db/migrate/20210315101919_enable_email_channel.rb'
RSpec/NamedSubject:
Enabled: false
Style/RedundantConstantBase:
Enabled: false
Rails/RootPathnameMethods:
Enabled: false
RSpec/Rails/MinitestAssertions:
Enabled: false
RSpec/Rails/InferredSpecType:
Enabled: false
RSpec/IndexedLet:
Enabled: false
RSpec/MatchArray:
Enabled: false
Rails/ResponseParsedBody:
Enabled: false
RSpec/FactoryBot/ConsistentParenthesesStyle:
Enabled: false
Rails/ThreeStateBooleanColumn:
Enabled: false
Rails/Pluck:
Enabled: false
Rails/TopLevelHashWithIndifferentAccess:
Enabled: false
Rails/ActionOrder:
Enabled: false
Style/ArrayIntersect:
Enabled: false
RSpec/NoExpectationExample:
Enabled: false
Style/RedundantReturn:
Enabled: false
Rails/I18nLocaleTexts:
Enabled: false
# we should bring this down
RSpec/MultipleMemoizedHelpers:
Max: 14

View File

@@ -1 +1 @@
3.1.3
3.2.2

1
.slugignore Normal file
View File

@@ -0,0 +1 @@
/spec

46
Gemfile
View File

@@ -1,10 +1,10 @@
source 'https://rubygems.org'
ruby '3.1.3'
ruby '3.2.2'
##-- base gems for rails --##
gem 'rack-cors', require: 'rack/cors'
gem 'rails', '~> 6.1', '>= 6.1.7.3'
gem 'rails', '~> 7'
# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', require: false
@@ -36,19 +36,19 @@ gem 'json_schemer'
# Rack middleware for blocking & throttling abusive requests
gem 'rack-attack'
# a utility tool for streaming, flexible and safe downloading of remote files
gem 'down', '~> 5.0'
gem 'down'
# authentication type to fetch and send mail over oauth2.0
gem 'gmail_xoauth'
# Prevent CSV injection
gem 'csv-safe'
# Support message translation
gem 'google-cloud-translate'
##-- for active storage --##
gem 'aws-sdk-s3', require: false
gem 'azure-storage-blob', require: false
# original gem isn't maintained actively
# we wanted updated version of faraday which is a dependency for slack-ruby-client
gem 'azure-storage-blob', git: 'https://github.com/chatwoot/azure-storage-ruby', branch: 'chatwoot', require: false
gem 'google-cloud-storage', require: false
gem 'image_processing', '~> 1.12.2'
gem 'image_processing'
##-- gems for database --#
gem 'groupdate'
@@ -62,13 +62,13 @@ gem 'activerecord-import'
gem 'dotenv-rails'
gem 'foreman'
gem 'puma'
gem 'webpacker', '~> 5.4', '>= 5.4.3'
gem 'webpacker'
# metrics on heroku
gem 'barnes'
##--- gems for authentication & authorization ---##
gem 'devise'
gem 'devise-secure_password', '~> 2.0', git: 'https://github.com/chatwoot/devise-secure_password'
gem 'devise-secure_password', git: 'https://github.com/chatwoot/devise-secure_password', branch: 'chatwoot'
gem 'devise_token_auth'
# authorization
gem 'jwt'
@@ -81,7 +81,6 @@ gem 'administrate'
gem 'wisper', '2.0.0'
##--- gems for channels ---##
# TODO: bump up gem to 2.0
gem 'facebook-messenger'
gem 'line-bot-api'
gem 'twilio-ruby', '~> 5.66'
@@ -91,9 +90,14 @@ gem 'twitty', '~> 0.1.5'
# facebook client
gem 'koala'
# slack client
gem 'slack-ruby-client'
gem 'slack-ruby-client', '~> 2.0.0'
# for dialogflow integrations
gem 'google-cloud-dialogflow'
gem 'google-cloud-dialogflow-v2'
gem 'grpc'
# Translate integrations
# 'google-cloud-translate' gem depends on faraday 2.0 version
# this dependency breaks the slack-ruby-client gem
gem 'google-cloud-translate-v3'
##-- apm and error monitoring ---#
# loaded only when environment variables are set.
@@ -108,9 +112,9 @@ gem 'sentry-ruby', require: false
gem 'sentry-sidekiq', require: false
##-- background job processing --##
gem 'sidekiq', '~> 6.4.2'
gem 'sidekiq'
# We want cron jobs
gem 'sidekiq-cron', '~> 1.6', '>= 1.6.0'
gem 'sidekiq-cron'
##-- Push notification service --##
gem 'fcm'
@@ -129,7 +133,10 @@ gem 'procore-sift'
# parse email
gem 'email_reply_trimmer'
gem 'html2text'
# TODO: we might have to fork this gem since 0.3.1 has hard depency on nokogir 1.10.
# and this gem hasn't been updated for a while.
gem 'html2text', git: 'https://github.com/chatwoot/html2text_ruby', branch: 'chatwoot'
# to calculate working hours
gem 'working_hours'
@@ -144,11 +151,6 @@ gem 'stripe'
## to populate db with sample data
gem 'faker'
# Can remove this in rails 7
gem 'net-imap', require: false
gem 'net-pop', require: false
gem 'net-smtp', require: false
# Include logrange conditionally in intializer using env variable
gem 'lograge', '~> 0.12.0', require: false
@@ -189,7 +191,7 @@ end
group :test do
# Cypress in rails.
gem 'cypress-on-rails', '~> 1.13', '>= 1.13.1'
gem 'cypress-on-rails'
# fast cleaning of database
gem 'database_cleaner'
# mock http calls
@@ -211,7 +213,7 @@ group :development, :test do
gem 'mock_redis'
gem 'pry-rails'
gem 'rspec_junit_formatter'
gem 'rspec-rails', '~> 5.0.3'
gem 'rspec-rails'
gem 'rubocop', require: false
gem 'rubocop-performance', require: false
gem 'rubocop-rails', require: false

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@ class ApiController < ApplicationController
def index
render json: { version: Chatwoot.config[:version],
timestamp: Time.now.utc.to_formatted_s(:db),
timestamp: Time.now.utc.to_fs(:db),
queue_services: redis_status,
data_services: postgres_status }
end

View File

@@ -41,7 +41,7 @@ class WidgetsController < ActionController::Base
source_id: @auth_token_params[:source_id]
)
@contact = @contact_inbox ? @contact_inbox.contact : nil
@contact = @contact_inbox&.contact
end
def build_contact

View File

@@ -1,6 +1,6 @@
<template>
<div v-on-clickaway="onCloseAgentList" class="bulk-action__agents">
<div class="triangle" :style="cssVars">
<div class="triangle">
<svg height="12" viewBox="0 0 24 12" width="24">
<path
d="M20 12l-8-8-12 12"
@@ -104,14 +104,13 @@ import { mapGetters } from 'vuex';
import Thumbnail from 'dashboard/components/widgets/Thumbnail.vue';
import Spinner from 'shared/components/Spinner';
import { mixin as clickaway } from 'vue-clickaway';
import bulkActionsMixin from 'dashboard/mixins/bulkActionsMixin.js';
export default {
components: {
Thumbnail,
Spinner,
},
mixins: [clickaway, bulkActionsMixin],
mixins: [clickaway],
props: {
selectedInboxes: {
type: Array,
@@ -240,7 +239,7 @@ export default {
display: block;
z-index: var(--z-index-one);
position: absolute;
top: calc(var(--space-slab) * -1);
top: var(--space-minus-slab);
right: var(--triangle-position);
text-align: left;
}

View File

@@ -58,7 +58,7 @@
<transition name="popover-animation">
<label-actions
v-if="showLabelActions"
triangle-position="8.5"
class="label-actions-box"
@assign="assignLabels"
@close="showLabelActions = false"
/>
@@ -66,12 +66,12 @@
<transition name="popover-animation">
<update-actions
v-if="showUpdateActions"
class="update-actions-box"
:selected-inboxes="selectedInboxes"
:conversation-count="conversations.length"
:show-resolve="!showResolvedAction"
:show-reopen="!showOpenAction"
:show-snooze="!showSnoozedAction"
triangle-position="5.6"
@update="updateConversations"
@close="showUpdateActions = false"
/>
@@ -79,9 +79,9 @@
<transition name="popover-animation">
<agent-selector
v-if="showAgentsList"
class="agent-actions-box"
:selected-inboxes="selectedInboxes"
:conversation-count="conversations.length"
triangle-position="2.8"
@select="submit"
@close="showAgentsList = false"
/>
@@ -89,7 +89,7 @@
<transition name="popover-animation">
<team-actions
v-if="showTeamsList"
triangle-position="0.2"
class="team-actions-box"
@assign-team="assignTeam"
@close="showTeamsList = false"
/>
@@ -247,4 +247,17 @@ export default {
opacity: 0;
transform: scale(0.95);
}
.label-actions-box {
--triangle-position: 8.5rem;
}
.update-actions-box {
--triangle-position: 5.6rem;
}
.agent-actions-box {
--triangle-position: 2.8rem;
}
.team-actions-box {
--triangle-position: 0.2rem;
}
</style>

View File

@@ -1,6 +1,6 @@
<template>
<div v-on-clickaway="onClose" class="labels-container">
<div class="triangle" :style="cssVars">
<div class="triangle">
<svg height="12" viewBox="0 0 24 12" width="24">
<path
d="M20 12l-8-8-12 12"
@@ -75,10 +75,9 @@
<script>
import { mixin as clickaway } from 'vue-clickaway';
import { mapGetters } from 'vuex';
import bulkActionsMixin from 'dashboard/mixins/bulkActionsMixin.js';
export default {
mixins: [clickaway, bulkActionsMixin],
mixins: [clickaway],
data() {
return {
query: '',
@@ -207,7 +206,7 @@ export default {
position: absolute;
right: var(--triangle-position);
text-align: left;
top: calc(var(--space-slab) * -1);
top: var(--space-minus-slab);
z-index: var(--z-index-one);
}
}

View File

@@ -1,6 +1,6 @@
<template>
<div v-on-clickaway="onClose" class="bulk-action__teams">
<div class="triangle" :style="cssVars">
<div class="triangle">
<svg height="12" viewBox="0 0 24 12" width="24">
<path
d="M20 12l-8-8-12 12"
@@ -59,9 +59,8 @@
<script>
import { mixin as clickaway } from 'vue-clickaway';
import { mapGetters } from 'vuex';
import bulkActionsMixin from 'dashboard/mixins/bulkActionsMixin.js';
export default {
mixins: [clickaway, bulkActionsMixin],
mixins: [clickaway],
data() {
return {
query: '',
@@ -141,7 +140,7 @@ export default {
display: block;
z-index: var(--z-index-one);
position: absolute;
top: calc(var(--space-slab) * -1);
top: var(--space-minus-slab);
right: var(--triangle-position);
text-align: left;
}

View File

@@ -1,6 +1,6 @@
<template>
<div v-on-clickaway="onClose" class="actions-container">
<div class="triangle" :style="cssVars">
<div class="triangle">
<svg height="12" viewBox="0 0 24 12" width="24">
<path
d="M20 12l-8-8-12 12"
@@ -45,14 +45,13 @@
import { mixin as clickaway } from 'vue-clickaway';
import WootDropdownItem from 'shared/components/ui/dropdown/DropdownItem.vue';
import WootDropdownMenu from 'shared/components/ui/dropdown/DropdownMenu.vue';
import bulkActionsMixin from 'dashboard/mixins/bulkActionsMixin.js';
export default {
components: {
WootDropdownItem,
WootDropdownMenu,
},
mixins: [clickaway, bulkActionsMixin],
mixins: [clickaway],
props: {
selectedInboxes: {
type: Array,
@@ -156,7 +155,7 @@ export default {
position: absolute;
right: var(--triangle-position);
text-align: left;
top: calc(var(--space-slab) * -1);
top: var(--space-minus-slab);
z-index: var(--z-index-one);
}
}

View File

@@ -4,7 +4,7 @@ class ApplicationMailbox < ActionMailbox::Base
# Last part is the regex for the UUID
# Eg: email should be something like : reply+6bdc3f4d-0bec-4515-a284-5d916fdde489@domain.com
REPLY_EMAIL_UUID_PATTERN = /^reply\+([0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12})$/i
CONVERSATION_MESSAGE_ID_PATTERN = %r{conversation/([a-zA-Z0-9\-]*?)/messages/(\d+?)@(\w+\.\w+)}
CONVERSATION_MESSAGE_ID_PATTERN = %r{conversation/([a-zA-Z0-9-]*?)/messages/(\d+?)@(\w+\.\w+)}
# routes as a reply to existing conversations
routing(

View File

@@ -62,7 +62,7 @@ class Attachment < ApplicationRecord
def thumb_url
if file.attached? && file.representable?
url_for(file.representation(resize: '250x250'))
url_for(file.representation(resize_to_fill: [250, nil]))
else
''
end

View File

@@ -11,7 +11,7 @@ module Avatarable
end
def avatar_url
return url_for(avatar.representation(resize: '250x250')) if avatar.attached? && avatar.representable?
return url_for(avatar.representation(resize_to_fill: [250, nil])) if avatar.attached? && avatar.representable?
''
end

View File

@@ -10,7 +10,7 @@ module Pubsubable
def pubsub_token
# backfills tokens for existing records
regenerate_pubsub_token if self[:pubsub_token].blank?
regenerate_pubsub_token if self[:pubsub_token].blank? && persisted?
self[:pubsub_token]
end
end

View File

@@ -1,3 +1,3 @@
json.identifier @inbox_channel.identifier
json.identity_validation_enabled @inbox_channel.hmac_mandatory
json.partial! 'public/api/v1/models/inbox.json.jbuilder', resource: @inbox_channel.inbox
json.partial! 'public/api/v1/models/inbox', formats: [:json], resource: @inbox_channel.inbox

View File

@@ -7,20 +7,20 @@ json.position category.position
json.related_categories do
if category.related_categories.any?
json.array! category.related_categories.each do |related_category|
json.partial! partial: 'public/api/v1/models/associated_category.json.jbuilder', category: related_category
json.partial! partial: 'public/api/v1/models/associated_category', formats: [:json], category: related_category
end
end
end
if category.parent_category.present?
json.parent_category do
json.partial! partial: 'public/api/v1/models/associated_category.json.jbuilder', category: category.parent_category
json.partial! partial: 'public/api/v1/models/associated_category', formats: [:json], category: category.parent_category
end
end
if category.root_category.present?
json.root_category do
json.partial! partial: 'public/api/v1/models/associated_category.json.jbuilder', category: category.root_category
json.partial! partial: 'public/api/v1/models/associated_category', formats: [:json], category: category.root_category
end
end

View File

@@ -1,5 +1,5 @@
json.payload do
json.array! @articles, partial: 'public/api/v1/models/article.json.jbuilder', as: :article
json.array! @articles, partial: 'public/api/v1/models/article', formats: [:json], as: :article
end
json.meta do

View File

@@ -1,3 +1,3 @@
json.payload do
json.array! @categories, partial: 'public/api/v1/models/category.json.jbuilder', as: :category
json.array! @categories, partial: 'public/api/v1/models/category', formats: [:json], as: :category
end

View File

@@ -1 +1 @@
json.array! @portals, partial: 'public/api/v1/models/portal.json.jbuilder', as: :portal
json.array! @portals, partial: 'public/api/v1/models/portal', formats: [:json], as: :portal

0
bin/validate_push Normal file → Executable file
View File

View File

@@ -30,7 +30,7 @@ end
module Chatwoot
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 6.0
config.load_defaults 7.0
config.eager_load_paths << Rails.root.join('lib')
config.eager_load_paths << Rails.root.join('enterprise/lib')
@@ -51,7 +51,7 @@ module Chatwoot
# https://stackoverflow.com/questions/72970170/upgrading-to-rails-6-1-6-1-causes-psychdisallowedclass-tried-to-load-unspecif
# https://discuss.rubyonrails.org/t/cve-2022-32224-possible-rce-escalation-bug-with-serialized-columns-in-active-record/81017
# FIX ME : fixes breakage of installation config. we need to migrate.
config.active_record.yaml_column_permitted_classes = [HashWithIndifferentAccess]
config.active_record.yaml_column_permitted_classes = [ActiveSupport::HashWithIndifferentAccess]
end
def self.config

View File

@@ -4,7 +4,7 @@ default: &default
host: <%= ENV.fetch('POSTGRES_HOST', 'localhost') %>
port: <%= ENV.fetch('POSTGRES_PORT', '5432') %>
# ref: https://github.com/mperham/sidekiq/issues/2985#issuecomment-531097962
pool: <%= Sidekiq.server? ? Sidekiq.options[:concurrency] : ENV.fetch('RAILS_MAX_THREADS', 5) %>
pool: <%= Sidekiq.server? ? ENV.fetch('SIDEKIQ_CONCURRENCY', 10) : ENV.fetch('RAILS_MAX_THREADS', 5) %>
variables:
# we are setting this value to be close to the racktimeout value. we will iterate and reduce this value going forward
statement_timeout: <%= ENV["POSTGRES_STATEMENT_TIMEOUT"] || "14s" %>

View File

@@ -1,14 +1,14 @@
# Alfred
# Add here as you use it for more features
# Used for Round Robin, Conversation Emails & Online Presence
$alfred = ConnectionPool.new(size: 5, timeout: 3) do
$alfred = ConnectionPool.new(size: 5, timeout: 1) do
redis = Rails.env.test? ? MockRedis.new : Redis.new(Redis::Config.app)
Redis::Namespace.new('alfred', redis: redis, warning: true)
end
# Velma : Determined protector
# used in rack attack
$velma = ConnectionPool.new(size: 5, timeout: 3) do
$velma = ConnectionPool.new(size: 5, timeout: 1) do
config = Rails.env.test? ? MockRedis.new : Redis.new(Redis::Config.app)
Redis::Namespace.new('velma', redis: config, warning: true)
end

View File

@@ -1,45 +0,0 @@
# Be sure to restart your server when you modify this file.
#
# This file contains migration options to ease your Rails 6.0 upgrade.
#
# Once upgraded flip defaults one by one to migrate to the new default.
#
# Read the Guide for Upgrading Ruby on Rails for more info on each option.
# Don't force requests from old versions of IE to be UTF-8 encoded.
# Rails.application.config.action_view.default_enforce_utf8 = false
# Embed purpose and expiry metadata inside signed and encrypted
# cookies for increased security.
#
# This option is not backwards compatible with earlier Rails versions.
# It's best enabled when your entire app is migrated and stable on 6.0.
# Rails.application.config.action_dispatch.use_cookies_with_metadata = true
# Change the return value of `ActionDispatch::Response#content_type` to Content-Type header without modification.
# Rails.application.config.action_dispatch.return_only_media_type_on_content_type = false
# Return false instead of self when enqueuing is aborted from a callback.
# Rails.application.config.active_job.return_false_on_aborted_enqueue = true
# Send Active Storage analysis and purge jobs to dedicated queues.
# Rails.application.config.active_storage.queues.analysis = :active_storage_analysis
# Rails.application.config.active_storage.queues.purge = :active_storage_purge
# When assigning to a collection of attachments declared via `has_many_attached`, replace existing
# attachments instead of appending. Use #attach to add new attachments without replacing existing ones.
# Rails.application.config.active_storage.replace_on_assign_to_many = true
# Use ActionMailer::MailDeliveryJob for sending parameterized and normal mail.
#
# The default delivery jobs (ActionMailer::Parameterized::DeliveryJob, ActionMailer::DeliveryJob),
# will be removed in Rails 6.1. This setting is not backwards compatible with earlier Rails versions.
# If you send mail in the background, job workers need to have a copy of
# MailDeliveryJob to ensure all delivery jobs are processed properly.
# Make sure your entire app is migrated and stable on 6.0 before using this setting.
# Rails.application.config.action_mailer.delivery_job = "ActionMailer::MailDeliveryJob"
# Enable the same cache key to be reused when the object being cached of type
# `ActiveRecord::Relation` changes by moving the volatile information (max updated at and count)
# of the relation's cache key into the cache version to support recycling cache key.
# Rails.application.config.active_record.collection_cache_versioning = true

View File

@@ -0,0 +1,11 @@
# Define an application-wide HTTP permissions policy. For further
# information see https://developers.google.com/web/updates/2018/06/feature-policy
#
# Rails.application.config.permissions_policy do |f|
# f.camera :none
# f.gyroscope :none
# f.microphone :none
# f.usb :none
# f.fullscreen :self
# f.payment :self, "https://secure.example.com"
# end

View File

@@ -4,7 +4,7 @@
# pick it up automatically.
---
:verbose: false
:concurrency: <%= ENV.fetch("SIDEKIQ_CONCURRENCY", 5) %>
:concurrency: <%= ENV.fetch("SIDEKIQ_CONCURRENCY", 10) %>
:timeout: 25
:max_retries: 3
@@ -32,4 +32,4 @@
production:
:concurrency: <%= ENV.fetch("SIDEKIQ_CONCURRENCY", 10) %>
staging:
:concurrency: <%= ENV.fetch("SIDEKIQ_CONCURRENCY", 5) %>
:concurrency: <%= ENV.fetch("SIDEKIQ_CONCURRENCY", 10) %>

View File

@@ -0,0 +1,8 @@
# This migration comes from active_storage (originally 20211119233751)
class RemoveNotNullOnActiveStorageBlobsChecksum < ActiveRecord::Migration[6.0]
def change
return unless table_exists?(:active_storage_blobs)
change_column_null(:active_storage_blobs, :checksum, true)
end
end

View File

@@ -10,8 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2023_04_26_130150) do
ActiveRecord::Schema[7.0].define(version: 2023_04_26_130150) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_stat_statements"
enable_extension "pg_trgm"
@@ -22,8 +21,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.string "owner_type"
t.bigint "owner_id"
t.string "token"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["owner_type", "owner_id"], name: "index_access_tokens_on_owner_type_and_owner_id"
t.index ["token"], name: "index_access_tokens_on_token", unique: true
end
@@ -33,9 +32,9 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.bigint "user_id"
t.integer "role", default: 0
t.bigint "inviter_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "active_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "active_at", precision: nil
t.integer "availability", default: 0, null: false
t.boolean "auto_offline", default: true, null: false
t.index ["account_id", "user_id"], name: "uniq_user_id_per_account_id", unique: true
@@ -45,8 +44,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
create_table "accounts", id: :serial, force: :cascade do |t|
t.string "name", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
t.integer "locale", default: 0
t.string "domain", limit: 100
t.string "support_email", limit: 100
@@ -62,8 +61,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.integer "status", default: 0, null: false
t.string "message_id", null: false
t.string "message_checksum", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["message_id", "message_checksum"], name: "index_action_mailbox_inbound_emails_uniqueness", unique: true
end
@@ -72,7 +71,7 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.string "record_type", null: false
t.bigint "record_id", null: false
t.bigint "blob_id", null: false
t.datetime "created_at", null: false
t.datetime "created_at", precision: nil, null: false
t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
end
@@ -83,8 +82,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.string "content_type"
t.text "metadata"
t.bigint "byte_size", null: false
t.string "checksum", null: false
t.datetime "created_at", null: false
t.string "checksum"
t.datetime "created_at", precision: nil, null: false
t.string "service_name", null: false
t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
end
@@ -99,8 +98,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.integer "inbox_id"
t.integer "agent_bot_id"
t.integer "status", default: 0
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "account_id"
end
@@ -108,8 +107,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.string "name"
t.string "description"
t.string "outgoing_url"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.bigint "account_id"
t.integer "bot_type", default: 0
t.jsonb "bot_config", default: {}
@@ -126,8 +125,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.text "content"
t.integer "status"
t.integer "views"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.bigint "author_id"
t.bigint "associated_article_id"
t.jsonb "meta", default: {}
@@ -145,8 +144,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.float "coordinates_long", default: 0.0
t.integer "message_id", null: false
t.integer "account_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
t.string "fallback_title"
t.string "extension"
t.index ["account_id"], name: "index_attachments_on_account_id"
@@ -167,7 +166,7 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.string "comment"
t.string "remote_address"
t.string "request_uuid"
t.datetime "created_at"
t.datetime "created_at", precision: nil
t.index ["associated_type", "associated_id"], name: "associated_index"
t.index ["auditable_type", "auditable_id", "version"], name: "auditable_index"
t.index ["created_at"], name: "index_audits_on_created_at"
@@ -182,8 +181,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.string "event_name", null: false
t.jsonb "conditions", default: "{}", null: false
t.jsonb "actions", default: "{}", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "active", default: true, null: false
t.index ["account_id"], name: "index_automation_rules_on_account_id"
end
@@ -198,12 +197,12 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.bigint "account_id", null: false
t.bigint "inbox_id", null: false
t.jsonb "trigger_rules", default: {}
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "campaign_type", default: 0, null: false
t.integer "campaign_status", default: 0, null: false
t.jsonb "audience", default: []
t.datetime "scheduled_at"
t.datetime "scheduled_at", precision: nil
t.boolean "trigger_only_during_business_hours", default: false
t.index ["account_id"], name: "index_campaigns_on_account_id"
t.index ["campaign_status"], name: "index_campaigns_on_campaign_status"
@@ -216,8 +215,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.integer "account_id", null: false
t.string "short_code"
t.text "content"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
end
create_table "categories", force: :cascade do |t|
@@ -226,8 +225,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.string "name"
t.text "description"
t.integer "position"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "locale", default: "en"
t.string "slug", null: false
t.bigint "parent_category_id"
@@ -242,8 +241,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
create_table "channel_api", force: :cascade do |t|
t.integer "account_id", null: false
t.string "webhook_url"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "identifier"
t.string "hmac_token"
t.boolean "hmac_mandatory", default: false
@@ -256,15 +255,15 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.integer "account_id", null: false
t.string "email", null: false
t.string "forward_to_email", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "imap_enabled", default: false
t.string "imap_address", default: ""
t.integer "imap_port", default: 0
t.string "imap_login", default: ""
t.string "imap_password", default: ""
t.boolean "imap_enable_ssl", default: true
t.datetime "imap_inbox_synced_at"
t.datetime "imap_inbox_synced_at", precision: nil
t.boolean "smtp_enabled", default: false
t.string "smtp_address", default: ""
t.integer "smtp_port", default: 0
@@ -286,8 +285,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.string "user_access_token", null: false
t.string "page_access_token", null: false
t.integer "account_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
t.string "instagram_id"
t.index ["page_id", "account_id"], name: "index_channel_facebook_pages_on_page_id_and_account_id", unique: true
t.index ["page_id"], name: "index_channel_facebook_pages_on_page_id"
@@ -298,8 +297,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.string "line_channel_id", null: false
t.string "line_channel_secret", null: false
t.string "line_channel_token", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["line_channel_id"], name: "index_channel_line_on_line_channel_id", unique: true
end
@@ -308,8 +307,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.string "phone_number", null: false
t.string "provider", default: "default"
t.jsonb "provider_config", default: {}
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["phone_number"], name: "index_channel_sms_on_phone_number", unique: true
end
@@ -317,8 +316,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.string "bot_name"
t.integer "account_id", null: false
t.string "bot_token", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["bot_token"], name: "index_channel_telegram_on_bot_token", unique: true
end
@@ -327,8 +326,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.string "auth_token", null: false
t.string "account_sid", null: false
t.integer "account_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "medium", default: 0
t.string "messaging_service_sid"
t.index ["account_sid", "phone_number"], name: "index_channel_twilio_sms_on_account_sid_and_phone_number", unique: true
@@ -341,8 +340,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.string "twitter_access_token", null: false
t.string "twitter_access_token_secret", null: false
t.integer "account_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "tweets_enabled", default: true
t.index ["account_id", "profile_id"], name: "index_channel_twitter_profiles_on_account_id_and_profile_id", unique: true
end
@@ -350,8 +349,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
create_table "channel_web_widgets", id: :serial, force: :cascade do |t|
t.string "website_url"
t.integer "account_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
t.string "website_token"
t.string "widget_color", default: "#1f93ff"
t.string "welcome_title"
@@ -372,10 +371,10 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.string "phone_number", null: false
t.string "provider", default: "default"
t.jsonb "provider_config", default: {}
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.jsonb "message_templates", default: {}
t.datetime "message_templates_last_updated"
t.datetime "message_templates_last_updated", precision: nil
t.index ["phone_number"], name: "index_channel_whatsapp_on_phone_number", unique: true
end
@@ -383,8 +382,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.bigint "contact_id"
t.bigint "inbox_id"
t.string "source_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "hmac_verified", default: false
t.string "pubsub_token"
t.index ["contact_id"], name: "index_contact_inboxes_on_contact_id"
@@ -399,12 +398,12 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.string "email"
t.string "phone_number"
t.integer "account_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
t.jsonb "additional_attributes", default: {}
t.string "identifier"
t.jsonb "custom_attributes", default: {}
t.datetime "last_activity_at"
t.datetime "last_activity_at", precision: nil
t.index "lower((email)::text), account_id", name: "index_contacts_on_lower_email_account_id"
t.index ["account_id"], name: "index_contacts_on_account_id"
t.index ["email", "account_id"], name: "uniq_email_per_account_contact", unique: true
@@ -417,8 +416,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.bigint "account_id", null: false
t.bigint "user_id", null: false
t.bigint "conversation_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["account_id"], name: "index_conversation_participants_on_account_id"
t.index ["conversation_id"], name: "index_conversation_participants_on_conversation_id"
t.index ["user_id", "conversation_id"], name: "index_conversation_participants_on_user_id_and_conversation_id", unique: true
@@ -430,23 +429,23 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.integer "inbox_id", null: false
t.integer "status", default: 0, null: false
t.integer "assignee_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
t.bigint "contact_id"
t.integer "display_id", null: false
t.datetime "contact_last_seen_at"
t.datetime "agent_last_seen_at"
t.datetime "contact_last_seen_at", precision: nil
t.datetime "agent_last_seen_at", precision: nil
t.jsonb "additional_attributes", default: {}
t.bigint "contact_inbox_id"
t.uuid "uuid", default: -> { "gen_random_uuid()" }, null: false
t.string "identifier"
t.datetime "last_activity_at", default: -> { "CURRENT_TIMESTAMP" }, null: false
t.datetime "last_activity_at", precision: nil, default: -> { "CURRENT_TIMESTAMP" }, null: false
t.bigint "team_id"
t.bigint "campaign_id"
t.datetime "snoozed_until"
t.datetime "snoozed_until", precision: nil
t.jsonb "custom_attributes", default: {}
t.datetime "assignee_last_seen_at"
t.datetime "first_reply_created_at"
t.datetime "assignee_last_seen_at", precision: nil
t.datetime "first_reply_created_at", precision: nil
t.integer "priority"
t.index ["account_id", "display_id"], name: "index_conversations_on_account_id_and_display_id", unique: true
t.index ["account_id", "id"], name: "index_conversations_on_id_and_account_id"
@@ -474,8 +473,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.text "feedback_message"
t.bigint "contact_id", null: false
t.bigint "assigned_agent_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["account_id"], name: "index_csat_survey_responses_on_account_id"
t.index ["assigned_agent_id"], name: "index_csat_survey_responses_on_assigned_agent_id"
t.index ["contact_id"], name: "index_csat_survey_responses_on_contact_id"
@@ -490,8 +489,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.integer "default_value"
t.integer "attribute_model", default: 0
t.bigint "account_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.text "attribute_description"
t.jsonb "attribute_values", default: []
t.index ["account_id"], name: "index_custom_attribute_definitions_on_account_id"
@@ -504,8 +503,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.jsonb "query", default: "{}", null: false
t.bigint "account_id", null: false
t.bigint "user_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["account_id"], name: "index_custom_filters_on_account_id"
t.index ["user_id"], name: "index_custom_filters_on_user_id"
end
@@ -515,8 +514,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.jsonb "content", default: []
t.bigint "account_id", null: false
t.bigint "user_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["account_id"], name: "index_dashboard_apps_on_account_id"
t.index ["user_id"], name: "index_dashboard_apps_on_user_id"
end
@@ -528,8 +527,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.text "processing_errors"
t.integer "total_records"
t.integer "processed_records"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["account_id"], name: "index_data_imports_on_account_id"
end
@@ -539,8 +538,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.integer "account_id"
t.integer "template_type", default: 1
t.integer "locale", default: 0, null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["name", "account_id"], name: "index_email_templates_on_name_and_account_id", unique: true
end
@@ -548,15 +547,15 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.integer "account_id", null: false
t.integer "category_id", null: false
t.string "name"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "inbox_members", id: :serial, force: :cascade do |t|
t.integer "user_id", null: false
t.integer "inbox_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
t.index ["inbox_id", "user_id"], name: "index_inbox_members_on_inbox_id_and_user_id", unique: true
t.index ["inbox_id"], name: "index_inbox_members_on_inbox_id"
end
@@ -565,8 +564,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.integer "channel_id", null: false
t.integer "account_id", null: false
t.string "name", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
t.string "channel_type"
t.boolean "enable_auto_assignment", default: true
t.boolean "greeting_enabled", default: false
@@ -589,8 +588,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
create_table "installation_configs", force: :cascade do |t|
t.string "name", null: false
t.jsonb "serialized_value", default: {}, null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "locked", default: true, null: false
t.index ["name", "created_at"], name: "index_installation_configs_on_name_and_created_at", unique: true
t.index ["name"], name: "index_installation_configs_on_name", unique: true
@@ -604,8 +603,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.integer "hook_type", default: 0
t.string "reference_id"
t.string "access_token"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.jsonb "settings", default: {}
end
@@ -615,8 +614,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.string "color", default: "#1f93ff", null: false
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.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["account_id"], name: "index_labels_on_account_id"
t.index ["title", "account_id"], name: "index_labels_on_title_and_account_id", unique: true
end
@@ -628,8 +627,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.bigint "created_by_id"
t.bigint "updated_by_id"
t.jsonb "actions", default: {}, null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["account_id"], name: "index_macros_on_account_id"
end
@@ -637,9 +636,9 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.bigint "user_id", null: false
t.bigint "conversation_id", null: false
t.bigint "account_id", null: false
t.datetime "mentioned_at", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "mentioned_at", precision: nil, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["account_id"], name: "index_mentions_on_account_id"
t.index ["conversation_id"], name: "index_mentions_on_conversation_id"
t.index ["user_id", "conversation_id"], name: "index_mentions_on_user_id_and_conversation_id", unique: true
@@ -652,8 +651,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.integer "inbox_id", null: false
t.integer "conversation_id", null: false
t.integer "message_type", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
t.boolean "private", default: false
t.integer "status", default: 0
t.string "source_id"
@@ -678,8 +677,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.bigint "account_id", null: false
t.bigint "contact_id", null: false
t.bigint "user_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["account_id"], name: "index_notes_on_account_id"
t.index ["contact_id"], name: "index_notes_on_contact_id"
t.index ["user_id"], name: "index_notes_on_user_id"
@@ -689,8 +688,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.integer "account_id"
t.integer "user_id"
t.integer "email_flags", default: 0, null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "push_flags", default: 0, null: false
t.index ["account_id", "user_id"], name: "by_account_user", unique: true
end
@@ -699,8 +698,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.bigint "user_id", null: false
t.integer "subscription_type", null: false
t.jsonb "subscription_attributes", default: {}, null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "identifier"
t.index ["identifier"], name: "index_notification_subscriptions_on_identifier", unique: true
t.index ["user_id"], name: "index_notification_subscriptions_on_user_id"
@@ -714,9 +713,9 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.bigint "primary_actor_id", null: false
t.string "secondary_actor_type"
t.bigint "secondary_actor_id"
t.datetime "read_at"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "read_at", precision: nil
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["account_id"], name: "index_notifications_on_account_id"
t.index ["primary_actor_type", "primary_actor_id"], name: "uniq_primary_actor_per_account_notifications"
t.index ["secondary_actor_type", "secondary_actor_id"], name: "uniq_secondary_actor_per_account_notifications"
@@ -727,8 +726,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.bigint "platform_app_id", null: false
t.string "permissible_type", null: false
t.bigint "permissible_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["permissible_type", "permissible_id"], name: "index_platform_app_permissibles_on_permissibles"
t.index ["platform_app_id", "permissible_id", "permissible_type"], name: "unique_permissibles_index", unique: true
t.index ["platform_app_id"], name: "index_platform_app_permissibles_on_platform_app_id"
@@ -736,15 +735,15 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
create_table "platform_apps", force: :cascade do |t|
t.string "name", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
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", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
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
@@ -758,8 +757,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.string "homepage_link"
t.string "page_title"
t.text "header_text"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.jsonb "config", default: {"allowed_locales"=>["en"]}
t.boolean "archived", default: false
t.index ["custom_domain"], name: "index_portals_on_custom_domain", unique: true
@@ -777,8 +776,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
create_table "related_categories", force: :cascade do |t|
t.bigint "category_id"
t.bigint "related_category_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["category_id", "related_category_id"], name: "index_related_categories_on_category_id_and_related_category_id", unique: true
t.index ["related_category_id", "category_id"], name: "index_related_categories_on_related_category_id_and_category_id", unique: true
end
@@ -790,11 +789,11 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.integer "inbox_id"
t.integer "user_id"
t.integer "conversation_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.float "value_in_business_hours"
t.datetime "event_start_time"
t.datetime "event_end_time"
t.datetime "event_start_time", precision: nil
t.datetime "event_end_time", precision: nil
t.index ["account_id"], name: "index_reporting_events_on_account_id"
t.index ["conversation_id"], name: "index_reporting_events_on_conversation_id"
t.index ["created_at"], name: "index_reporting_events_on_created_at"
@@ -810,7 +809,7 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.string "tagger_type"
t.integer "tagger_id"
t.string "context", limit: 128
t.datetime "created_at"
t.datetime "created_at", precision: nil
t.index ["context"], name: "index_taggings_on_context"
t.index ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "taggings_idx", unique: true
t.index ["tag_id"], name: "index_taggings_on_tag_id"
@@ -832,8 +831,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
create_table "team_members", force: :cascade do |t|
t.bigint "team_id", null: false
t.bigint "user_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["team_id", "user_id"], name: "index_team_members_on_team_id_and_user_id", unique: true
t.index ["team_id"], name: "index_team_members_on_team_id"
t.index ["user_id"], name: "index_team_members_on_user_id"
@@ -844,8 +843,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.text "description"
t.boolean "allow_auto_assign", default: true
t.bigint "account_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["account_id"], name: "index_teams_on_account_id"
t.index ["name", "account_id"], name: "index_teams_on_name_and_account_id", unique: true
end
@@ -854,8 +853,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.string "name"
t.string "auth_key"
t.integer "account_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
end
create_table "users", id: :serial, force: :cascade do |t|
@@ -863,23 +862,23 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.string "uid", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.datetime "reset_password_sent_at", precision: nil
t.datetime "remember_created_at", precision: nil
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.datetime "current_sign_in_at", precision: nil
t.datetime "last_sign_in_at", precision: nil
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.string "confirmation_token"
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
t.datetime "confirmed_at", precision: nil
t.datetime "confirmation_sent_at", precision: nil
t.string "unconfirmed_email"
t.string "name", null: false
t.string "display_name"
t.string "email"
t.json "tokens"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
t.string "pubsub_token"
t.integer "availability", default: 0
t.jsonb "ui_settings", default: {}
@@ -896,8 +895,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.integer "account_id"
t.integer "inbox_id"
t.string "url"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "webhook_type", default: 0
t.jsonb "subscriptions", default: ["conversation_status_changed", "conversation_updated", "conversation_created", "contact_created", "contact_updated", "message_created", "message_updated", "webwidget_triggered"]
t.index ["account_id", "url"], name: "index_webhooks_on_account_id_and_url", unique: true
@@ -912,8 +911,8 @@ ActiveRecord::Schema.define(version: 2023_04_26_130150) do
t.integer "open_minutes"
t.integer "close_hour"
t.integer "close_minutes"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "open_all_day", default: false
t.index ["account_id"], name: "index_working_hours_on_account_id"
t.index ["inbox_id"], name: "index_working_hours_on_inbox_id"

View File

@@ -16,10 +16,10 @@ KillMode=mixed
StandardInput=null
SyslogIdentifier=%p
Environment="PATH=/home/chatwoot/.rvm/gems/ruby-3.1.3/bin:/home/chatwoot/.rvm/gems/ruby-3.1.3@global/bin:/home/chatwoot/.rvm/rubies/ruby-3.1.3/bin:/home/chatwoot/.rvm/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin:/home/chatwoot/.rvm/bin:/home/chatwoot/.rvm/bin"
Environment="PATH=/home/chatwoot/.rvm/gems/ruby-3.2.2/bin:/home/chatwoot/.rvm/gems/ruby-3.2.2@global/bin:/home/chatwoot/.rvm/rubies/ruby-3.2.2/bin:/home/chatwoot/.rvm/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin:/home/chatwoot/.rvm/bin:/home/chatwoot/.rvm/bin"
Environment="PORT=3000"
Environment="RAILS_ENV=production"
Environment="NODE_ENV=production"
Environment="RAILS_LOG_TO_STDOUT=true"
Environment="GEM_HOME=/home/chatwoot/.rvm/gems/ruby-3.1.3"
Environment="GEM_PATH=/home/chatwoot/.rvm/gems/ruby-3.1.3:/home/chatwoot/.rvm/gems/ruby-3.1.3@global"
Environment="GEM_HOME=/home/chatwoot/.rvm/gems/ruby-3.2.2"
Environment="GEM_PATH=/home/chatwoot/.rvm/gems/ruby-3.2.2:/home/chatwoot/.rvm/gems/ruby-3.2.2@global"

View File

@@ -16,10 +16,10 @@ KillMode=mixed
StandardInput=null
SyslogIdentifier=%p
Environment="PATH=/home/chatwoot/.rvm/gems/ruby-3.1.3/bin:/home/chatwoot/.rvm/gems/ruby-3.1.3@global/bin:/home/chatwoot/.rvm/rubies/ruby-3.1.3/bin:/home/chatwoot/.rvm/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin:/home/chatwoot/.rvm/bin:/home/chatwoot/.rvm/bin"
Environment="PATH=/home/chatwoot/.rvm/gems/ruby-3.2.2/bin:/home/chatwoot/.rvm/gems/ruby-3.2.2@global/bin:/home/chatwoot/.rvm/rubies/ruby-3.2.2/bin:/home/chatwoot/.rvm/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin:/home/chatwoot/.rvm/bin:/home/chatwoot/.rvm/bin"
Environment="PORT=3000"
Environment="RAILS_ENV=production"
Environment="NODE_ENV=production"
Environment="RAILS_LOG_TO_STDOUT=true"
Environment="GEM_HOME=/home/chatwoot/.rvm/gems/ruby-3.1.3"
Environment="GEM_PATH=/home/chatwoot/.rvm/gems/ruby-3.1.3:/home/chatwoot/.rvm/gems/ruby-3.1.3@global"
Environment="GEM_HOME=/home/chatwoot/.rvm/gems/ruby-3.2.2"
Environment="GEM_PATH=/home/chatwoot/.rvm/gems/ruby-3.2.2:/home/chatwoot/.rvm/gems/ruby-3.2.2@global"

View File

@@ -328,8 +328,8 @@ function setup_chatwoot() {
sudo -i -u chatwoot << EOF
rvm --version
rvm autolibs disable
rvm install "ruby-3.1.3"
rvm use 3.1.3 --default
rvm install "ruby-3.2.2"
rvm use 3.2.2 --default
git clone https://github.com/chatwoot/chatwoot.git
cd chatwoot

View File

@@ -1,5 +1,5 @@
# pre-build stage
FROM ruby:3.1.3-alpine3.16 AS pre-builder
FROM ruby:3.2.2-alpine3.16 AS pre-builder
# ARG default to production settings
# For development docker-compose file overrides ARGS
@@ -64,13 +64,13 @@ RUN if [ "$RAILS_ENV" = "production" ]; then \
RUN git rev-parse HEAD > /app/.git_sha
# Remove unnecessary files
RUN rm -rf /gems/ruby/3.1.0/cache/*.gem \
&& find /gems/ruby/3.1.0/gems/ \( -name "*.c" -o -name "*.o" \) -delete \
RUN rm -rf /gems/ruby/3.2.0/cache/*.gem \
&& find /gems/ruby/3.2.0/gems/ \( -name "*.c" -o -name "*.o" \) -delete \
&& rm -rf .git \
&& rm .gitignore
# final build stage
FROM ruby:3.1.3-alpine3.16
FROM ruby:3.2.2-alpine3.16
ARG BUNDLE_WITHOUT="development:test"

View File

@@ -59,7 +59,7 @@ class ConfigLoader
end
def save_as_new_config(latest)
config = InstallationConfig.find_or_create_by(name: latest[:name])
config = InstallationConfig.find_or_initialize_by(name: latest[:name])
config.value = latest[:value]
config.locked = latest[:locked]
config.save!

View File

@@ -1,3 +1,5 @@
require 'google/cloud/dialogflow/v2'
class Integrations::Dialogflow::ProcessorService < Integrations::BotProcessorService
pattr_initialize [:event_name!, :hook!, :event_data!]
@@ -17,11 +19,15 @@ class Integrations::Dialogflow::ProcessorService < Integrations::BotProcessorSer
Rails.logger.warn "Account: #{hook.try(:account_id)} Hook: #{hook.id} credentials are not present." && return
end
Google::Cloud::Dialogflow.configure { |config| config.credentials = hook.settings['credentials'] }
session_client = Google::Cloud::Dialogflow.sessions
session = session_client.session_path project: hook.settings['project_id'], session: session_id
::Google::Cloud::Dialogflow::V2::Sessions::Client.configure do |config|
config.timeout = 10.0
config.credentials = hook.settings['credentials']
end
client = ::Google::Cloud::Dialogflow::V2::Sessions::Client.new
session = "projects/#{hook.settings['project_id']}/agent/sessions/#{session_id}"
query_input = { text: { text: message, language_code: 'en-US' } }
session_client.detect_intent session: session, query_input: query_input
client.detect_intent session: session, query_input: query_input
end
def process_response(message, response)

View File

@@ -1,3 +1,4 @@
require 'google/cloud/translate/v3'
class Integrations::GoogleTranslate::DetectLanguageService
pattr_initialize [:hook!, :message!]
@@ -33,7 +34,7 @@ class Integrations::GoogleTranslate::DetectLanguageService
end
def client
@client ||= Google::Cloud::Translate.translation_service do |config|
@client ||= ::Google::Cloud::Translate::V3::TranslationService::Client.new do |config|
config.credentials = hook.settings['credentials']
end
end

View File

@@ -1,3 +1,4 @@
require 'google/cloud/translate/v3'
class Integrations::GoogleTranslate::ProcessorService
pattr_initialize [:message!, :target_language!]
@@ -23,7 +24,7 @@ class Integrations::GoogleTranslate::ProcessorService
end
def client
@client ||= Google::Cloud::Translate.translation_service do |config|
@client ||= ::Google::Cloud::Translate::V3::TranslationService::Client.new do |config|
config.credentials = hook.settings['credentials']
end
end

View File

@@ -15,7 +15,7 @@ module Redis::Config
password: ENV.fetch('REDIS_PASSWORD', nil).presence,
ssl_params: { verify_mode: Chatwoot.redis_ssl_verify_mode },
reconnect_attempts: 2,
network_timeout: 5
timeout: 1
}
end

View File

@@ -16,8 +16,7 @@ db_namespace = namespace :db do
desc 'Runs setup if database does not exist, or runs migrations if it does'
task chatwoot_prepare: :load_config do
ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).each do |db_config|
ActiveRecord::Base.establish_connection(db_config.config)
# handling case where database was created by the provider, with out running db:setup
ActiveRecord::Base.establish_connection(db_config.configuration_hash)
unless ActiveRecord::Base.connection.table_exists? 'ar_internal_metadata'
db_namespace['load_config'].invoke if ActiveRecord::Base.schema_format == :ruby
ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:ruby, ENV.fetch('SCHEMA', nil))

10
lib/tasks/yarn.rake Normal file
View File

@@ -0,0 +1,10 @@
# ref: https://github.com/rails/rails/issues/43906#issuecomment-1094380699
# https://github.com/rails/rails/issues/43906#issuecomment-1099992310
task before_assets_precompile: :environment do
# run a command which starts your packaging
system('yarn')
end
# every time you execute 'rake assets:precompile'
# run 'before_assets_precompile' first
Rake::Task['assets:precompile'].enhance ['before_assets_precompile']

View File

@@ -25,7 +25,7 @@
"@june-so/analytics-next": "^1.36.5",
"@rails/actioncable": "6.1.3",
"@rails/ujs": "^7.0.3-1",
"@rails/webpacker": "5.3.0",
"@rails/webpacker": "5.4.4",
"@sentry/tracing": "^6.19.7",
"@sentry/vue": "^6.19.7",
"@tailwindcss/typography": "0.2.0",
@@ -78,7 +78,9 @@
"vuelidate": "0.7.7",
"vuex": "~2.1.1",
"vuex-router-sync": "~4.1.2",
"wavesurfer.js": "^6.0.4"
"wavesurfer.js": "^6.0.4",
"webpack": "^4.46.0",
"webpack-cli": "^3.3.12"
},
"devDependencies": {
"@babel/core": "7.13.16",
@@ -119,7 +121,7 @@
"prettier": "^1.16.4",
"rimraf": "^3.0.0",
"vue-jest": "4",
"webpack-dev-server": "3.11.2"
"webpack-dev-server": "^3"
},
"engines": {
"node": ">=10.x",

View File

@@ -231,8 +231,8 @@ RSpec.describe 'Api::V1::Accounts::Articles', type: :request do
json_response = JSON.parse(response.body)
expect(json_response['payload']['associated_articles'].length).to eq(2)
expect(json_response['payload']['associated_articles'][0]['id']).to eq(child_article_1.id)
expect(json_response['payload']['associated_articles'][1]['id']).to eq(child_article_2.id)
associated_articles_ids = json_response['payload']['associated_articles'].map { |article| article['id'] }
expect(associated_articles_ids).to match_array([child_article_1.id, child_article_2.id])
expect(json_response['payload']['id']).to eq(root_article.id)
end
end

View File

@@ -150,7 +150,7 @@ describe Integrations::Dialogflow::ProcessorService do
end
describe '#get_response' do
let(:google_dialogflow) { Google::Cloud::Dialogflow }
let(:google_dialogflow) { ::Google::Cloud::Dialogflow::V2::Sessions::Client }
let(:session_client) { double }
let(:session) { double }
let(:query_input) { { text: { text: message, language_code: 'en-US' } } }
@@ -158,8 +158,7 @@ describe Integrations::Dialogflow::ProcessorService do
before do
hook.update(settings: { 'project_id' => 'test', 'credentials' => 'creds' })
allow(google_dialogflow).to receive(:sessions).and_return(session_client)
allow(session_client).to receive(:session_path).and_return(session)
allow(google_dialogflow).to receive(:new).and_return(session_client)
allow(session_client).to receive(:detect_intent).and_return({ session: session, query_input: query_input })
end

View File

@@ -8,7 +8,7 @@ describe Integrations::GoogleTranslate::DetectLanguageService do
let(:translate_client) { double }
before do
allow(::Google::Cloud::Translate).to receive(:translation_service).and_return(translate_client)
allow(::Google::Cloud::Translate::V3::TranslationService::Client).to receive(:new).and_return(translate_client)
allow(translate_client).to receive(:detect_language).and_return(::Google::Cloud::Translate::V3::DetectLanguageResponse
.new({ languages: [{ language_code: 'es', confidence: 0.71875 }] }))
end

View File

@@ -14,7 +14,7 @@ describe ::Redis::Config do
it 'checks for app redis config' do
app_config = described_class.app
expect(app_config.keys).to match_array([:url, :password, :network_timeout, :reconnect_attempts, :ssl_params])
expect(app_config.keys).to match_array([:url, :password, :timeout, :reconnect_attempts, :ssl_params])
expect(app_config[:url]).to eq(redis_url)
expect(app_config[:password]).to eq(redis_pasword)
end
@@ -43,7 +43,7 @@ describe ::Redis::Config do
end
it 'checks for app redis config' do
expect(described_class.app.keys).to match_array([:url, :password, :sentinels, :network_timeout, :reconnect_attempts, :ssl_params])
expect(described_class.app.keys).to match_array([:url, :password, :sentinels, :timeout, :reconnect_attempts, :ssl_params])
expect(described_class.app[:url]).to eq("redis://#{redis_master_name}")
expect(described_class.app[:sentinels]).to match_array(expected_sentinels)
end
@@ -60,7 +60,7 @@ describe ::Redis::Config do
end
it 'checks for app redis config and sentinel passwords will be empty' do
expect(described_class.app.keys).to match_array([:url, :password, :sentinels, :network_timeout, :reconnect_attempts, :ssl_params])
expect(described_class.app.keys).to match_array([:url, :password, :sentinels, :timeout, :reconnect_attempts, :ssl_params])
expect(described_class.app[:url]).to eq("redis://#{redis_master_name}")
expect(described_class.app[:sentinels]).to match_array(expected_sentinels.map { |s| s.except(:password) })
end
@@ -78,7 +78,7 @@ describe ::Redis::Config do
end
it 'checks for app redis config and redis password is replaced in sentinel config' do
expect(described_class.app.keys).to match_array([:url, :password, :sentinels, :network_timeout, :reconnect_attempts, :ssl_params])
expect(described_class.app.keys).to match_array([:url, :password, :sentinels, :timeout, :reconnect_attempts, :ssl_params])
expect(described_class.app[:url]).to eq("redis://#{redis_master_name}")
expect(described_class.app[:sentinels]).to match_array(expected_sentinels.map { |s| s.merge(password: redis_sentinel_password) })
end

View File

@@ -63,10 +63,10 @@ describe ActionCableListener do
a_collection_containing_exactly(
admin.pubsub_token, conversation.contact_inbox.pubsub_token
),
'conversation.typing_on', conversation: conversation.push_event_data,
user: agent.push_event_data,
account_id: account.id,
is_private: false
'conversation.typing_on', { conversation: conversation.push_event_data,
user: agent.push_event_data,
account_id: account.id,
is_private: false }
)
listener.conversation_typing_on(event)
end
@@ -83,10 +83,10 @@ describe ActionCableListener do
a_collection_containing_exactly(
admin.pubsub_token, agent.pubsub_token
),
'conversation.typing_on', conversation: conversation.push_event_data,
user: conversation.contact.push_event_data,
account_id: account.id,
is_private: false
'conversation.typing_on', { conversation: conversation.push_event_data,
user: conversation.contact.push_event_data,
account_id: account.id,
is_private: false }
)
listener.conversation_typing_on(event)
end
@@ -103,10 +103,10 @@ describe ActionCableListener do
a_collection_containing_exactly(
admin.pubsub_token, conversation.contact_inbox.pubsub_token
),
'conversation.typing_off', conversation: conversation.push_event_data,
user: agent.push_event_data,
account_id: account.id,
is_private: false
'conversation.typing_off', { conversation: conversation.push_event_data,
user: agent.push_event_data,
account_id: account.id,
is_private: false }
)
listener.conversation_typing_off(event)
end

View File

@@ -245,6 +245,7 @@ RSpec.describe SupportMailbox, type: :mailbox do
expect(conversation.messages.last.content_attributes['email']['html_content']['reply']).to include(
<<~BODY.chomp
Hi,
We are providing you platform from here you can sell paid posts on your website.
Chatwoot | CS team | [C](https://d33wubrfki0l68.cloudfront.net/973467c532160fd8b940300a43fa85fa2d060307/dc9a0/static/brand-73f58cdefae282ae74cebfa74c1d7003.svg)

View File

@@ -41,7 +41,7 @@ end
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.fixture_path = Rails.root.join('spec/fixtures')
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false

1087
yarn.lock

File diff suppressed because it is too large Load Diff