diff --git a/app/jobs/reports/sp_issuer_user_counts_report.rb b/app/jobs/reports/sp_issuer_user_counts_report.rb new file mode 100644 index 00000000000..564f1bb2ecb --- /dev/null +++ b/app/jobs/reports/sp_issuer_user_counts_report.rb @@ -0,0 +1,27 @@ +module Reports + class SpIssuerUserCountsReport < BaseReport + REPORT_NAME = 'sp-issuer-user-counts-report'.freeze + + def perform(_date) + configs = IdentityConfig.store.sp_issuer_user_counts_report_configs + + configs.each do |report_hash| + emails = report_hash['emails'] + issuer = report_hash['issuer'] + + user_counts = Db::Identity::SpUserCounts.with_issuer(issuer) + + emails.each do |email| + ReportMailer.sp_issuer_user_counts_report( + name: REPORT_NAME, + email: email, + issuer: issuer, + total: user_counts['total'], + ial1_total: user_counts['ial1_total'], + ial2_total: user_counts['ial2_total'], + ).deliver_now + end + end + end + end +end diff --git a/app/mailers/report_mailer.rb b/app/mailers/report_mailer.rb index 584b460d783..f69efc16a54 100644 --- a/app/mailers/report_mailer.rb +++ b/app/mailers/report_mailer.rb @@ -11,6 +11,15 @@ def deleted_user_accounts_report(email:, name:, issuers:, data:) mail(to: email, subject: t('report_mailer.deleted_accounts_report.subject')) end + def sp_issuer_user_counts_report(email:, issuer:, total:, ial1_total:, ial2_total:, name:) + @name = name + @issuer = issuer + @total = total + @ial1_total = ial1_total + @ial2_total = ial2_total + mail(to: email, subject: t('report_mailer.sp_issuer_user_counts_report.subject')) + end + def system_demand_report(email:, data:, name:) @name = name attachments['system_demand.csv'] = data diff --git a/app/services/db/identity/sp_user_counts.rb b/app/services/db/identity/sp_user_counts.rb index 8c262230c69..100a484a5d4 100644 --- a/app/services/db/identity/sp_user_counts.rb +++ b/app/services/db/identity/sp_user_counts.rb @@ -16,6 +16,21 @@ def self.by_issuer ActiveRecord::Base.connection.execute(sql).to_a end + def self.with_issuer(issuer) + sql = <<~SQL + SELECT + count(user_id) AS total, + count(user_id)-count(verified_at) AS ial1_total, + count(verified_at) AS ial2_total + FROM identities + WHERE identities.service_provider = ? + LIMIT 1 + SQL + + query = ApplicationRecord.sanitize_sql_array([sql, issuer]) + ActiveRecord::Base.connection.execute(query).first + end + def self.overall sql = <<~SQL SELECT diff --git a/app/views/report_mailer/sp_issuer_user_counts_report.html.erb b/app/views/report_mailer/sp_issuer_user_counts_report.html.erb new file mode 100644 index 00000000000..994cb045f38 --- /dev/null +++ b/app/views/report_mailer/sp_issuer_user_counts_report.html.erb @@ -0,0 +1,5 @@ +<%= t('report_mailer.sp_issuer_user_counts_report.name') %>: <%= @name %>
+<%= t('report_mailer.sp_issuer_user_counts_report.issuer') %>: <%= @issuer %>
+<%= t('report_mailer.sp_issuer_user_counts_report.total') %>: <%= @total %>
+<%= t('report_mailer.sp_issuer_user_counts_report.ial1_total') %>: <%= @ial1_total %>
+<%= t('report_mailer.sp_issuer_user_counts_report.ial2_total') %>: <%= @ial2_total %>
\ No newline at end of file diff --git a/config/application.yml.default b/config/application.yml.default index 2497649d566..8441376c1db 100644 --- a/config/application.yml.default +++ b/config/application.yml.default @@ -324,6 +324,7 @@ sp_handoff_bounce_max_seconds: 2 show_user_attribute_deprecation_warnings: false otp_min_attempts_remaining_warning_count: 3 system_demand_report_email: 'foo@bar.com' +sp_issuer_user_counts_report_configs: '[]' test_ssn_allowed_list: '' totp_code_interval: 30 unauthorized_scope_enabled: false diff --git a/config/initializers/job_configurations.rb b/config/initializers/job_configurations.rb index b6380ab6fab..50163c4f8b5 100644 --- a/config/initializers/job_configurations.rb +++ b/config/initializers/job_configurations.rb @@ -34,6 +34,12 @@ cron: cron_24h, args: -> { [Time.zone.today] }, }, + # Email user counts for specific issuer + sp_issuer_user_counts: { + class: 'Reports::SpIssuerUserCountsReport', + cron: cron_24h, + args: -> { [Time.zone.today] }, + }, # Combined Invoice Supplement Report to S3 combined_invoice_supplement_report: { class: 'Reports::CombinedInvoiceSupplementReport', diff --git a/config/locales/report_mailer/en.yml b/config/locales/report_mailer/en.yml index 25737426436..059542b3353 100644 --- a/config/locales/report_mailer/en.yml +++ b/config/locales/report_mailer/en.yml @@ -5,6 +5,13 @@ en: issuers: Issuers name: Name subject: Deleted accounts report + sp_issuer_user_counts_report: + ial1_total: IAL1 users + ial2_total: IAL2 users + issuer: Issuer + name: Name + subject: Service provider user count report + total: Total users system_demand_report: name: Name subject: System demand report diff --git a/config/locales/report_mailer/es.yml b/config/locales/report_mailer/es.yml index 05922400d5e..53666b7e596 100644 --- a/config/locales/report_mailer/es.yml +++ b/config/locales/report_mailer/es.yml @@ -5,6 +5,13 @@ es: issuers: Emisores name: Nombre subject: Informe de cuentas eliminadas + sp_issuer_user_counts_report: + ial1_total: IAL1 usuarias + ial2_total: IAL2 usuarias + issuer: Identificación del emisor + name: Nombre + subject: Informe de recuento de usuarios del proveedor de servicios + total: Total de usuarias system_demand_report: name: Nombre subject: Informe de demanda del sistema diff --git a/config/locales/report_mailer/fr.yml b/config/locales/report_mailer/fr.yml index 098761d4ace..6bc77cadf5d 100644 --- a/config/locales/report_mailer/fr.yml +++ b/config/locales/report_mailer/fr.yml @@ -5,6 +5,13 @@ fr: issuers: Émetteurs name: Nom subject: Rapport sur les comptes supprimés + sp_issuer_user_counts_report: + ial1_total: IAL1 utilisatrices + ial2_total: IAL2 utilisatrices + issuer: Identifiant de l’émetteur + name: Nom + subject: Rapport sur le nombre d’utilisateurs + total: Nombre total d’utilisateurs system_demand_report: name: Nom subject: Rapport de demande du système diff --git a/lib/identity_config.rb b/lib/identity_config.rb index 239a5960f2b..a445926c81f 100644 --- a/lib/identity_config.rb +++ b/lib/identity_config.rb @@ -423,6 +423,7 @@ def self.build_store(config_map) config.add(:session_total_duration_timeout_in_minutes, type: :integer) config.add(:ses_configuration_set_name, type: :string) config.add(:set_remember_device_session_expiration, type: :boolean) + config.add(:sp_issuer_user_counts_report_configs, type: :json) config.add(:show_user_attribute_deprecation_warnings, type: :boolean) config.add(:skip_encryption_allowed_list, type: :json) config.add(:sp_handoff_bounce_max_seconds, type: :integer) diff --git a/spec/jobs/reports/sp_issuer_user_counts_report_spec.rb b/spec/jobs/reports/sp_issuer_user_counts_report_spec.rb new file mode 100644 index 00000000000..0493ec03adc --- /dev/null +++ b/spec/jobs/reports/sp_issuer_user_counts_report_spec.rb @@ -0,0 +1,31 @@ +require 'rails_helper' + +RSpec.describe Reports::SpIssuerUserCountsReport do + let(:name) { 'sp-issuer-user-counts-report' } + let(:issuer) { 'urn:gov:gsa:openidconnect:sp:sinatra' } + let(:email) { 'foo@bar.com' } + let(:user) { create(:user) } + let(:uuid) { 'foo' } + let(:last_authenticated_at) { '2020-01-02 12:03:04 UTC' } + + subject { described_class.new } + + it 'sends out a report to the email listed with one total user' do + create( + :service_provider_identity, + service_provider: issuer, + user: user, + uuid: uuid, + last_authenticated_at: last_authenticated_at, + ) + + allow(IdentityConfig.store).to receive(:sp_issuer_user_counts_report_configs).and_return( + [{ 'issuer' => issuer, 'emails' => [email] }], + ) + expect(ReportMailer).to receive(:sp_issuer_user_counts_report).with( + name: name, email: email, ial1_total: 1, ial2_total: 0, issuer: issuer, total: 1, + ).and_call_original + + subject.perform(Time.zone.today) + end +end