mirror of
https://github.com/lingble/chatwoot.git
synced 2025-10-28 17:52:39 +00:00
@@ -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
|
||||
|
||||
@@ -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
7
.gitignore
vendored
@@ -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
|
||||
|
||||
33
.rubocop.yml
33
.rubocop.yml
@@ -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
|
||||
|
||||
@@ -1 +1 @@
|
||||
3.1.3
|
||||
3.2.2
|
||||
|
||||
1
.slugignore
Normal file
1
.slugignore
Normal file
@@ -0,0 +1 @@
|
||||
/spec
|
||||
46
Gemfile
46
Gemfile
@@ -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
|
||||
|
||||
647
Gemfile.lock
647
Gemfile.lock
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
0
bin/validate_push
Normal file → Executable 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
|
||||
|
||||
@@ -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" %>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
11
config/initializers/permissions_policy.rb
Normal file
11
config/initializers/permissions_policy.rb
Normal 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
|
||||
@@ -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) %>
|
||||
|
||||
@@ -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
|
||||
283
db/schema.rb
283
db/schema.rb
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
10
lib/tasks/yarn.rake
Normal 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']
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user