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