mirror of
https://github.com/discourse/discourse.git
synced 2024-12-12 12:33:44 +08:00
88ecb650a9
This is a bottom up rewrite of Discourse cache to support faster performance and a limited surface area. ActiveSupport::Cache::Store accepts many options we do not use, this partial implementation only picks the bits out that we do use and want to support. Additionally params are named which avoids typos such as "expires_at" vs "expires_in" This also moves a few spots in Discourse to use Discourse.cache over setex Performance of setex and Discourse.cache.write is similar.
162 lines
5.1 KiB
Ruby
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}"
|
|
Discourse.cache.write key, user.email, expires_in: 1.hour
|
|
|
|
url = path("/email/unsubscribed?key=#{key}")
|
|
if topic
|
|
url += "&topic_id=#{topic.id}"
|
|
end
|
|
|
|
redirect_to url
|
|
end
|
|
|
|
end
|
|
|
|
def unsubscribed
|
|
@email = Discourse.cache.read(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
|