173 lines
7.1 KiB
Ruby
173 lines
7.1 KiB
Ruby
#
|
|
# Copyright (C) 2011 Instructure, Inc.
|
|
#
|
|
# This file is part of Canvas.
|
|
#
|
|
# Canvas is free software: you can redistribute it and/or modify it under
|
|
# the terms of the GNU Affero General Public License as published by the Free
|
|
# Software Foundation, version 3 of the License.
|
|
#
|
|
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
# details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License along
|
|
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
|
|
class NotificationPolicy < ActiveRecord::Base
|
|
|
|
belongs_to :notification
|
|
belongs_to :communication_channel
|
|
|
|
before_save :infer_frequency
|
|
|
|
attr_accessible :notification, :communication_channel, :frequency, :notification_id, :communication_channel_id
|
|
|
|
validates_presence_of :communication_channel_id
|
|
validates_inclusion_of :broadcast, in: [true, false]
|
|
|
|
# This is for choosing a policy for another context, so:
|
|
# NotificationPolicy.for(notification) or
|
|
# communication_channel.notification_policies.for(notification)
|
|
scope :for, lambda { |context|
|
|
case context
|
|
when User
|
|
joins(:communication_channel).
|
|
where("communication_channels.user_id=? AND communication_channels.workflow_state<>'retired'", context)
|
|
when Notification
|
|
where(:notification_id => context)
|
|
else
|
|
scoped
|
|
end
|
|
}
|
|
|
|
# TODO: the scope name should be self-explanatory... change this to
|
|
# by_frequency or something This is for choosing a policy by frequency
|
|
scope :by, lambda { |freq| where(:frequency => Array(freq).map(&:to_s)) }
|
|
|
|
scope :in_state, lambda { |state| where(:workflow_state => state.to_s) }
|
|
|
|
def infer_frequency
|
|
self.frequency ||= "immediately"
|
|
end
|
|
protected :infer_frequency
|
|
|
|
def communication_preference
|
|
return nil unless broadcast
|
|
communication_channel || user.communication_channel
|
|
end
|
|
|
|
def self.spam_blocked_by(user)
|
|
NotificationPolicy.where(:communication_channel_id => user.communication_channels.pluck(:id)).delete_all
|
|
cc = user.communication_channel
|
|
cc.confirm
|
|
Notification.all.each do |notification|
|
|
if notification.category == "Message"
|
|
NotificationPolicy.create(:notification => notification, :communication_channel => cc, :frequency => 'immediately')
|
|
else
|
|
NotificationPolicy.create(:notification => notification, :communication_channel => cc, :frequency => 'never')
|
|
end
|
|
end
|
|
true
|
|
rescue => e
|
|
puts e.to_s
|
|
false
|
|
end
|
|
|
|
def self.setup_for(user, params)
|
|
# Check for user preference settings first. Some communication related options are available on the page.
|
|
# Handle those if given.
|
|
user_prefs = params[:user]
|
|
# If have user preference settings and this is a root account, check further to see if settings can be changed
|
|
if user_prefs && params[:root_account]
|
|
user_prefs.each_pair do |key, value|
|
|
bool_val = (value == 'true')
|
|
# save the preference as a symbol (convert from string)
|
|
case key.to_sym
|
|
when :send_scores_in_emails
|
|
# Only set if a root account and the root account allows the setting.
|
|
if params[:root_account].settings[:allow_sending_scores_in_emails] != false
|
|
user.preferences[:send_scores_in_emails] = bool_val
|
|
end
|
|
when :no_submission_comments_inbox
|
|
user.preferences[:no_submission_comments_inbox] = bool_val
|
|
end
|
|
end
|
|
user.save!
|
|
else
|
|
# User preference change not being made. Make a notification policy change.
|
|
|
|
# Using the category name, fetch all Notifications for the category. Will set the desired value on them.
|
|
notifications = Notification.where(:category => params[:category]).pluck(:id)
|
|
# Look for frequency settings and only recognize a valid value.
|
|
frequency = case params[:frequency]
|
|
when Notification::FREQ_IMMEDIATELY, Notification::FREQ_DAILY, Notification::FREQ_WEEKLY, Notification::FREQ_NEVER
|
|
params[:frequency]
|
|
else
|
|
Notification::FREQ_NEVER
|
|
end
|
|
|
|
# Find any existing NotificationPolicies for the category and the channel. If frequency is 'never', delete the
|
|
# entry. If other than than, create or update the entry.
|
|
NotificationPolicy.transaction do
|
|
notifications.each do |notification_id|
|
|
# can't use hash syntax for the where cause Rails 2 will try to call communication_channels= for the
|
|
# or_initialize portion
|
|
if CANVAS_RAILS2
|
|
p = NotificationPolicy.includes(:communication_channel).where("communication_channels.user_id=?", user).
|
|
find_or_initialize_by_communication_channel_id_and_notification_id(params[:channel_id], notification_id)
|
|
else
|
|
p = NotificationPolicy.joins(:communication_channel).where(:communication_channels => { :user_id => user }).
|
|
find_or_initialize_by_communication_channel_id_and_notification_id(params[:channel_id], notification_id)
|
|
end
|
|
# Set the frequency and save
|
|
p.frequency = frequency
|
|
p.save!
|
|
end
|
|
end # transaction
|
|
end #if..else
|
|
nil
|
|
end
|
|
|
|
# Fetch the user's NotificationPolicies but whenever a category is not
|
|
# represented, create a NotificationPolicy on the primary
|
|
# CommunicationChannel with a default frequency set.
|
|
# Returns the full list of policies for the user
|
|
#
|
|
# ===== Arguments
|
|
# * <tt>user</tt> - The User instance to load the values for.
|
|
# * <tt>full_category_list</tt> - An array of Notification models that
|
|
# represent the unique list of categories that should be displayed for the
|
|
# user.
|
|
#
|
|
# ===== Returns
|
|
# A list of NotificationPolicy entries for the user. May include newly
|
|
# created entries if defaults were needed.
|
|
def self.setup_with_default_policies(user, full_category_list)
|
|
categories = {}
|
|
# Get the list of notification categories and its default. Like this:
|
|
# {"Announcement" => 'immediately'}
|
|
full_category_list.each {|c| categories[c.category] = c.default_frequency(user) }
|
|
if default_channel_id = user.communication_channel.try(:id)
|
|
# Load unique list of categories that the user currently has settings for.
|
|
user_categories = NotificationPolicy.for(user).
|
|
includes(:notification).
|
|
where("notification_id IS NOT NULL AND communication_channel_id = ?", default_channel_id).
|
|
map{|np| np.notification.category }.uniq
|
|
missing_categories = (categories.keys - user_categories)
|
|
missing_categories.each do |need_category|
|
|
# Create the settings for a completely unrepresented category. Use
|
|
# default communication_channel (primary email)
|
|
self.setup_for(user, {:category => need_category,
|
|
:channel_id => default_channel_id,
|
|
:frequency => categories[need_category]})
|
|
end
|
|
end
|
|
# Load and return user's policies after defaults may or may not have been set.
|
|
# TODO: Don't load policies for retired channels
|
|
NotificationPolicy.includes(:notification).for(user)
|
|
end
|
|
end
|