From 7320957405c21b1f428e8d36910ed65852c4d64b Mon Sep 17 00:00:00 2001 From: Sojan Jose Date: Tue, 20 Feb 2024 15:53:29 +0530 Subject: [PATCH 1/5] chore: Add facebook_api_version to global config (#8965) - Ability to configure facebook_api_version from global config Co-authored-by: Pranav --- app/controllers/dashboard_controller.rb | 2 +- app/controllers/super_admin/app_configs_controller.rb | 2 +- config/installation_config.yml | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 9e59758ea..0aea9df83 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -55,7 +55,7 @@ class DashboardController < ActionController::Base VAPID_PUBLIC_KEY: VapidService.public_key, ENABLE_ACCOUNT_SIGNUP: GlobalConfigService.load('ENABLE_ACCOUNT_SIGNUP', 'false'), FB_APP_ID: GlobalConfigService.load('FB_APP_ID', ''), - FACEBOOK_API_VERSION: 'v14.0', + FACEBOOK_API_VERSION: GlobalConfigService.load('FACEBOOK_API_VERSION', 'v17.0'), IS_ENTERPRISE: ChatwootApp.enterprise?, AZURE_APP_ID: ENV.fetch('AZURE_APP_ID', ''), GIT_SHA: GIT_HASH diff --git a/app/controllers/super_admin/app_configs_controller.rb b/app/controllers/super_admin/app_configs_controller.rb index a31d01675..6223f7174 100644 --- a/app/controllers/super_admin/app_configs_controller.rb +++ b/app/controllers/super_admin/app_configs_controller.rb @@ -34,7 +34,7 @@ class SuperAdmin::AppConfigsController < SuperAdmin::ApplicationController def allowed_configs @allowed_configs = case @config when 'facebook' - %w[FB_APP_ID FB_VERIFY_TOKEN FB_APP_SECRET IG_VERIFY_TOKEN ENABLE_MESSENGER_CHANNEL_HUMAN_AGENT] + %w[FB_APP_ID FB_VERIFY_TOKEN FB_APP_SECRET IG_VERIFY_TOKEN FACEBOOK_API_VERSION ENABLE_MESSENGER_CHANNEL_HUMAN_AGENT] when 'email' ['MAILER_INBOUND_EMAIL_DOMAIN'] else diff --git a/config/installation_config.yml b/config/installation_config.yml index 60eae3bc2..9db527832 100644 --- a/config/installation_config.yml +++ b/config/installation_config.yml @@ -110,6 +110,11 @@ display_title: 'Instagram Verify Token' description: 'The verify token used for Instagram Webhook' locked: false +- name: FACEBOOK_API_VERSION + display_title: 'Facebook API Version' + description: 'Configure this if you want to use a different Facebook API version. Make sure its prefixed with `v`' + value: 'v17.0' + locked: false - name: ENABLE_MESSENGER_CHANNEL_HUMAN_AGENT display_title: 'Enable human agent' value: false From 721a2f50525eeb116db4f3b8b96ac3588fb0ac56 Mon Sep 17 00:00:00 2001 From: Nithin David Thomas <1277421+nithindavid@users.noreply.github.com> Date: Tue, 20 Feb 2024 03:18:51 -0800 Subject: [PATCH 2/5] feat: API changes to support multi step user signup (#8933) -API Changes to support the new onboarding flow Co-authored-by: Sojan --- .../api/v1/accounts/agents_controller.rb | 5 +++ app/controllers/api/v1/accounts_controller.rb | 1 + app/controllers/api/v2/accounts_controller.rb | 13 +++++++ .../api/v1/models/_account.json.jbuilder | 5 +++ .../enterprise/api/v2/accounts_controller.rb | 35 +++++++++++-------- .../api/v1/accounts_controller_spec.rb | 19 ++++++++++ .../api/v2/accounts_controller_spec.rb | 14 ++++++++ .../api/v1/accounts/agents_controller_spec.rb | 10 ++++++ .../api/v2/accounts_controller_spec.rb | 16 +++++++++ 9 files changed, 103 insertions(+), 15 deletions(-) diff --git a/app/controllers/api/v1/accounts/agents_controller.rb b/app/controllers/api/v1/accounts/agents_controller.rb index 221c96b85..eff9975f7 100644 --- a/app/controllers/api/v1/accounts/agents_controller.rb +++ b/app/controllers/api/v1/accounts/agents_controller.rb @@ -49,6 +49,11 @@ class Api::V1::Accounts::AgentsController < Api::V1::Accounts::BaseController Rails.logger.info "[Agent#bulk_create] ignoring email #{email}, errors: #{e.record.errors}" end end + + # This endpoint is used to bulk create agents during onboarding + # onboarding_step key in present in Current account custom attributes, since this is a one time operation + Current.account.custom_attributes.delete('onboarding_step') + Current.account.save! head :ok end diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb index 481594ee4..c0dac6d9e 100644 --- a/app/controllers/api/v1/accounts_controller.rb +++ b/app/controllers/api/v1/accounts_controller.rb @@ -46,6 +46,7 @@ class Api::V1::AccountsController < Api::BaseController def update @account.assign_attributes(account_params.slice(:name, :locale, :domain, :support_email, :auto_resolve_duration)) @account.custom_attributes.merge!(custom_attributes_params) + @account.custom_attributes['onboarding_step'] = 'invite_team' if @account.custom_attributes['onboarding_step'] == 'account_update' @account.save! end diff --git a/app/controllers/api/v2/accounts_controller.rb b/app/controllers/api/v2/accounts_controller.rb index ea19727ad..45faca3d0 100644 --- a/app/controllers/api/v2/accounts_controller.rb +++ b/app/controllers/api/v2/accounts_controller.rb @@ -22,6 +22,7 @@ class Api::V2::AccountsController < Api::BaseController ).perform fetch_account_and_user_info + update_account_info if @account.present? if @user send_auth_headers(@user) @@ -33,6 +34,18 @@ class Api::V2::AccountsController < Api::BaseController private + def account_attributes + { + custom_attributes: @account.custom_attributes.merge({ 'onboarding_step' => 'profile_update' }) + } + end + + def update_account_info + @account.update!( + account_attributes + ) + end + def fetch_account_and_user_info; end def fetch_account diff --git a/app/views/api/v1/models/_account.json.jbuilder b/app/views/api/v1/models/_account.json.jbuilder index 9f89a5510..5e9d9048a 100644 --- a/app/views/api/v1/models/_account.json.jbuilder +++ b/app/views/api/v1/models/_account.json.jbuilder @@ -6,6 +6,11 @@ if resource.custom_attributes.present? json.subscribed_quantity resource.custom_attributes['subscribed_quantity'] json.subscription_status resource.custom_attributes['subscription_status'] json.subscription_ends_on resource.custom_attributes['subscription_ends_on'] + json.industry resource.custom_attributes['industry'] if resource.custom_attributes['industry'].present? + json.company_size resource.custom_attributes['company_size'] if resource.custom_attributes['company_size'].present? + json.timezone resource.custom_attributes['timezone'] if resource.custom_attributes['timezone'].present? + json.logo resource.custom_attributes['logo'] if resource.custom_attributes['logo'].present? + json.onboarding_step resource.custom_attributes['onboarding_step'] if resource.custom_attributes['onboarding_step'].present? end end json.domain @account.domain diff --git a/enterprise/app/controllers/enterprise/api/v2/accounts_controller.rb b/enterprise/app/controllers/enterprise/api/v2/accounts_controller.rb index d0d76c1ae..3edefbb5f 100644 --- a/enterprise/app/controllers/enterprise/api/v2/accounts_controller.rb +++ b/enterprise/app/controllers/enterprise/api/v2/accounts_controller.rb @@ -2,12 +2,11 @@ module Enterprise::Api::V2::AccountsController private def fetch_account_and_user_info - data = fetch_from_clearbit + @data = fetch_from_clearbit - return if data.blank? + return if @data.blank? - update_user_info(data) - update_account_info(data) + update_user_info end def fetch_from_clearbit @@ -17,19 +16,25 @@ module Enterprise::Api::V2::AccountsController nil end - def update_user_info(data) - @user.update!(name: data[:name]) + def update_user_info + @user.update!(name: @data[:name]) if @data[:name].present? end - def update_account_info(data) - @account.update!( - name: data[:company_name], - custom_attributes: @account.custom_attributes.merge( - 'industry' => data[:industry], - 'company_size' => data[:company_size], - 'timezone' => data[:timezone], - 'logo' => data[:logo] - ) + def data_from_clearbit + return {} if @data.blank? + + { name: @data[:company_name], + custom_attributes: { + 'industry' => @data[:industry], + 'company_size' => @data[:company_size], + 'timezone' => @data[:timezone], + 'logo' => @data[:logo] + } } + end + + def account_attributes + super.deep_merge( + data_from_clearbit ) end end diff --git a/spec/controllers/api/v1/accounts_controller_spec.rb b/spec/controllers/api/v1/accounts_controller_spec.rb index 95fa2ae7f..bd604f650 100644 --- a/spec/controllers/api/v1/accounts_controller_spec.rb +++ b/spec/controllers/api/v1/accounts_controller_spec.rb @@ -213,6 +213,25 @@ RSpec.describe 'Accounts API', type: :request do end end + it 'updates onboarding step to invite_team if onboarding step is present in account custom attributes' do + account.update(custom_attributes: { onboarding_step: 'account_update' }) + put "/api/v1/accounts/#{account.id}", + params: params, + headers: admin.create_new_auth_token, + as: :json + + expect(account.reload.custom_attributes['onboarding_step']).to eq('invite_team') + end + + it 'will not update onboarding step if onboarding step is not present in account custom attributes' do + put "/api/v1/accounts/#{account.id}", + params: params, + headers: admin.create_new_auth_token, + as: :json + + expect(account.reload.custom_attributes['onboarding_step']).to be_nil + end + it 'Throws error 422' do params[:name] = 'test' * 999 diff --git a/spec/controllers/api/v2/accounts_controller_spec.rb b/spec/controllers/api/v2/accounts_controller_spec.rb index 82693ed2b..182ebadac 100644 --- a/spec/controllers/api/v2/accounts_controller_spec.rb +++ b/spec/controllers/api/v2/accounts_controller_spec.rb @@ -30,6 +30,20 @@ RSpec.describe 'Accounts API', type: :request do end end + it 'updates the onboarding step in custom attributes' do + with_modified_env ENABLE_ACCOUNT_SIGNUP: 'true' do + allow(account_builder).to receive(:perform).and_return([user, account]) + + params = { email: email, user: nil, locale: nil, password: 'Password1!' } + + post api_v2_accounts_url, + params: params, + as: :json + + expect(account.reload.custom_attributes['onboarding_step']).to eq('profile_update') + end + end + it 'calls ChatwootCaptcha' do with_modified_env ENABLE_ACCOUNT_SIGNUP: 'true' do captcha = double diff --git a/spec/enterprise/controllers/api/v1/accounts/agents_controller_spec.rb b/spec/enterprise/controllers/api/v1/accounts/agents_controller_spec.rb index 97e76a6cd..e5a8a5b7d 100644 --- a/spec/enterprise/controllers/api/v1/accounts/agents_controller_spec.rb +++ b/spec/enterprise/controllers/api/v1/accounts/agents_controller_spec.rb @@ -41,5 +41,15 @@ RSpec.describe 'Agents API', type: :request do expect(response.body).to include('Account limit exceeded. Please purchase more licenses') end end + + context 'when onboarding step is present in account custom attributes' do + it 'removes onboarding step from account custom attributes' do + account.update(custom_attributes: { onboarding_step: 'completed' }) + + post "/api/v1/accounts/#{account.id}/agents/bulk_create", params: bulk_create_params, headers: admin.create_new_auth_token + + expect(account.reload.custom_attributes).not_to include('onboarding_step') + end + end end end diff --git a/spec/enterprise/controllers/enterprise/api/v2/accounts_controller_spec.rb b/spec/enterprise/controllers/enterprise/api/v2/accounts_controller_spec.rb index 8ad75b42f..c74a2bcb5 100644 --- a/spec/enterprise/controllers/enterprise/api/v2/accounts_controller_spec.rb +++ b/spec/enterprise/controllers/enterprise/api/v2/accounts_controller_spec.rb @@ -51,6 +51,22 @@ RSpec.describe Enterprise::Api::V2::AccountsController, type: :request do end end + it 'updates the onboarding step in custom attributes' do + with_modified_env ENABLE_ACCOUNT_SIGNUP: 'true' do + allow(account_builder).to receive(:perform).and_return([user, account]) + + params = { email: email, user: nil, locale: nil, password: 'Password1!' } + + post api_v2_accounts_url, + params: params, + as: :json + + custom_attributes = account.custom_attributes + + expect(custom_attributes['onboarding_step']).to eq('profile_update') + end + end + it 'handles errors when fetching data from clearbit' do with_modified_env ENABLE_ACCOUNT_SIGNUP: 'true' do allow(account_builder).to receive(:perform).and_return([user, account]) From 5d9fb55370ccd9ea01043cbfe0e74f09569602e0 Mon Sep 17 00:00:00 2001 From: Liam <43280985+LiamAshdown@users.noreply.github.com> Date: Tue, 20 Feb 2024 11:41:03 +0000 Subject: [PATCH 3/5] feat: Export contact improvements (#8895) This pull request enhances the export contacts feature by adding a confirmation step before exporting. Previously, clicking the export button would trigger the export action without confirmation. Additionally, it ensures that only the intended recipient receives the export email, addressing the previous behaviour where all administrators received it. Fixes: #8504 Co-authored-by: Sojan Jose --- .../api/v1/accounts/contacts_controller.rb | 2 +- .../dashboard/i18n/locale/en/contact.json | 8 +++++++- .../dashboard/contacts/components/Header.vue | 16 ++++++++++++++-- app/jobs/account/contacts_export_job.rb | 4 ++-- .../channel_notifications_mailer.rb | 5 +++-- .../api/v1/accounts/contacts_controller_spec.rb | 4 ++-- spec/jobs/account/contacts_export_job_spec.rb | 6 +++--- .../channel_notifications_mailer_spec.rb | 5 ++--- 8 files changed, 34 insertions(+), 16 deletions(-) diff --git a/app/controllers/api/v1/accounts/contacts_controller.rb b/app/controllers/api/v1/accounts/contacts_controller.rb index f424f3b66..98683ea25 100644 --- a/app/controllers/api/v1/accounts/contacts_controller.rb +++ b/app/controllers/api/v1/accounts/contacts_controller.rb @@ -46,7 +46,7 @@ class Api::V1::Accounts::ContactsController < Api::V1::Accounts::BaseController def export column_names = params['column_names'] - Account::ContactsExportJob.perform_later(Current.account.id, column_names) + Account::ContactsExportJob.perform_later(Current.account.id, column_names, Current.user.email) head :ok, message: I18n.t('errors.contacts.export.success') end diff --git a/app/javascript/dashboard/i18n/locale/en/contact.json b/app/javascript/dashboard/i18n/locale/en/contact.json index 594e34c4f..cae908016 100644 --- a/app/javascript/dashboard/i18n/locale/en/contact.json +++ b/app/javascript/dashboard/i18n/locale/en/contact.json @@ -79,7 +79,13 @@ "TITLE": "Export Contacts", "DESC": "Export contacts to a CSV file.", "SUCCESS_MESSAGE": "Export is in progress. You will be notified on email when the export file is ready to download.", - "ERROR_MESSAGE": "There was an error, please try again" + "ERROR_MESSAGE": "There was an error, please try again", + "CONFIRM": { + "TITLE": "Export Contacts", + "MESSAGE": "Are you sure you want to export all contacts?", + "YES": "Yes, Export", + "NO": "No, Cancel" + } }, "DELETE_NOTE": { "CONFIRM": { diff --git a/app/javascript/dashboard/routes/dashboard/contacts/components/Header.vue b/app/javascript/dashboard/routes/dashboard/contacts/components/Header.vue index 4df4017b2..1b4fd90e0 100644 --- a/app/javascript/dashboard/routes/dashboard/contacts/components/Header.vue +++ b/app/javascript/dashboard/routes/dashboard/contacts/components/Header.vue @@ -113,6 +113,13 @@ + @@ -175,8 +182,13 @@ export default { toggleImport() { this.$emit('on-toggle-import'); }, - submitExport() { - this.$emit('on-export-submit'); + async submitExport() { + const ok = + await this.$refs.confirmExportContactsDialog.showConfirmation(); + + if (ok) { + this.$emit('on-export-submit'); + } }, submitSearch() { this.$emit('on-search-submit'); diff --git a/app/jobs/account/contacts_export_job.rb b/app/jobs/account/contacts_export_job.rb index 0ae8b3892..b8e9dbc96 100644 --- a/app/jobs/account/contacts_export_job.rb +++ b/app/jobs/account/contacts_export_job.rb @@ -1,13 +1,13 @@ class Account::ContactsExportJob < ApplicationJob queue_as :low - def perform(account_id, column_names) + def perform(account_id, column_names, email_to) account = Account.find(account_id) headers = valid_headers(column_names) generate_csv(account, headers) file_url = account_contact_export_url(account) - AdministratorNotifications::ChannelNotificationsMailer.with(account: account).contact_export_complete(file_url)&.deliver_later + AdministratorNotifications::ChannelNotificationsMailer.with(account: account).contact_export_complete(file_url, email_to)&.deliver_later end def generate_csv(account, headers) diff --git a/app/mailers/administrator_notifications/channel_notifications_mailer.rb b/app/mailers/administrator_notifications/channel_notifications_mailer.rb index 8c52a9bd3..6c0f7cee2 100644 --- a/app/mailers/administrator_notifications/channel_notifications_mailer.rb +++ b/app/mailers/administrator_notifications/channel_notifications_mailer.rb @@ -60,12 +60,13 @@ class AdministratorNotifications::ChannelNotificationsMailer < ApplicationMailer send_mail_with_liquid(to: admin_emails, subject: subject) and return end - def contact_export_complete(file_url) + def contact_export_complete(file_url, email_to) return unless smtp_config_set_or_development? @action_url = file_url subject = "Your contact's export file is available to download." - send_mail_with_liquid(to: admin_emails, subject: subject) and return + + send_mail_with_liquid(to: email_to, subject: subject) and return end private diff --git a/spec/controllers/api/v1/accounts/contacts_controller_spec.rb b/spec/controllers/api/v1/accounts/contacts_controller_spec.rb index e5e298747..21511310b 100644 --- a/spec/controllers/api/v1/accounts/contacts_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/contacts_controller_spec.rb @@ -197,7 +197,7 @@ RSpec.describe 'Contacts API', type: :request do let(:admin) { create(:user, account: account, role: :administrator) } it 'enqueues a contact export job' do - expect(Account::ContactsExportJob).to receive(:perform_later).with(account.id, nil).once + expect(Account::ContactsExportJob).to receive(:perform_later).with(account.id, nil, admin.email).once get "/api/v1/accounts/#{account.id}/contacts/export", headers: admin.create_new_auth_token, @@ -207,7 +207,7 @@ RSpec.describe 'Contacts API', type: :request do end it 'enqueues a contact export job with sent_columns' do - expect(Account::ContactsExportJob).to receive(:perform_later).with(account.id, %w[phone_number email]).once + expect(Account::ContactsExportJob).to receive(:perform_later).with(account.id, %w[phone_number email], admin.email).once get "/api/v1/accounts/#{account.id}/contacts/export", headers: admin.create_new_auth_token, diff --git a/spec/jobs/account/contacts_export_job_spec.rb b/spec/jobs/account/contacts_export_job_spec.rb index e597ff637..b395967b4 100644 --- a/spec/jobs/account/contacts_export_job_spec.rb +++ b/spec/jobs/account/contacts_export_job_spec.rb @@ -24,17 +24,17 @@ RSpec.describe Account::ContactsExportJob do allow(AdministratorNotifications::ChannelNotificationsMailer).to receive(:with).with(account: account).and_return(mailer) allow(mailer).to receive(:contact_export_complete) - described_class.perform_now(account.id, []) + described_class.perform_now(account.id, [], 'test@test.com') file_url = Rails.application.routes.url_helpers.rails_blob_url(account.contacts_export) expect(account.contacts_export).to be_present expect(file_url).to be_present - expect(mailer).to have_received(:contact_export_complete).with(file_url) + expect(mailer).to have_received(:contact_export_complete).with(file_url, 'test@test.com') end it 'generates valid data export file' do - described_class.perform_now(account.id, []) + described_class.perform_now(account.id, [], 'test@test.com') csv_data = CSV.parse(account.contacts_export.download, headers: true) emails = csv_data.pluck('email') diff --git a/spec/mailers/administrator_notifications/channel_notifications_mailer_spec.rb b/spec/mailers/administrator_notifications/channel_notifications_mailer_spec.rb index f67b8300c..944475fb2 100644 --- a/spec/mailers/administrator_notifications/channel_notifications_mailer_spec.rb +++ b/spec/mailers/administrator_notifications/channel_notifications_mailer_spec.rb @@ -10,7 +10,6 @@ RSpec.describe AdministratorNotifications::ChannelNotificationsMailer do before do allow(described_class).to receive(:new).and_return(class_instance) allow(class_instance).to receive(:smtp_config_set_or_development?).and_return(true) - Account::ContactsExportJob.perform_now(account.id, []) end describe 'slack_disconnect' do @@ -92,8 +91,8 @@ RSpec.describe AdministratorNotifications::ChannelNotificationsMailer do end describe 'contact_export_complete' do - let!(:file_url) { Rails.application.routes.url_helpers.rails_blob_url(account.contacts_export) } - let(:mail) { described_class.with(account: account).contact_export_complete(file_url).deliver_now } + let!(:file_url) { 'http://test.com/test' } + let(:mail) { described_class.with(account: account).contact_export_complete(file_url, administrator.email).deliver_now } it 'renders the subject' do expect(mail.subject).to eq("Your contact's export file is available to download.") From c5c08451517f86b3b95b5f836e80b1597ef23244 Mon Sep 17 00:00:00 2001 From: Muhsin Keloth Date: Tue, 20 Feb 2024 17:17:25 +0530 Subject: [PATCH 4/5] feat: Add labels, status and priority in notification `push_event_data` (#8972) --- app/models/notification.rb | 10 +--------- .../api/v1/accounts/notifications_controller_spec.rb | 1 + 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/app/models/notification.rb b/app/models/notification.rb index f8c6e3d5b..cd3d57627 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -68,20 +68,12 @@ class Notification < ApplicationRecord } if primary_actor.present? - payload[:primary_actor] = primary_actor_data + payload[:primary_actor] = primary_actor&.push_event_data payload[:push_message_title] = push_message_title end payload end - def primary_actor_data - { - id: primary_actor.push_event_data[:id], - meta: primary_actor.push_event_data[:meta], - inbox_id: primary_actor.push_event_data[:inbox_id] - } - end - def fcm_push_data { id: id, diff --git a/spec/controllers/api/v1/accounts/notifications_controller_spec.rb b/spec/controllers/api/v1/accounts/notifications_controller_spec.rb index 3dcb47f71..4605e0fda 100644 --- a/spec/controllers/api/v1/accounts/notifications_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/notifications_controller_spec.rb @@ -29,6 +29,7 @@ RSpec.describe 'Notifications API', type: :request do expect(response_json['data']['meta']['count']).to eq 2 # notification appear in descending order expect(response_json['data']['payload'].first['id']).to eq notification2.id + expect(response_json['data']['payload'].first['primary_actor']).not_to be_nil end end end From e6cf8c39b7a3d4482c2a96dcc51995e910800255 Mon Sep 17 00:00:00 2001 From: Muhsin Keloth Date: Tue, 20 Feb 2024 18:55:39 +0530 Subject: [PATCH 5/5] feat: Update `last_snoozed_at` after the un-snooze notification (#8943) --- .../v1/accounts/notifications_controller.rb | 3 ++- .../reopen_snoozed_notifications_job.rb | 23 +++++++++++++++---- app/models/notification.rb | 1 + .../notifications/index.json.jbuilder | 1 + .../accounts/notifications_controller_spec.rb | 1 + .../reopen_snoozed_notifications_job_spec.rb | 3 +++ 6 files changed, 27 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/v1/accounts/notifications_controller.rb b/app/controllers/api/v1/accounts/notifications_controller.rb index 3ac0568e3..52035ce64 100644 --- a/app/controllers/api/v1/accounts/notifications_controller.rb +++ b/app/controllers/api/v1/accounts/notifications_controller.rb @@ -54,7 +54,8 @@ class Api::V1::Accounts::NotificationsController < Api::V1::Accounts::BaseContro end def snooze - @notification.update(snoozed_until: parse_date_time(params[:snoozed_until].to_s)) if params[:snoozed_until] + updated_meta = (@notification.meta || {}).merge('last_snoozed_at' => nil) + @notification.update(snoozed_until: parse_date_time(params[:snoozed_until].to_s), meta: updated_meta) if params[:snoozed_until] render json: @notification end diff --git a/app/jobs/notification/reopen_snoozed_notifications_job.rb b/app/jobs/notification/reopen_snoozed_notifications_job.rb index 05235b62b..91ed5ee61 100644 --- a/app/jobs/notification/reopen_snoozed_notifications_job.rb +++ b/app/jobs/notification/reopen_snoozed_notifications_job.rb @@ -2,9 +2,24 @@ class Notification::ReopenSnoozedNotificationsJob < ApplicationJob queue_as :low def perform - # rubocop:disable Rails/SkipsModelValidations - Notification.where(snoozed_until: 3.days.ago..Time.current) - .update_all(snoozed_until: nil, updated_at: Time.current, last_activity_at: Time.current, read_at: nil) - # rubocop:enable Rails/SkipsModelValidations + Notification.where(snoozed_until: 3.days.ago..Time.current).find_in_batches(batch_size: 100) do |notifications_batch| + notifications_batch.each do |notification| + update_notification(notification) + end + end + end + + private + + def update_notification(notification) + updated_meta = (notification.meta || {}).merge('last_snoozed_at' => notification.snoozed_until) + + notification.update!( + snoozed_until: nil, + updated_at: Time.current, + last_activity_at: Time.current, + meta: updated_meta, + read_at: nil + ) end end diff --git a/app/models/notification.rb b/app/models/notification.rb index cd3d57627..113c6cf3e 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -64,6 +64,7 @@ class Notification < ApplicationRecord created_at: created_at.to_i, last_activity_at: last_activity_at.to_i, snoozed_until: snoozed_until, + meta: meta, account_id: account_id } diff --git a/app/views/api/v1/accounts/notifications/index.json.jbuilder b/app/views/api/v1/accounts/notifications/index.json.jbuilder index ae86372c9..4a408dfca 100644 --- a/app/views/api/v1/accounts/notifications/index.json.jbuilder +++ b/app/views/api/v1/accounts/notifications/index.json.jbuilder @@ -21,6 +21,7 @@ json.data do json.created_at notification.created_at.to_i json.last_activity_at notification.last_activity_at.to_i json.snoozed_until notification.snoozed_until + json.meta notification.meta end end end diff --git a/spec/controllers/api/v1/accounts/notifications_controller_spec.rb b/spec/controllers/api/v1/accounts/notifications_controller_spec.rb index 4605e0fda..9b16e48fb 100644 --- a/spec/controllers/api/v1/accounts/notifications_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/notifications_controller_spec.rb @@ -179,6 +179,7 @@ RSpec.describe 'Notifications API', type: :request do expect(response).to have_http_status(:success) expect(notification.reload.snoozed_until).not_to eq('') + expect(notification.reload.meta['last_snoozed_at']).to be_nil end end end diff --git a/spec/jobs/notification/reopen_snoozed_notifications_job_spec.rb b/spec/jobs/notification/reopen_snoozed_notifications_job_spec.rb index 024c3d0d6..94697dcd6 100644 --- a/spec/jobs/notification/reopen_snoozed_notifications_job_spec.rb +++ b/spec/jobs/notification/reopen_snoozed_notifications_job_spec.rb @@ -14,10 +14,13 @@ RSpec.describe Notification::ReopenSnoozedNotificationsJob do it 'reopens snoozed notifications whose snooze until has passed' do described_class.perform_now + snoozed_until = snoozed_till_5_minutes_ago.reload.snoozed_until + expect(snoozed_till_5_minutes_ago.reload.snoozed_until).to be_nil expect(snoozed_till_tomorrow.reload.snoozed_until.to_date).to eq 1.day.from_now.to_date expect(snoozed_indefinitely.reload.snoozed_until).to be_nil expect(snoozed_indefinitely.reload.read_at).to be_nil + expect(snoozed_until).to eq(snoozed_till_5_minutes_ago.reload.meta['snoozed_until']) end end end