diff --git a/app/controllers/admin/settings_controller.rb b/app/controllers/admin/settings_controller.rb index 1ebf2946d8..5ec7a91674 100644 --- a/app/controllers/admin/settings_controller.rb +++ b/app/controllers/admin/settings_controller.rb @@ -10,6 +10,7 @@ def index .where.not(code: 'default_language') @billing_settings = SettingEntry.with_group('billing') @contacts_settings = SettingEntry.with_group('contacts') + @certificate_settings = SettingEntry.with_group('certificate') end def create diff --git a/app/jobs/expire_certificate_reminder_job.rb b/app/jobs/expire_certificate_reminder_job.rb index 196c53d1a8..838139a04a 100644 --- a/app/jobs/expire_certificate_reminder_job.rb +++ b/app/jobs/expire_certificate_reminder_job.rb @@ -1,10 +1,11 @@ class ExpireCertificateReminderJob < ApplicationJob queue_as :default - - DEADLINE = 1.month def perform - Certificate.where('expires_at < ?', DEADLINE.from_now).each do |certificate| + deadline_days = Setting.certificate_reminder_deadline || 30 + deadline = deadline_days.days.from_now + + Certificate.where('expires_at < ?', deadline).where(reminder_sent: false).each do |certificate| send_reminder(certificate) end end @@ -15,6 +16,7 @@ def send_reminder(certificate) registrar = certificate.api_user.registrar send_email(registrar, certificate) + certificate.update(reminder_sent: true) end def send_email(registrar, certificate) diff --git a/app/views/admin/settings/index.haml b/app/views/admin/settings/index.haml index c9a272a295..b9ba72f448 100644 --- a/app/views/admin/settings/index.haml +++ b/app/views/admin/settings/index.haml @@ -54,6 +54,15 @@ - @contacts_settings.each do |setting| = render 'setting_row', setting: setting + .panel.panel-default + .panel-heading + = t('.certificate') + .table-responsive + %table.table.table-hover.table-bordered.table-condensed + %tbody + - @certificate_settings.each do |setting| + = render 'setting_row', setting: setting + .row .col-md-12.text-right = submit_tag(t('.save_btn'), class: 'btn btn-success', name: nil) diff --git a/config/locales/admin/settings.en.yml b/config/locales/admin/settings.en.yml index bb042db013..21dbbf4fa0 100644 --- a/config/locales/admin/settings.en.yml +++ b/config/locales/admin/settings.en.yml @@ -9,6 +9,7 @@ en: billing: Billing contacts: Contacts save_btn: Save + certificate: Certificate create: saved: Settings have been successfully updated diff --git a/db/migrate/20250910112808_add_reminder_sent_to_certificate.rb b/db/migrate/20250910112808_add_reminder_sent_to_certificate.rb new file mode 100644 index 0000000000..a84bbde3a3 --- /dev/null +++ b/db/migrate/20250910112808_add_reminder_sent_to_certificate.rb @@ -0,0 +1,5 @@ +class AddReminderSentToCertificate < ActiveRecord::Migration[6.1] + def change + add_column :certificates, :reminder_sent, :boolean, default: false + end +end diff --git a/db/migrate/20250910113941_add_certificate_reminder_deadline_to_settings.rb b/db/migrate/20250910113941_add_certificate_reminder_deadline_to_settings.rb new file mode 100644 index 0000000000..a0292e0b70 --- /dev/null +++ b/db/migrate/20250910113941_add_certificate_reminder_deadline_to_settings.rb @@ -0,0 +1,18 @@ +class AddCertificateReminderDeadlineToSettings < ActiveRecord::Migration[6.1] + def up + unless SettingEntry.exists?(code: 'certificate_reminder_deadline') + SettingEntry.create!( + code: 'certificate_reminder_deadline', + value: '30', + format: 'integer', + group: 'certificate' + ) + else + puts "SettingEntry certificate_reminder_deadline already exists" + end + end + + def down + SettingEntry.where(code: 'certificate_reminder_deadline').destroy_all + end +end diff --git a/db/structure.sql b/db/structure.sql index faa3014b0d..1eea7020f1 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -1,3 +1,8 @@ +\restrict 1nctSeWgAMeDygPpYdyeGcpf3SIlnwVyJaYVgeIkZgsmRdEvwgJ7hEgebG5zQ3v + +-- Dumped from database version 13.4 (Debian 13.4-4.pgdg110+1) +-- Dumped by pg_dump version 13.22 (Debian 13.22-0+deb11u1) + SET statement_timeout = 0; SET lock_timeout = 0; SET idle_in_transaction_session_timeout = 0; @@ -629,7 +634,8 @@ CREATE TABLE public.certificates ( serial character varying, revoked_at timestamp without time zone, revoked_reason integer, - p12_password character varying + p12_password character varying, + reminder_sent boolean DEFAULT false ); @@ -732,7 +738,8 @@ CREATE TABLE public.contacts ( company_register_status character varying, ident_request_sent_at timestamp without time zone, verified_at timestamp without time zone, - verification_id character varying + verification_id character varying, + system_disclosed_attributes character varying[] DEFAULT '{}'::character varying[] ); @@ -5279,6 +5286,8 @@ ALTER TABLE ONLY public.users -- PostgreSQL database dump complete -- +\unrestrict 1nctSeWgAMeDygPpYdyeGcpf3SIlnwVyJaYVgeIkZgsmRdEvwgJ7hEgebG5zQ3v + SET search_path TO "$user", public; INSERT INTO "schema_migrations" (version) VALUES @@ -5767,10 +5776,13 @@ INSERT INTO "schema_migrations" (version) VALUES ('20230707084741'), ('20230710120154'), ('20230711083811'), +('20240722085530'), +('20240723110208'), ('20240816091049'), ('20240816092636'), ('20240924103554'), ('20241015071505'), +('20241022121525'), ('20241030095636'), ('20241104104620'), ('20241112093540'), @@ -5779,12 +5791,12 @@ INSERT INTO "schema_migrations" (version) VALUES ('20241206085817'), ('20250204094550'), ('20250219102811'), -('20250313122119'), -('20250319104749'), ('20250310133151'), +('20250313122119'), ('20250314133357'), -('20240722085530'), -('20240723110208'), -('20241022121525'); +('20250319104749'), +('20250627084536'), +('20250910112808'), +('20250910113941'); diff --git a/test/jobs/expire_certificate_reminder_job_test.rb b/test/jobs/expire_certificate_reminder_job_test.rb index 59df68afc0..0f1cd087d7 100644 --- a/test/jobs/expire_certificate_reminder_job_test.rb +++ b/test/jobs/expire_certificate_reminder_job_test.rb @@ -6,10 +6,11 @@ class ExpireCertificateReminderJobTest < ActiveJob::TestCase setup do ActionMailer::Base.deliveries.clear @certificate = certificates(:api) + + create_setting_if_not_exists('certificate_reminder_deadline', '30', 'integer', 'certificate') end def test_sends_reminder_for_expiring_certificate - # Устанавливаем дату истечения на 2 недели от текущего времени (меньше месяца) @certificate.update(expires_at: 2.weeks.from_now) perform_enqueued_jobs do @@ -18,14 +19,12 @@ def test_sends_reminder_for_expiring_certificate assert_emails 1 - # Проверяем, что письмо отправлено правильному получателю email = ActionMailer::Base.deliveries.last assert_equal @certificate.api_user.registrar.email, email.to.first assert_match 'Certificate Expiring', email.subject end def test_does_not_send_reminder_for_certificate_expiring_later - # Устанавливаем дату истечения на 2 месяца от текущего времени (больше месяца) @certificate.update(expires_at: 2.months.from_now) perform_enqueued_jobs do @@ -36,7 +35,6 @@ def test_does_not_send_reminder_for_certificate_expiring_later end def test_sends_reminder_for_multiple_expiring_certificates - # Создаем второй сертификат, который тоже скоро истекает second_certificate = certificates(:registrar) @certificate.update(expires_at: 1.week.from_now) second_certificate.update(expires_at: 3.weeks.from_now) @@ -47,4 +45,37 @@ def test_sends_reminder_for_multiple_expiring_certificates assert_emails 2 end + + def test_uses_custom_deadline_setting + update_setting('certificate_reminder_deadline', '10') + + @certificate.update(expires_at: 2.weeks.from_now) + + perform_enqueued_jobs do + ExpireCertificateReminderJob.perform_now + end + + assert_emails 0 + + @certificate.update(expires_at: 5.days.from_now) + + perform_enqueued_jobs do + ExpireCertificateReminderJob.perform_now + end + + assert_emails 1 + end + + private + + def create_setting_if_not_exists(code, value, format, group) + unless SettingEntry.exists?(code: code) + SettingEntry.create!(code: code, value: value, format: format, group: group) + end + end + + def update_setting(code, value) + setting = SettingEntry.find_by(code: code) + setting.update!(value: value) if setting + end end