* Create "blank" EmailSubscriptionTag * Refactor liquid_tags_used with spec * Create /user_subscriptions#create - Update liquid tag name to UserSubscriptionTag * Add rate limiting and specs * Add counter_culture for user_subscriptions * Update /async_info/base_data - Alphabetize user_data - Add email - Add subscription_source_article_ids - Cache subscription_source_article_ids on User model * Add stale email check and specs * Change user_email to subscriber_email for clarity * Restrict UserSubscriptionTag * Rename RESTRICTED_TAGS to RESTRICTED_LIQUID_TAGS * Make TODO comment more clear * Refactor error responses and update specs * Update type to source_type in error message * Use constantize over safe_constantize * Add check for active source * Refactor checking of current_user's subscriptions - Remove data from async_info - Create a new service to fetch/cache a user's existing subscriptions * Restrict email in base_data to admin roles * Oops! Rename liquid tag file * Change error back to result...oops! * It's not goodbye, it's see you later. RIP email :/ * Add current_email to /user_subscriptions/base_data * Revert adding current_email * Undo async_info_controller changes/fix conflict * Move params to constant * Refactor SubscriptionCacheChecker * Remove duplicate status code in JSON response * Remove duplicate status code for #subscribed * Use response.parsed_body * Remove user guard in SubscriptionCacheChecker
85 lines
2.9 KiB
Ruby
85 lines
2.9 KiB
Ruby
class UserSubscriptionsController < ApplicationController
|
|
before_action :authenticate_user!
|
|
|
|
USER_SUBSCRIPTION_PARAMS = %i[source_type source_id subscriber_email].freeze
|
|
|
|
def subscribed
|
|
params.require(%i[source_type source_id])
|
|
source_type = params[:source_type]
|
|
source_id = params[:source_id]
|
|
|
|
is_subscribed = UserSubscriptions::SubscriptionCacheChecker.call(current_user, source_type, source_id)
|
|
|
|
render json: { is_subscribed: is_subscribed, success: true }, status: :ok
|
|
end
|
|
|
|
def create
|
|
rate_limit!(:user_subscription_creation)
|
|
|
|
source_type = user_subscription_params[:source_type]
|
|
return error_response("invalid source_type") unless UserSubscription::ALLOWED_TYPES.include?(source_type)
|
|
|
|
source_id = user_subscription_params[:source_id]
|
|
user_subscription_source = source_type.constantize.find_by(id: source_id)
|
|
return error_response("source not found") unless active_source?(source_type, user_subscription_source)
|
|
|
|
unless user_subscription_tag_enabled?(source_type, user_subscription_source)
|
|
return error_response("user subscriptions are not enabled for the requested source")
|
|
end
|
|
|
|
return error_response("subscriber email mismatch") if subscriber_email_stale?
|
|
|
|
@user_subscription = user_subscription_source.build_user_subscription(current_user)
|
|
|
|
if @user_subscription.save
|
|
rate_limiter.track_limit_by_action(:user_subscription_creation)
|
|
render json: { message: "success", success: true }, status: :ok
|
|
else
|
|
error_response(@user_subscription.errors.full_messages.to_sentence)
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def user_subscription_tag_enabled?(source_type, user_subscription_source)
|
|
liquid_tags =
|
|
case source_type
|
|
when "Article"
|
|
user_subscription_source.liquid_tags_used(:body)
|
|
else
|
|
user_subscription_source.liquid_tags_used
|
|
end
|
|
|
|
liquid_tags.include?(UserSubscriptionTag)
|
|
end
|
|
|
|
def active_source?(source_type, user_subscription_source)
|
|
return false unless user_subscription_source
|
|
|
|
# Don't create new user subscriptions for inactive sources
|
|
# (i.e. unpublished Articles, deleted Comments, etc.)
|
|
case source_type
|
|
when "Article"
|
|
user_subscription_source.published?
|
|
else
|
|
false
|
|
end
|
|
end
|
|
|
|
def error_response(msg)
|
|
render json: { error: msg, success: false }, status: :unprocessable_entity
|
|
end
|
|
|
|
# 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.
|
|
def subscriber_email_stale?
|
|
current_user&.email != user_subscription_params[:subscriber_email]
|
|
end
|
|
|
|
def user_subscription_params
|
|
params.require(:user_subscription).permit(USER_SUBSCRIPTION_PARAMS)
|
|
end
|
|
end
|