From a31ff153adaa437184e3e8ea0d013befa2ff3482 Mon Sep 17 00:00:00 2001 From: Keith Lawrence Date: Tue, 12 Sep 2023 14:37:00 +0100 Subject: [PATCH 1/6] Remove EmailSubscription model --- app/models/email_subscription.rb | 65 ---------- ...20230824083133_drop_email_subscriptions.rb | 5 + db/schema.rb | 13 +- spec/models/email_subscription_spec.rb | 121 ------------------ 4 files changed, 6 insertions(+), 198 deletions(-) delete mode 100644 app/models/email_subscription.rb create mode 100644 db/migrate/20230824083133_drop_email_subscriptions.rb delete mode 100644 spec/models/email_subscription_spec.rb diff --git a/app/models/email_subscription.rb b/app/models/email_subscription.rb deleted file mode 100644 index bd1ee1bb..00000000 --- a/app/models/email_subscription.rb +++ /dev/null @@ -1,65 +0,0 @@ -class EmailSubscription < ApplicationRecord - class SubscriberListNotFound < StandardError; end - - belongs_to :oidc_user - - validates :name, presence: true - validates :topic_slug, presence: true - - before_destroy :deactivate! - - def to_hash - { - "name" => name, - "topic_slug" => topic_slug, - "email_alert_api_subscription_id" => email_alert_api_subscription_id, - }.compact - end - - def activated? - email_alert_api_subscription_id.present? - end - - def check_if_still_active! - GdsApi - .email_alert_api.get_subscription(email_alert_api_subscription_id) - .dig("subscription", "ended_reason") - .blank? - rescue GdsApi::HTTPGone, GdsApi::HTTPNotFound - false - end - - def reactivate_if_confirmed! - deactivate! - - return unless oidc_user.email - return unless oidc_user.email_verified - - subscriber_list = - begin - GdsApi.email_alert_api.get_subscriber_list(slug: topic_slug) - rescue GdsApi::HTTPNotFound - raise SubscriberListNotFound - end - - subscription = GdsApi.email_alert_api.subscribe( - subscriber_list_id: subscriber_list.dig("subscriber_list", "id"), - address: oidc_user.email, - frequency: "daily", - skip_confirmation_email: true, - ) - - update!(email_alert_api_subscription_id: subscription.dig("subscription", "id")) - end - - def deactivate! - return unless email_alert_api_subscription_id - - GdsApi.email_alert_api.unsubscribe(email_alert_api_subscription_id) - rescue GdsApi::HTTPGone, GdsApi::HTTPNotFound - # this can happen if the subscription has been deactivated by the - # user through email-alert-frontend - ensure - update!(email_alert_api_subscription_id: nil) - end -end diff --git a/db/migrate/20230824083133_drop_email_subscriptions.rb b/db/migrate/20230824083133_drop_email_subscriptions.rb new file mode 100644 index 00000000..bab19051 --- /dev/null +++ b/db/migrate/20230824083133_drop_email_subscriptions.rb @@ -0,0 +1,5 @@ +class DropEmailSubscriptions < ActiveRecord::Migration[7.0] + def up + drop_table :email_subscriptions + end +end diff --git a/db/schema.rb b/db/schema.rb index f7dd427d..73d2f8ff 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2022_06_10_101751) do +ActiveRecord::Schema[7.0].define(version: 2023_08_24_083133) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -22,17 +22,6 @@ t.datetime "updated_at", null: false end - create_table "email_subscriptions", force: :cascade do |t| - t.bigint "oidc_user_id", null: false - t.string "name", null: false - t.string "topic_slug", null: false - t.string "email_alert_api_subscription_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["oidc_user_id", "name"], name: "index_email_subscriptions_on_oidc_user_id_and_name", unique: true - t.index ["oidc_user_id"], name: "index_email_subscriptions_on_oidc_user_id" - end - create_table "oidc_users", force: :cascade do |t| t.string "sub", null: false t.datetime "created_at", default: -> { "now()" }, null: false diff --git a/spec/models/email_subscription_spec.rb b/spec/models/email_subscription_spec.rb deleted file mode 100644 index 6face272..00000000 --- a/spec/models/email_subscription_spec.rb +++ /dev/null @@ -1,121 +0,0 @@ -require "gds_api/test_helpers/email_alert_api" - -RSpec.describe EmailSubscription do - include GdsApi::TestHelpers::EmailAlertApi - - subject(:email_subscription) do - FactoryBot.create( - :email_subscription, - oidc_user:, - name:, - email_alert_api_subscription_id:, - ) - end - - let(:oidc_user) { FactoryBot.create(:oidc_user) } - - let(:email) { "email@example.com" } - let(:name) { "subscription-name" } - let(:email_alert_api_subscription_id) { nil } - - describe "associations" do - it { is_expected.to belong_to(:oidc_user) } - end - - describe "validations" do - it { is_expected.to validate_presence_of(:name) } - it { is_expected.to validate_presence_of(:topic_slug) } - end - - describe "reactivate_if_confirmed!" do - let(:email) { "email@example.com" } - let(:email_verified) { false } - - before { email_subscription.oidc_user.update!(email:, email_verified:) } - - it "doesn't call email-alert-api if the user is not confirmed" do - stub = stub_subscriber_list - - email_subscription.reactivate_if_confirmed! - - expect(stub).not_to have_been_made - end - - context "when the user is confirmed" do - let(:email_verified) { true } - - it "calls email-alert-api to create the subscription" do - stub1 = stub_subscriber_list - stub2 = stub_create_subscription - - email_subscription.reactivate_if_confirmed! - - expect(stub1).to have_been_made - expect(stub2).to have_been_made - expect(email_subscription.email_alert_api_subscription_id).to eq("new-subscription-id") - end - - context "when the user has a prior subscription" do - let(:email_alert_api_subscription_id) { "prior-subscription-id" } - - it "calls email-alert-api to remove the prior subscription" do - stub = stub_email_alert_api_unsubscribes_a_subscription("prior-subscription-id") - stub_subscriber_list - stub_create_subscription - - email_subscription.reactivate_if_confirmed! - - expect(stub).to have_been_made - end - end - - def stub_create_subscription - stub_email_alert_api_creates_a_subscription( - subscriber_list_id: "list-id", - address: email, - frequency: "daily", - returned_subscription_id: "new-subscription-id", - skip_confirmation_email: true, - ) - end - end - end - - describe "deactivate!" do - subject(:email_subscription) { FactoryBot.build(:email_subscription, email_alert_api_subscription_id: "prior-subscription-id") } - - it "calls email-alert-api to remove the prior subscription and forgets the subscription id" do - stub = stub_email_alert_api_unsubscribes_a_subscription("prior-subscription-id") - - email_subscription.deactivate! - - expect(email_subscription.reload.email_alert_api_subscription_id).to be_nil - expect(stub).to have_been_made - end - - context "when the subscription has been ended in email-alert-api" do - before { stub_email_alert_api_has_no_subscription_for_uuid("prior-subscription-id") } - - it "sets the email_alert_api_subscription_id to nil" do - email_subscription.deactivate! - - expect(email_subscription.reload.email_alert_api_subscription_id).to be_nil - end - end - - it "calls deactivate! on destroy" do - stub = stub_email_alert_api_unsubscribes_a_subscription("prior-subscription-id") - - email_subscription.destroy! - - expect(stub).to have_been_made - end - end - - def stub_subscriber_list - stub_email_alert_api_has_subscriber_list_by_slug( - slug: email_subscription.topic_slug, - returned_attributes: { id: "list-id" }, - ) - end -end From dd452516b6687bcb99938658dbd6f66f26575887 Mon Sep 17 00:00:00 2001 From: Keith Lawrence Date: Thu, 24 Aug 2023 10:56:37 +0100 Subject: [PATCH 2/6] Update OIDC User Controller to remove EmailSubscription branch --- .../internal/oidc_users_controller.rb | 27 +++---------------- 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/app/controllers/internal/oidc_users_controller.rb b/app/controllers/internal/oidc_users_controller.rb index 56683106..3d745da3 100644 --- a/app/controllers/internal/oidc_users_controller.rb +++ b/app/controllers/internal/oidc_users_controller.rb @@ -45,34 +45,14 @@ def authorise_sso_user! end def update_email_alert_api_address(user) - # if the user has linked their notifications account to their - # GOV.UK account we don't need to update their - # `user.email_subscriptions`, because we can update the subscriber - # directly. GdsApi.email_alert_api.change_subscriber( id: email_alert_api_subscriber_id(user), new_address: user.email, on_conflict: "merge", ) rescue GdsApi::HTTPNotFound - # but for users who haven't linked their notifications account to - # their GOV.UK account, we do need to update any account-linked - # subscriptions they have (eg, brexit checker users who haven't - # touched notifications since registering through the checker). - # - # this branch can be removed once we have no GOV.UK accounts which - # have subscriptions but are *not* linked to the corresponding - # notifications account. - user.email_subscriptions.find_each do |subscription| - if subscription.activated? && !subscription.check_if_still_active! - subscription.destroy! - next - end - - subscription.reactivate_if_confirmed! - rescue EmailSubscription::SubscriberListNotFound - subscription.destroy! - end + # No linked email-alert-api account, nothing to do + nil end def end_email_alert_api_subscriptions(user) @@ -80,8 +60,7 @@ def end_email_alert_api_subscriptions(user) email_alert_api_subscriber_id(user), ) rescue GdsApi::HTTPNotFound - # if there is no linked notifications account, there is nothing to - # do + # No linked email-alert-api account, nothing to do nil end From 84b3826d58ded74636971421d74d1e80c6c177e9 Mon Sep 17 00:00:00 2001 From: Keith Lawrence Date: Thu, 24 Aug 2023 10:57:06 +0100 Subject: [PATCH 3/6] Remove email_subscriptions relation from OIDC User --- app/models/oidc_user.rb | 2 - spec/requests/oidc_users_spec.rb | 87 -------------------------------- 2 files changed, 89 deletions(-) diff --git a/app/models/oidc_user.rb b/app/models/oidc_user.rb index 9ac8e413..72c63d91 100644 --- a/app/models/oidc_user.rb +++ b/app/models/oidc_user.rb @@ -1,6 +1,4 @@ class OidcUser < ApplicationRecord - has_many :email_subscriptions, dependent: :destroy - validates :sub, presence: true before_destroy :create_tombstone diff --git a/spec/requests/oidc_users_spec.rb b/spec/requests/oidc_users_spec.rb index ef2e1c39..f92b0c5a 100644 --- a/spec/requests/oidc_users_spec.rb +++ b/spec/requests/oidc_users_spec.rb @@ -113,93 +113,6 @@ expect(stub).to have_been_made end end - - context "when the user has an email subscription" do - before { EmailSubscription.create!(oidc_user: user, name: "name", topic_slug: "slug", email_alert_api_subscription_id: prior_subscription_id) } - - let(:prior_subscription_id) { nil } - - it "activates it" do - stub_fetch_topic = stub_email_alert_api_has_subscriber_list_by_slug(slug: "slug", returned_attributes: { id: "list-id" }) - stub_create_new = stub_email_alert_api_creates_a_subscription( - subscriber_list_id: "list-id", - address: email, - frequency: "daily", - returned_subscription_id: "new-subscription-id", - skip_confirmation_email: true, - ) - - put(oidc_user_path(subject_identifier:), params:, headers:) - - expect(stub_fetch_topic).to have_been_made - expect(stub_create_new).to have_been_made - end - - context "when the email and email_verified attributes have not changed" do - let(:email) { user.email } - let(:email_verified) { user.email_verified } - - it "does not make any requests to email-alert-api" do - put oidc_user_path(subject_identifier:), params:, headers: - end - end - - context "when the subscriber list has been deleted from email-alert-api" do - before do - stub_email_alert_api_does_not_have_subscriber_list_by_slug(slug: "slug") - end - - it "deletes the subscription" do - expect { put oidc_user_path(subject_identifier:), params:, headers: }.to change(EmailSubscription, :count).by(-1) - end - end - - context "when the subscription has been activated" do - let(:prior_subscription_id) { "prior-subscription-id" } - - it "reactivates it" do - stub_email_alert_api_has_subscription(prior_subscription_id, "daily") - stub_cancel_old = stub_email_alert_api_unsubscribes_a_subscription(prior_subscription_id) - stub_fetch_topic = stub_email_alert_api_has_subscriber_list_by_slug(slug: "slug", returned_attributes: { id: "list-id" }) - stub_create_new = stub_email_alert_api_creates_a_subscription( - subscriber_list_id: "list-id", - address: email, - frequency: "daily", - returned_subscription_id: "new-subscription-id", - skip_confirmation_email: true, - ) - - put(oidc_user_path(subject_identifier:), params:, headers:) - - expect(stub_cancel_old).to have_been_made - expect(stub_fetch_topic).to have_been_made - expect(stub_create_new).to have_been_made - end - - context "when the subscription has been deactivated in email-alert-api" do - before do - stub_email_alert_api_has_subscription(prior_subscription_id, "daily", ended: true) - end - - it "deletes the subscription" do - stub_email_alert_api_unsubscribes_a_subscription(prior_subscription_id) - expect { put oidc_user_path(subject_identifier:), params:, headers: }.to change(EmailSubscription, :count).by(-1) - end - end - - context "when the subscriber list has been deleted from email-alert-api" do - before do - stub_email_alert_api_does_not_have_subscriber_list_by_slug(slug: "slug") - end - - it "deletes the subscription" do - stub_email_alert_api_has_subscription(prior_subscription_id, "daily") - stub_email_alert_api_unsubscribes_a_subscription(prior_subscription_id) - expect { put oidc_user_path(subject_identifier:), params:, headers: }.to change(EmailSubscription, :count).by(-1) - end - end - end - end end end From 9b4e4b3e03de265d0a605ff6b5655af5b3c5c3db Mon Sep 17 00:00:00 2001 From: Keith Lawrence Date: Thu, 24 Aug 2023 11:28:24 +0100 Subject: [PATCH 4/6] Remove EmailSubscriptionsController --- .../email_subscriptions_controller.rb | 49 ----- config/routes.rb | 2 - spec/requests/email_subscriptions_spec.rb | 167 ------------------ 3 files changed, 218 deletions(-) delete mode 100644 app/controllers/internal/email_subscriptions_controller.rb delete mode 100644 spec/requests/email_subscriptions_spec.rb diff --git a/app/controllers/internal/email_subscriptions_controller.rb b/app/controllers/internal/email_subscriptions_controller.rb deleted file mode 100644 index 46821a42..00000000 --- a/app/controllers/internal/email_subscriptions_controller.rb +++ /dev/null @@ -1,49 +0,0 @@ -class Internal::EmailSubscriptionsController < InternalController - include AuthenticatedApiConcern - - before_action :check_subscription_exists, only: %i[show destroy] - - def show - if email_subscription.activated? && !email_subscription.check_if_still_active! - email_subscription.destroy! - head :not_found and return - end - - render_api_response(email_subscription: email_subscription.to_hash) - end - - def update - @govuk_account_session.get_attributes(%w[email email_verified]) - - email_subscription = EmailSubscription.transaction do - EmailSubscription - .create_with(topic_slug: params.fetch(:topic_slug)) - .find_or_create_by!( - oidc_user_id: @govuk_account_session.user.id, - name: params.fetch(:subscription_name), - ).tap { |subscription| subscription.update!(topic_slug: params.fetch(:topic_slug)) } - end - - email_subscription.reactivate_if_confirmed! - - render_api_response(email_subscription: email_subscription.to_hash) - end - - def destroy - email_subscription.destroy! - head :no_content - end - -private - - def email_subscription - @email_subscription ||= EmailSubscription.find_by( - oidc_user: @govuk_account_session.user, - name: params.fetch(:subscription_name), - ) - end - - def check_subscription_exists - head :not_found unless email_subscription - end -end diff --git a/config/routes.rb b/config/routes.rb index 5038f9ec..0d88afdf 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -21,8 +21,6 @@ get "/attributes", to: "attributes#show" patch "/attributes", to: "attributes#update" - - resources :email_subscriptions, only: %i[show update destroy], param: :subscription_name, path: "email-subscriptions" end namespace :personalisation do diff --git a/spec/requests/email_subscriptions_spec.rb b/spec/requests/email_subscriptions_spec.rb deleted file mode 100644 index 0b776d3f..00000000 --- a/spec/requests/email_subscriptions_spec.rb +++ /dev/null @@ -1,167 +0,0 @@ -require "gds_api/test_helpers/email_alert_api" - -RSpec.describe "Email subscriptions" do - include GdsApi::TestHelpers::EmailAlertApi - - let(:headers) { { "Content-Type" => "application/json", "GOVUK-Account-Session" => session_identifier.serialise } } - let(:session_identifier) { placeholder_govuk_account_session_object } - - describe "GET /api/email-subscriptions/:subscription_name" do - it "returns a 404" do - get(email_subscription_path(subscription_name: "foo"), headers:) - expect(response).to have_http_status(:not_found) - end - - context "when the subscription exists" do - before do - stub_email_alert_api_has_subscription( - email_subscription.email_alert_api_subscription_id, - "daily", - ended: subscription_ended, - ) - end - - let(:email_subscription) do - FactoryBot.create(:email_subscription, oidc_user: session_identifier.user, email_alert_api_subscription_id: "prior-subscription-id") - end - - let(:subscription_ended) { false } - - it "returns the subscription details" do - get(email_subscription_path(subscription_name: email_subscription.name), headers:) - expect(response).to be_successful - expect(JSON.parse(response.body)["email_subscription"]).to eq(email_subscription.to_hash) - end - - context "when the subscription has been ended in email-alert-api" do - let(:subscription_ended) { true } - - it "deletes the subscription here and returns a 404" do - stub_email_alert_api_unsubscribes_a_subscription(email_subscription.email_alert_api_subscription_id) - expect { get email_subscription_path(subscription_name: email_subscription.name), headers: }.to change(EmailSubscription, :count).by(-1) - expect(response).to have_http_status(:not_found) - end - end - end - end - - describe "PUT /api/email-subscriptions/:subscription_name" do - let(:params) { { topic_slug: "slug" } } - let(:email) { "email@example.com" } - let(:email_verified) { false } - - it "creates a new subscription record if one doesn't already exist" do - stub_local_attributes - - expect { put email_subscription_path(subscription_name: "name"), params: params.to_json, headers: }.to change(EmailSubscription, :count).by(1) - - expect(response).to be_successful - expect(JSON.parse(response.body)["email_subscription"]).to eq(EmailSubscription.last.to_hash) - end - - context "when the email and email verified attributes are not cached locally" do - it "returns a 401" do - expect { put email_subscription_path(subscription_name: "name"), params: params.to_json, headers: }.not_to change(EmailSubscription, :count) - - expect(response).to have_http_status(:unauthorized) - end - end - - context "when the user has verified their email address" do - let(:email_verified) { true } - - it "calls email-alert-api to create the subscription" do - expect_activate_email_subscription do - stub_local_attributes - - expect { put email_subscription_path(subscription_name: "name"), params: params.to_json, headers: }.to change(EmailSubscription, :count).by(1) - - expect(response).to be_successful - expect(JSON.parse(response.body)["email_subscription"]).to eq(EmailSubscription.last.to_hash) - end - end - end - - context "when the subscription already exists" do - let!(:email_subscription) do - FactoryBot.create(:email_subscription, oidc_user: session_identifier.user, email_alert_api_subscription_id: "prior-subscription-id") - end - - before { stub_local_attributes } - - it "calls email-alert-api to deactivate the old subscription" do - stub_cancel_old = stub_email_alert_api_unsubscribes_a_subscription(email_subscription.email_alert_api_subscription_id) - - put(email_subscription_path(subscription_name: email_subscription.name), params: params.to_json, headers:) - - expect(response).to be_successful - expect(JSON.parse(response.body)["email_subscription"]).to eq(EmailSubscription.last.to_hash) - expect(stub_cancel_old).to have_been_made - end - - context "when the user has verified their email address" do - let(:email_verified) { true } - - it "calls email-alert-api to create the new subscription" do - expect_activate_email_subscription do - stub_email_alert_api_unsubscribes_a_subscription(email_subscription.email_alert_api_subscription_id) - - put(email_subscription_path(subscription_name: email_subscription.name), params: params.to_json, headers:) - - expect(response).to be_successful - expect(JSON.parse(response.body)["email_subscription"]).to eq(EmailSubscription.last.to_hash) - end - end - end - end - - def stub_local_attributes - session_identifier.user.update!( - email:, - email_verified:, - ) - end - - def expect_activate_email_subscription - stub_fetch_topic = stub_email_alert_api_has_subscriber_list_by_slug( - slug: params[:topic_slug], - returned_attributes: { id: "list-id" }, - ) - - stub_create_new = stub_email_alert_api_creates_a_subscription( - subscriber_list_id: "list-id", - address: "email@example.com", - frequency: "daily", - returned_subscription_id: "new-subscription-id", - skip_confirmation_email: true, - ) - - yield - - expect(stub_fetch_topic).to have_been_made - expect(stub_create_new).to have_been_made - end - end - - describe "DELETE /api/email-subscriptions/:subscription_name" do - it "returns a 404" do - delete(email_subscription_path(subscription_name: "foo"), headers:) - expect(response).to have_http_status(:not_found) - end - - context "when the subscription exists" do - let!(:email_subscription) do - FactoryBot.create(:email_subscription, oidc_user: session_identifier.user, email_alert_api_subscription_id: "prior-subscription-id") - end - - it "deletes it, calls email-alert-api to cancel the old subscription, and returns a 204" do - stub_cancel_old = stub_email_alert_api_unsubscribes_a_subscription(email_subscription.email_alert_api_subscription_id) - - expect { delete email_subscription_path(subscription_name: email_subscription.name), headers: }.to change(EmailSubscription, :count).by(-1) - - expect(response).to have_http_status(:no_content) - expect(stub_cancel_old).to have_been_made - end - end - end -end From 9bddffb83eabf3450162f9a0c3b6f3f40f8c9c75 Mon Sep 17 00:00:00 2001 From: Keith Lawrence Date: Thu, 24 Aug 2023 11:28:39 +0100 Subject: [PATCH 5/6] Remove EmailSubscriptionFactory --- spec/factories/email_subscription_factory.rb | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 spec/factories/email_subscription_factory.rb diff --git a/spec/factories/email_subscription_factory.rb b/spec/factories/email_subscription_factory.rb deleted file mode 100644 index 87dd1b59..00000000 --- a/spec/factories/email_subscription_factory.rb +++ /dev/null @@ -1,7 +0,0 @@ -FactoryBot.define do - factory :email_subscription do - oidc_user - sequence(:name) { |n| "subscription-#{n}" } - sequence(:topic_slug) { |n| "topic-#{n}" } - end -end From 14ab0c08e3da8361f0bed9a42818cf952f61ae6c Mon Sep 17 00:00:00 2001 From: Keith Lawrence Date: Thu, 24 Aug 2023 11:28:54 +0100 Subject: [PATCH 6/6] Remove EmailSubscription states from pact helper --- spec/service_consumers/pact_helper.rb | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/spec/service_consumers/pact_helper.rb b/spec/service_consumers/pact_helper.rb index 86b4d435..abd2a4b6 100644 --- a/spec/service_consumers/pact_helper.rb +++ b/spec/service_consumers/pact_helper.rb @@ -15,21 +15,6 @@ def stub_cached_attributes(email_verified: true) email_verified:, ) end - - def stub_will_create_email_subscription(topic_slug, subscriber_list_id: "list-id") - stub_email_alert_api_has_subscriber_list_by_slug( - slug: topic_slug, - returned_attributes: { id: subscriber_list_id }, - ) - - stub_email_alert_api_creates_a_subscription( - subscriber_list_id:, - address: EMAIL_ADDRESS, - frequency: "daily", - returned_subscription_id: "subscription-id", - skip_confirmation_email: true, - ) - end end def oidc_user @@ -125,21 +110,12 @@ def url_encode(str) provider_state "there is a valid user session" do set_up do stub_cached_attributes - stub_will_create_email_subscription "wizard-news-topic-slug" # rubocop:disable RSpec/AnyInstance allow_any_instance_of(AccountSession).to receive(:set_remote_attributes) # rubocop:enable RSpec/AnyInstance end end - provider_state "there is a valid user session, with a 'wizard-news' email subscription" do - set_up do - stub_cached_attributes - stub_will_create_email_subscription "wizard-news-topic-slug" - FactoryBot.create(:email_subscription, name: "wizard-news", oidc_user_id: oidc_user.id) - end - end - provider_state "there is a valid user session, with an attribute called 'email'" do set_up do stub_cached_attributes