module UserSubscriptions # When creating a UserSubscription from a controller/user interaction on the # frontend, we need to do some extra validations and logic. class CreateFromControllerParams attr_reader :user, :source_type, :source_id, :subscriber_email, :response Response = Struct.new(:success, :data, :error, keyword_init: true) def self.call(...) new(...).call end def initialize(user, user_subscription_params) @user = user @source_type = user_subscription_params[:source_type] @source_id = user_subscription_params[:source_id] @response = Response.new(success: false) # TODO: [@forem/delightful]: uncomment this once email confirmation is re-enabled # @subscriber_email = user_subscription_params[:subscriber_email] end def call return response if invalid_source_type? source = source_type.constantize.find_by(id: source_id) return response if invalid_source?(source) # TODO: [@forem/delightful]: uncomment this once email confirmation is re-enabled # return response if subscriber_email_mismatch? user_subscription = source.build_user_subscription(user) if user_subscription.save response.success = true response.data = user_subscription else response.error = user_subscription.errors_as_sentence end response end private def invalid_source_type? return false if UserSubscription::ALLOWED_TYPES.include?(source_type) response.error = "Invalid source_type." true end def invalid_source?(source) return false if source response.error = I18n.t("services.user_subscriptions.create_from_controller_params.source_not_found") true end def subscriber_email_mismatch? # This checks if the email address the user saw/consented to share is the # same as their current email address. A mismatch occurs if a user updates # their email address in a new/separate tab and then tries to subscribe on # the old/stale tab without refreshing. In that case, the user would have # consented to share their old email address instead of the current one. return false if user.email == subscriber_email response.error = I18n.t("services.user_subscriptions.create_from_controller_params.email_mismatch") true end end end