discourse/app/controllers/email_controller.rb
Sam Saffron 30990006a9 DEV: enable frozen string literal on all files
This reduces chances of errors where consumers of strings mutate inputs
and reduces memory usage of the app.

Test suite passes now, but there may be some stuff left, so we will run
a few sites on a branch prior to merging
2019-05-13 09:31:32 +08:00

162 lines
5.1 KiB
Ruby

# frozen_string_literal: true
class EmailController < ApplicationController
layout 'no_ember'
skip_before_action :check_xhr, :preload_json, :redirect_to_login_if_required
before_action :ensure_logged_in, only: :preferences_redirect
def preferences_redirect
redirect_to(email_preferences_path(current_user.username_lower))
end
def unsubscribe
@not_found = true
@watched_count = nil
if key = UnsubscribeKey.find_by(key: params[:key])
if @user = key.user
post = key.post
@topic = post&.topic || key.topic
@digest_unsubscribe = !@topic && !SiteSetting.disable_digest_emails
@type = key.unsubscribe_key_type
@not_found = false
if current_user.present? && (@user != current_user)
@different_user = @user.name
@return_url = request.original_url
end
watching = TopicUser.notification_levels[:watching]
if @topic
@watching_topic = TopicUser.exists?(user_id: @user.id, notification_level: watching, topic_id: @topic.id)
if @topic.category_id
if CategoryUser.exists?(user_id: @user.id, notification_level: CategoryUser.watching_levels, category_id: @topic.category_id)
@watched_count = TopicUser.joins(:topic)
.where(user: @user, notification_level: watching, "topics.category_id" => @topic.category_id)
.count
end
end
else
@digest_frequencies = digest_frequencies(@user)
end
end
end
end
def perform_unsubscribe
RateLimiter.new(nil, "unsubscribe_#{request.ip}", 10, 1.minute).performed!
key = UnsubscribeKey.find_by(key: params[:key])
raise Discourse::NotFound unless key && key.user
topic = key&.post&.topic || key.topic
user = key.user
updated = false
if topic
if params["unwatch_topic"]
TopicUser.where(topic_id: topic.id, user_id: user.id)
.update_all(notification_level: TopicUser.notification_levels[:tracking])
updated = true
end
if params["unwatch_category"] && topic.category_id
TopicUser.joins(:topic)
.where(:user => user,
:notification_level => TopicUser.notification_levels[:watching],
"topics.category_id" => topic.category_id)
.update_all(notification_level: TopicUser.notification_levels[:tracking])
CategoryUser.where(user_id: user.id,
category_id: topic.category_id,
notification_level: CategoryUser.watching_levels
)
.destroy_all
updated = true
end
if params["mute_topic"]
TopicUser.where(topic_id: topic.id, user_id: user.id)
.update_all(notification_level: TopicUser.notification_levels[:muted])
updated = true
end
end
if params["disable_mailing_list"]
user.user_option.update_columns(mailing_list_mode: false)
updated = true
end
if params['digest_after_minutes']
digest_frequency = params['digest_after_minutes'].to_i
user.user_option.update_columns(
digest_after_minutes: digest_frequency,
email_digests: digest_frequency.positive?
)
updated = true
end
if params["unsubscribe_all"]
user.user_option.update_columns(email_digests: false,
email_level: UserOption.email_level_types[:never],
email_messages_level: UserOption.email_level_types[:never])
updated = true
end
unless updated
redirect_back fallback_location: path("/")
else
key = "unsub_#{SecureRandom.hex}"
$redis.setex key, 1.hour, user.email
url = path("/email/unsubscribed?key=#{key}")
if topic
url += "&topic_id=#{topic.id}"
end
redirect_to url
end
end
def unsubscribed
@email = $redis.get(params[:key])
@topic_id = params[:topic_id]
user = User.find_by_email(@email)
raise Discourse::NotFound unless user
topic = Topic.find_by(id: params[:topic_id].to_i) if @topic_id
@topic = topic if topic && Guardian.new(nil).can_see?(topic)
end
private
def digest_frequencies(user)
frequency_in_minutes = user.user_option.digest_after_minutes
frequencies = DigestEmailSiteSetting.values.dup
never = frequencies.delete_at(0)
allowed_frequencies = %w[never weekly every_month every_six_months]
result = frequencies.reduce(frequencies: [], current: nil, selected: nil, take_next: false) do |memo, v|
memo[:current] = v[:name] if v[:value] == frequency_in_minutes
next(memo) unless allowed_frequencies.include?(v[:name])
memo.tap do |m|
m[:selected] = v[:value] if m[:take_next]
m[:frequencies] << [I18n.t("unsubscribe.digest_frequency.#{v[:name]}"), v[:value]]
m[:take_next] = !m[:take_next] && m[:current]
end
end
result.slice(:frequencies, :current, :selected).tap do |r|
r[:frequencies] << [I18n.t("unsubscribe.digest_frequency.#{never[:name]}"), never[:value]]
r[:selected] ||= never[:value]
r[:current] ||= never[:name]
end
end
end