check all models for protecting attributes refs #3847

Change-Id: I7cba6e26ad98e91723e2ccf0a28b8db79bb37b5c
Reviewed-on: https://gerrit.instructure.com/3631
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Jon Jensen <jon@instructure.com>
Reviewed-by: Brian Palmer <brianp@instructure.com>
This commit is contained in:
Cody Cutrer 2011-05-13 10:49:23 -06:00
parent cfd14b4241
commit bdbebfaec8
82 changed files with 247 additions and 92 deletions

View File

@ -88,7 +88,8 @@ class AccountsController < ApplicationController
if authorized_action(@account, @current_user, :manage_admin_users)
@root_account = @account.root_account || @account
params[:pseudonym][:unique_id] ||= params[:pseudonym][:path]
@pseudonym = Pseudonym.find_or_initialize_by_unique_id_and_account_id(params[:pseudonym][:unique_id], @root_account.id)
@pseudonym = Pseudonym.find_by_unique_id_and_account_id(params[:pseudonym][:unique_id], @root_account.id)
@pseudonym ||= Pseudonym.new(:unique_id => params[:pseudonym][:unique_id], :account => @root_account)
new_login = @pseudonym.new_record?
if !@pseudonym.new_record?
user = @pseudonym.user

View File

@ -489,7 +489,7 @@ class ApplicationController < ActionController::Base
end
def generate_page_view
@page_view = PageView.new(:url => request.url[0,255], :user_id => @current_user.id, :controller => request.path_parameters['controller'], :action => request.path_parameters['action'], :session_id => request.session_options[:id], :developer_key => @developer_key, :user_agent => request.headers['User-Agent'])
@page_view = PageView.new(:url => request.url[0,255], :user => @current_user, :controller => request.path_parameters['controller'], :action => request.path_parameters['action'], :session_id => request.session_options[:id], :developer_key => @developer_key, :user_agent => request.headers['User-Agent'])
@page_view.interaction_seconds = 5
@page_view.user_request = true if params[:user_request] || (@current_user && !request.xhr? && request.method == :get)
@page_view.created_at = Time.now
@ -551,7 +551,8 @@ class ApplicationController < ActionController::Base
# it's not an update because if the page_view already existed, we don't want to
# double-count it as multiple views when it's really just a single view.
if @current_user && @accessed_asset && (@accessed_asset[:level] == 'participate' || !@page_view_update)
@access = AssetUserAccess.find_or_create_by_user_id_and_asset_code(@current_user.id, @accessed_asset[:code])
@access = AssetUserAccess.find_by_user_id_and_asset_code(@current_user.id, @accessed_asset[:code])
@access ||= AssetUserAcces.create(:user => @current_user, :asset_code => @accessed_asset[:code])
@accessed_asset[:level] ||= 'view'
if @accessed_asset[:level] == 'view'
@access.view_score ||= 0

View File

@ -323,7 +323,8 @@ class UsersController < ApplicationController
end
def create
@pseudonym = Pseudonym.find_or_initialize_by_unique_id_and_account_id(params[:pseudonym][:unique_id], @domain_root_account.id)
@pseudonym = Pseudonym.find_by_unique_id_and_account_id(params[:pseudonym][:unique_id], @domain_root_account.id)
@pseudonym ||= Pseudonym.new(:unique_id => params[:pseudonym][:unique_id], :account => @domain_root_account)
@pseudonym.save_without_session_maintenance if @pseudonym.new_record?
@active_cc = CommunicationChannel.find_by_path_and_path_type_and_workflow_state(params[:pseudonym][:unique_id], 'email', 'active')
@any_cc = CommunicationChannel.find_by_path_and_path_type(params[:pseudonym][:unique_id], 'email') unless @active_cc

View File

@ -26,7 +26,7 @@ class WikiPageCommentsController < ApplicationController
if authorized_action(@page, @current_user, :read)
if @context.allow_wiki_comments || @context.grants_right?(@current_user, nil, :manage_wiki)
@comment = @page.wiki_page_comments.build(params[:wiki_page_comment])
@comment.user_id = @current_user && @current_user.id
@comment.user = @current_user
@comment.context = @context
@comment.user_name = @current_user ? @current_user.name : request.remote_ip
if @comment.save

View File

@ -18,7 +18,7 @@
class Account < ActiveRecord::Base
include Context
attr_accessible :name, :parent_account_id, :turnitin_account_id,
attr_accessible :name, :turnitin_account_id,
:turnitin_shared_secret, :turnitin_comments, :turnitin_pledge,
:default_time_zone, :parent_account, :settings, :default_storage_quota,
:storage_quota, :ip_filters
@ -524,7 +524,8 @@ class Account < ActiveRecord::Base
user = data[:user]
end
if user
account_user = self.account_users.find_or_initialize_by_user_id(user.id)
account_user = self.account_users.find_by_user_id(user.id)
account_users ||= self.account_users.build(:user => user)
account_user.membership_type = membership_type
account_user.save
if data[:new]
@ -541,7 +542,8 @@ class Account < ActiveRecord::Base
def add_user(user, membership_type = nil)
return nil unless user && user.is_a?(User)
membership_type ||= 'AccountAdmin'
self.account_users.find_or_create_by_user_id_and_membership_type(user.id, membership_type) rescue nil
au = self.account_users.find_by_user_id_and_membership_type(user.id, membership_type)
au ||= self.account_users.create(:user => user, :membership_type => membership_type)
end
def context_code
@ -617,7 +619,8 @@ class Account < ActiveRecord::Base
# be good to create some sort of of memoize_if_safe method, that only
# memoizes when we're caching classes and not in test mode? I dunno. But
# this stinks.
return @special_accounts[special_account_type] = Account.find_or_create_by_parent_account_id_and_name(nil, default_account_name)
@special_accounts[special_account_type] = Account.find_by_parent_account_id_and_name(nil, default_account_name)
return @special_accounts[special_account_type] ||= Account.create(:parent_account => nil, :name => default_account_name)
end
account = @special_accounts[special_account_type]

View File

@ -18,6 +18,7 @@
class AccountReport < ActiveRecord::Base
include Workflow
attr_accessible :user, :account, :report_type
attr_accessor :messaging_mailbox
belongs_to :account
belongs_to :user

View File

@ -26,6 +26,7 @@ class AccountUser < ActiveRecord::Base
before_save :set_update_account_associations_if_changed
after_save :touch_user
after_save :update_account_associations_if_changed
attr_accessible :account, :user, :membership_type
def set_update_account_associations_if_changed
@should_update_account_associations = (self.account_id_changed? || self.user_id_changed?) && !self.user_id.nil?

View File

@ -103,7 +103,9 @@ class AssessmentQuestionBank < ActiveRecord::Base
end
tags_to_delete = tags.select{|t| !ids.include?(t.learning_outcome_id) }
missing_ids.each do |id|
self.learning_outcome_tags.create!(:learning_outcome_id => id.to_i, :context => self.context, :tag_type => 'learning_outcome', :mastery_score => hash[id].to_f)
lot = self.learning_outcome_tags.build(:context => self.context, :tag_type => 'learning_outcome', :mastery_score => hash[id].to_f)
lot.learning_outcome_id = id.to_i
lot.save!
end
tags_to_delete.each{|t| t.destroy }
true

View File

@ -25,6 +25,7 @@ class AssetUserAccess < ActiveRecord::Base
has_many :page_views
has_many :asset_access_ranges
before_save :infer_defaults
attr_accessible :user, :asset_code
named_scope :for_context, lambda{|context|
{:conditions => ["asset_user_accesses.context_id = ? AND asset_user_accesses.context_type = ?", context.id, context.class.to_s]}
@ -177,7 +178,8 @@ class AssetUserAccess < ActiveRecord::Base
view_month = Date.new(y=view.created_at.year, m=view.created_at.month, d=1) #view.created_at.strftime("%m:%Y")
if !found_ranges[view_week]
contexts.each do |context|
week_range = self.asset_access_ranges.find_or_initialize_by_start_on_and_end_on_and_context_id_and_context_type(view_week, view_week + 6, context.id, context.class.to_s)
week_range = self.asset_access_ranges.find_by_start_on_and_end_on_and_context_id_and_context_type(view_week, view_week + 6, context.id, context.class.to_s)
week_range ||= self.asset_access_ranges.build(:start_on => view_week, :end_on => view_week + 6, :context => context)
week_range.user_id = self.user_id
week_range.asset_code = self.asset_code
week_range.save
@ -185,7 +187,8 @@ class AssetUserAccess < ActiveRecord::Base
end
if !found_ranges[view_month]
contexts.each do |context|
month_range = self.asset_access_ranges.find_or_initialize_by_start_on_and_end_on_and_context_id_and_context_type(view_month, (view_month >> 1) - 1, context.id, context.class.to_s)
month_range = self.asset_access_ranges.find_by_start_on_and_end_on_and_context_id_and_context_type(view_month, (view_month >> 1) - 1, context.id, context.class.to_s)
month_range ||= self.asset_access_ranges.build(:start_on => view_month, :end_on => (view_month >> 1) - 1, :context => context)
month_range.user_id = self.user_id
month_range.asset_code = self.asset_code
month_range.save

View File

@ -21,6 +21,7 @@ class AssignmentReminder < ActiveRecord::Base
belongs_to :user
has_a_broadcast_policy
before_save :infer_defaults
attr_accessible :assignment, :user, :reminder_type
def infer_defaults
self.reminder_type ||= 'due_at'

View File

@ -19,4 +19,5 @@
class AttachmentAssociation < ActiveRecord::Base
belongs_to :attachment
belongs_to :context, :polymorphic => true
attr_accessible :attachment, :context
end

View File

@ -18,4 +18,5 @@
class AuthorizationCode < ActiveRecord::Base
belongs_to :account
attr_accessible
end

View File

@ -21,4 +21,5 @@ class ClonedItem < ActiveRecord::Base
has_many :attachments
has_many :discussion_topics
has_many :wiki_pages
attr_accessible :original_item
end

View File

@ -49,7 +49,12 @@ class Collaboration < ActiveRecord::Base
end
def include_author_as_collaborator
Collaborator.find_or_create_by_user_id_and_collaboration_id(self.user_id, self.id)
c = Collaborator.find_by_user_id_and_collaboration_id(self.user_id, self.id)
unless c
c = Collaborator.new(:collaboration => self)
c.user_id = self.user_id
c.save
end
end
alias_method :destroy!, :destroy

View File

@ -24,6 +24,7 @@ class ContentExport < ActiveRecord::Base
has_many :attachments, :as => :context, :dependent => :destroy
has_a_broadcast_policy
serialize :settings
attr_accessible
workflow do
state :created

View File

@ -51,6 +51,7 @@ class ContentMigration < ActiveRecord::Base
'web_links' => false,
'wikis' => false
}
attr_accessible :context, :migration_settings, :user
workflow do
state :created

View File

@ -33,6 +33,8 @@ class ContentTag < ActiveRecord::Base
after_save :enforce_unique_in_modules
after_save :touch_context_module
after_save :touch_context_if_learning_outcome
attr_accessible :learning_outcome, :context, :tag_type, :mastery_score, :rubric_association, :content_asset_string, :content, :title, :indent, :position, :url
adheres_to_policy
@ -226,9 +228,11 @@ class ContentTag < ActiveRecord::Base
attempts = 0
begin
if association.is_a?(Quiz)
result = LearningOutcomeResult.find_or_create_by_learning_outcome_id_and_user_id_and_association_id_and_association_type_and_content_tag_id_and_associated_asset_type_and_associated_asset_id(self.learning_outcome_id, user.id, association.id, association_type, self.id, 'AssessmentQuestion', assessment_question.id)
result = LearningOutcomeResult.find_by_learning_outcome_id_and_user_id_and_association_id_and_association_type_and_content_tag_id_and_associated_asset_type_and_associated_asset_id(self.learning_outcome_id, user.id, association.id, association_type, self.id, 'AssessmentQuestion', assessment_question.id)
result ||= LearningOutcomeResult.create(:learning_outcome => self.learning_outcome, :user => user, :association => association, :content_tag => self, :associated_asset => assessment_question)
else
result = LearningOutcomeResult.find_or_create_by_learning_outcome_id_and_user_id_and_association_id_and_association_type_and_content_tag_id(self.learning_outcome_id, user.id, association.id, association_type, self.id)
result = LearningOutcomeResult.find_by_learning_outcome_id_and_user_id_and_association_id_and_association_type_and_content_tag_id(self.learning_outcome_id, user.id, association.id, association_type, self.id)
result ||= LearningOutcomeResult.create(:learning_outcome => self.learning_outcome, :user => user, :association => association, :content_tag => self)
end
rescue => e
attempts += 1

View File

@ -126,7 +126,11 @@ class ContextMessage < ActiveRecord::Base
def record_participants
sender = self.context_message_participants.find_by_user_id_and_participation_type(self.user_id, 'sender')
sender ||= self.context_message_participants.create(:user_id => self.user_id, :participation_type => 'sender')
unless sender
sender = self.context_message_participants.new(:participation_type => 'sender')
sender.user_id = self.user_id
sender.save
end
recipient_users = self.context.users.select{|u| (self.recipients || []).include?(u.id) }
return if recipient_users.empty?
participants_hash = {}

View File

@ -20,4 +20,5 @@ class ContextMessageParticipant < ActiveRecord::Base
belongs_to :user
belongs_to :context_message
after_save :touch_user
attr_accessible :user, :user_id, :participation_type
end

View File

@ -239,19 +239,16 @@ class ContextModule < ActiveRecord::Base
end
if params[:type] == 'external_url'
title = params[:title]
added_item ||= self.content_tags.build(
:context_id => self.context_id,
:context_type => self.context_type
)
added_item ||= self.content_tags.build(:context => self.context)
added_item.attributes = {
:content_id => 0,
:content_type => 'ExternalUrl',
:url => params[:url],
:url => params[:url],
:tag_type => 'context_module',
:title => title,
:indent => params[:indent],
:position => position
}
added_item.content_id = 0
added_item.content_type = 'ExternalUrl'
added_item.context_module_id = self.id
added_item.indent = params[:indent] || 0
added_item.workflow_state = 'active'
@ -259,14 +256,14 @@ class ContextModule < ActiveRecord::Base
added_item
elsif params[:type] == 'context_external_tool'
title = params[:title]
added_item ||= self.content_tags.build(
:context_id => self.context_id,
:context_type => self.context_type
)
added_item ||= self.content_tags.build(:context => self.context)
tool = ContextExternalTool.find_external_tool(params[:url], self.context)
unless tool
tool = ContextExternalTool.new
tool.id = 0
end
added_item.attributes = {
:content_id => tool ? tool.id : 0,
:content_type => 'ContextExternalTool',
:content => tool,
:url => params[:url],
:tag_type => 'context_module',
:title => title,
@ -280,18 +277,15 @@ class ContextModule < ActiveRecord::Base
added_item
elsif params[:type] == 'context_module_sub_header'
title = params[:title]
added_item ||= self.content_tags.build(
:context_id => self.context_id,
:context_type => self.context_type
)
added_item ||= self.content_tags.build(:context => self.context)
added_item.attributes = {
:content_id => 0,
:content_type => 'ContextModuleSubHeader',
:tag_type => 'context_module',
:tag_type => 'context_module',
:title => title,
:indent => params[:indent],
:position => position
}
added_item.content_id = 0
added_item.content_type = 'ContextModuleSubHeader'
added_item.context_module_id = self.id
added_item.indent = params[:indent] || 0
added_item.workflow_state = 'active'
@ -301,14 +295,10 @@ class ContextModule < ActiveRecord::Base
return nil unless item
added_item ||= ContentTag.find_by_content_id_and_content_type_and_context_id_and_context_type_and_tag_type(item.id, item.class.to_s, self.context_id, self.context_type, 'context_module')
title = params[:title] || (item.title rescue item.name)
added_item ||= self.content_tags.build(
:context_id => self.context_id,
:context_type => self.context_type
)
added_item ||= self.content_tags.build(:context => context)
added_item.attributes = {
:content_id => item.id,
:content_type => item.class.to_s,
:tag_type => 'context_module',
:content => item,
:tag_type => 'context_module',
:title => title,
:indent => params[:indent],
:position => position

View File

@ -21,4 +21,5 @@ class CourseAccountAssociation < ActiveRecord::Base
belongs_to :course_section
belongs_to :account
has_many :account_users, :foreign_key => 'account_id', :primary_key => 'account_id'
attr_accessible :account, :depth, :course_section
end

View File

@ -21,7 +21,7 @@ class DelayedMessage < ActiveRecord::Base
belongs_to :notification_policy
belongs_to :context, :polymorphic => true
belongs_to :communication_channel
attr_accessible :notification, :notification_policy, :frequency, :communication_channel, :linked_name, :name_of_topic,:link, :summary, :notification_id, :notification_policy_id, :context_id, :context_type, :communication_channel_id, :context, :workflow_state
validates_length_of :summary, :maximum => maximum_text_length, :allow_nil => true, :allow_blank => true
validates_presence_of :communication_channel_id

View File

@ -20,6 +20,7 @@ class DelayedNotification < ActiveRecord::Base
include Workflow
belongs_to :asset, :polymorphic => true
belongs_to :notification
attr_accessible :asset, :notification, :recipient_keys
serialize :recipient_keys

View File

@ -20,6 +20,7 @@ class DeveloperKey < ActiveRecord::Base
belongs_to :user
belongs_to :account
has_many :page_views
attr_accessible :api_key
before_create :generate_api_key

View File

@ -38,6 +38,8 @@ class Enrollment < ActiveRecord::Base
after_save :touch_user
before_save :update_user_account_associations_if_necessary
attr_accessible :user, :course, :workflow_state, :course_section, :limit_priveleges_to_course_section, :invitation_email
trigger.after(:insert).where("NEW.workflow_state = 'active'") do
<<-SQL
UPDATE assignments

View File

@ -21,4 +21,6 @@ class EnrollmentDatesOverride < ActiveRecord::Base
belongs_to :context, :polymorphic => true
belongs_to :enrollment_term
attr_accessible :enrollment_type, :enrollment_term, :start_at, :end_at
end

View File

@ -27,6 +27,8 @@ class ErrorReport < ActiveRecord::Base
define_callbacks :on_send_to_external
attr_accessible
def send_to_external
run_callbacks(:on_send_to_external)
end

View File

@ -26,7 +26,8 @@ class ExternalFeedEntry < ActiveRecord::Base
before_save :infer_defaults
validates_length_of :message, :maximum => maximum_text_length, :allow_nil => true, :allow_blank => true
sanitize_field :message, Instructure::SanitizeField::SANITIZE
attr_accessible :title, :message, :source_name, :source_url, :posted_at, :start_at, :end_at, :user, :url, :uuid, :author_name, :author_url, :author_email, :asset
def infer_defaults
self.uuid ||= Digest::MD5.hexdigest("#{title || rand.to_s}#{posted_at.strftime('%Y-%m-%d') rescue 'no-time'}")

View File

@ -19,4 +19,5 @@
class GradebookUpload < ActiveRecord::Base
belongs_to :context, :polymorphic => true
has_one :attachment
attr_accessible
end

View File

@ -179,9 +179,12 @@ class Group < ActiveRecord::Base
return nil if !user
res = nil
Group.transaction do
res = self.group_memberships.find_or_initialize_by_user_id(user.id)
res.workflow_state = 'invited' if res.new_record?
res.save
res = self.group_memberships.find_by_user_id(user.id)
unless res
res = self.group_memberships.build(:user => user)
res.workflow_state = 'invited'
res.save
end
end
res
end
@ -190,9 +193,12 @@ class Group < ActiveRecord::Base
return nil if !user
res = nil
Group.transaction do
res = self.group_memberships.find_or_initialize_by_user_id(user.id)
res.workflow_state = 'requested' if res.new_record?
res.save
res = self.group_memberships.find_by_user_id(user.id)
unless res
res = self.group_memberships.build(:user => user)
res.workflow_state = 'requested'
res.save
end
end
res
end

View File

@ -22,6 +22,8 @@ class GroupMembership < ActiveRecord::Base
belongs_to :group
belongs_to :user
attr_accessible :group, :user
before_save :ensure_mutually_exclusive_membership
before_save :assign_uuid

View File

@ -19,7 +19,9 @@
class Hashtag < ActiveRecord::Base
has_many :short_message_associations, :as => :context
has_many :short_messages, :through => :short_message_associations
attr_accessible :hashtag
before_save :infer_defaults
def infer_defaults

View File

@ -25,6 +25,8 @@ class InboxItem < ActiveRecord::Base
before_save :infer_context_code
after_save :update_user_inbox_items_count
after_destroy :update_user_inbox_items_count
attr_accessible :user_id, :asset, :subject, :body_teaser, :sender_id
workflow do
state :unread

View File

@ -42,7 +42,8 @@ class LearningOutcome < ActiveRecord::Base
end
def align(asset, context, opts={})
tag = self.content_tags.find_or_create_by_content_id_and_content_type_and_tag_type_and_context_id_and_context_type(asset.id, asset.class.to_s, 'learning_outcome', context.id, context.class.to_s)
tag = self.content_tags.find_by_content_id_and_content_type_and_tag_type_and_context_id_and_context_type(asset.id, asset.class.to_s, 'learning_outcome', context.id, context.class.to_s)
tag ||= self.content_tags.create(:content => asset, :tag_type => 'learning_outcome', :context => context)
mastery_type = opts[:mastery_type]
if mastery_type == 'points'
mastery_type = 'points_mastery'

View File

@ -26,6 +26,8 @@ class LearningOutcomeResult < ActiveRecord::Base
belongs_to :context, :polymorphic => true
simply_versioned
before_save :infer_defaults
attr_accessible :learning_outcome, :user, :association, :content_tag, :associated_asset
def infer_defaults
self.context_code = "#{self.context_type.underscore}_#{self.context_id}" rescue nil

View File

@ -18,6 +18,8 @@
class Mailbox < ActiveRecord::Base
belongs_to :mailboxable_entity, :polymorphic => true
attr_accessible :name, :purpose, :content_parser, :mailboxable_entity_type, :mailboxable_entity_id
before_create :generate_handle

View File

@ -27,7 +27,9 @@ class MediaObject < ActiveRecord::Base
after_create :retrieve_details_later
after_save :update_title_on_kaltura_later
serialize :data
attr_accessible :media_id, :title
attr_accessor :podcast_associated_asset
def infer_defaults

View File

@ -27,6 +27,8 @@ class Message < ActiveRecord::Base
belongs_to :user
belongs_to :asset_context, :polymorphic => true
attr_accessible :to, :from, :subject, :body, :delay_for, :context, :path_type, :from_name, :sent_at, :notification, :user, :communication_channel, :notification_name
after_save :stage_message
before_save :move_messages_for_deleted_users
before_save :infer_defaults

View File

@ -54,6 +54,8 @@ class Notification < ActiveRecord::Base
has_many :notification_policies, :dependent => :destroy
has_many :users, :through => :notification_policies
before_save :infer_default_content
attr_accessible :name, :subject, :body, :sms_body, :main_link, :delay_for, :category
named_scope :to_show_in_feed, :conditions => ["messages.category = ? OR messages.notification_name IN (?) ", "TestImmediately", TYPES_TO_SHOW_IN_FEED]
@ -116,9 +118,9 @@ class Notification < ActiveRecord::Base
message.parse!('summary')
delayed_message = DelayedMessage.new(
:notification => self,
:notification_policy_id => policy.id,
:notification_policy => policy,
:frequency => policy.frequency,
:communication_channel_id => policy.communication_channel_id,
:communication_channel_id => policy.communication_channel_id,
:linked_name => 'work on this link!!!',
:name_of_topic => message.subject,
:link => message.url,

View File

@ -23,6 +23,8 @@ class NotificationPolicy < ActiveRecord::Base
belongs_to :communication_channel
before_save :infer_frequency
attr_accessible :notification, :user, :communication_channel, :frequency, :notification_id, :user_id, :communication_channel_id
# This is for choosing a policy for another context, so:
# user.notification_policies.for(notification) or

View File

@ -18,6 +18,8 @@
class OauthRequest < ActiveRecord::Base
belongs_to :user
attr_accessible :service, :token, :secret, :user_secret, :return_url, :user, :original_host_with_port
def self.serialization_excludes; [:secret, :user_secret]; end
end

View File

@ -20,6 +20,7 @@ class PageComment < ActiveRecord::Base
belongs_to :page, :polymorphic => true
belongs_to :user
validates_length_of :message, :maximum => maximum_text_length, :allow_nil => true, :allow_blank => true
attr_accessible :message
named_scope :for_user, lambda{|user|
{:conditions => ['page_comments.user_id = ?', user.id]}

View File

@ -35,6 +35,8 @@ class PageView < ActiveRecord::Base
attr_accessor :generated_by_hand
attr_accessor :is_update
attr_accessible :url, :user, :controller, :action, :session_id, :developer_key, :user_agent
def ensure_account
self.account_id ||= (self.context_type == 'Account' ? self.context_id : self.context.account_id) rescue nil
@ -90,11 +92,13 @@ class PageView < ActiveRecord::Base
self.save
hour_start = ActiveSupport::TimeWithZone.new(Time.utc(self.created_at.year, self.created_at.month, self.created_at.day, self.created_at.hour), Time.zone).utc
hour_end = hour_start + (60*60)
range = PageViewRange.find_or_create_by_context_id_and_context_type_and_start_at_and_end_at(self.context_id, self.context_type, hour_start, hour_end)
range = PageViewRange.find_by_context_id_and_context_type_and_start_at_and_end_at(self.context_id, self.context_type, hour_start, hour_end)
range ||= PageViewRange.create(:context => self.context, :start_at => hour_start, :end_at => hour_end)
range.re_summarize
day_start = Time.utc(self.created_at.year, self.created_at.month, self.created_at.day)
day_end = day_start + 1.day
range = PageViewRange.find_or_create_by_context_id_and_context_type_and_start_at_and_end_at(self.context_id, self.context_type, day_start, day_end)
range = PageViewRange.find_by_context_id_and_context_type_and_start_at_and_end_at(self.context_id, self.context_type, day_start, day_end)
range ||= PageViewRange.create(:context => self.context, :start_at => day_start, :end_at => day_end)
range.re_summarize
end

View File

@ -20,6 +20,8 @@ class PageViewRange < ActiveRecord::Base
include Workflow
belongs_to :context, :polymorphic => true
serialize :data
attr_accessible :context, :start_at, :end_at
workflow do
state :needs_re_summarization
@ -57,7 +59,8 @@ class PageViewRange < ActiveRecord::Base
account = context.parent_account if context.respond_to?(:parent_account)
account = context.account if context.respond_to?(:account)
if account
range = PageViewRange.find_or_create_by_context_id_and_context_type_and_start_at_and_end_at(account.id, account.class.to_s, start_at.utc, end_at.utc)
range = PageViewRange.find_by_context_id_and_context_type_and_start_at_and_end_at(account.id, account.class.to_s, start_at.utc, end_at.utc)
range ||= PageViewRange.create(:context => account, :start_at => start_at.utc, :end_at => end_at.utc)
range.mark_for_review
end
self
@ -70,7 +73,8 @@ class PageViewRange < ActiveRecord::Base
account = context.parent_account if context.respond_to?(:parent_account)
account = context.account if context.respond_to?(:account)
if account
range = PageViewRange.find_or_create_by_context_id_and_context_type_and_start_at_and_end_at(account.id, account.class.to_s, start_at.utc, end_at.utc)
range = PageViewRange.find_by_context_id_and_context_type_and_start_at_and_end_at(account.id, account.class.to_s, start_at.utc, end_at.utc)
range ||= PageViewRange.create(:context => account, :start_at => start_at.utc, :end_at => end_at.utc)
range.mark_for_review
end
end
@ -97,7 +101,8 @@ class PageViewRange < ActiveRecord::Base
@hash_data[:user_agents] ||= {}
@hash_data[:user_agents][view.user_agent] ||= 0
@hash_data[:user_agents][view.user_agent] += 1
view.update_attributes(:summarized => true)
view.summarized = true
view.save
end
named_scope :for_review, lambda{

View File

@ -31,6 +31,7 @@ class PluginSetting < ActiveRecord::Base
before_save :validate_posted_settings
serialize :settings
attr_accessor :posted_settings
attr_accessible :name, :settings
attr_writer :plugin
before_save :encrypt_settings

View File

@ -393,16 +393,17 @@ class Quiz < ActiveRecord::Base
s = nil
state ||= 'untaken'
attempts = 0
user_id = user.is_a?(User) ? user.id : user
begin
if temporary || !user.is_a?(User)
user_code = "#{user.to_s}"
user_code = "user_#{user.id}" if user.is_a?(User)
s = QuizSubmission.find_or_initialize_by_quiz_id_and_temporary_user_code(self.id, user_code)
s = QuizSubmission.find_by_quiz_id_and_temporary_user_code(self.id, user_code)
s ||= QuizSubmission.new(:quiz => self, :temporary_user_code => user_code)
s.workflow_state ||= state
s.save
else
s = QuizSubmission.find_or_initialize_by_quiz_id_and_user_id(self.id, user_id)
s = QuizSubmission.find_by_quiz_id_and_user_id(self.id, user.id)
s ||= QuizSubmission.new(:quiz => self, :user => user)
s.workflow_state ||= state
s.save
end

View File

@ -18,7 +18,7 @@
class QuizSubmission < ActiveRecord::Base
include Workflow
attr_accessible :submission_data
attr_accessible :quiz, :user, :temporary_user_code, :submission_data
attr_readonly :quiz_id, :user_id
validates_presence_of :quiz_id
@ -187,7 +187,7 @@ class QuizSubmission < ActiveRecord::Base
end
def snapshot!(params)
QuizSubmissionSnapshot.create(:quiz_submission_id => self.id, :attempt => self.attempt, :data => params)
QuizSubmissionSnapshot.create(:quiz_submission => self, :attempt => self.attempt, :data => params)
end
def questions_as_object

View File

@ -19,4 +19,6 @@
class QuizSubmissionSnapshot < ActiveRecord::Base
belongs_to :quiz_submission
serialize :data
attr_accessible :quiz_submission, :attempt, :data
end

View File

@ -20,6 +20,8 @@ class ReportSnapshot < ActiveRecord::Base
STATS_COLLECTION_URL = "https://stats.instructure.com/stats_collection"
REPORT_TO_SEND = "counts_progressive_overview"
attr_accessible :report_type
after_create :push_to_instructure_if_collection_enabled
def self.report_value_over_time(report, key)

View File

@ -21,6 +21,8 @@ class RoleOverride < ActiveRecord::Base
has_many :children, :class_name => "Role", :foreign_key => "parent_id"
belongs_to :parent, :class_name => "Role"
before_save :default_values
attr_accessible :context, :permission, :enrollment_type, :enabled
def default_values
self.context_code = "#{self.context_type.underscore}_#{self.context_id}" rescue nil

View File

@ -120,7 +120,9 @@ class Rubric < ActiveRecord::Base
missing_ids = ids.select{|id| !tag_outcome_ids.include?(id) }
tags_to_delete = tags.select{|t| !ids.include?(t.learning_outcome_id) }
missing_ids.each do |id|
self.learning_outcome_tags.create!(:learning_outcome_id => id, :context => self.context, :tag_type => 'learning_outcome')
lot = self.learning_outcome_tags.build(:context => self.context, :tag_type => 'learning_outcome')
lot.learning_outcome_id = id
lot.save!
end
tags_to_delete.each{|t| t.destroy }
true

View File

@ -111,7 +111,9 @@ class RubricAssociation < ActiveRecord::Base
tags_to_update = tags.select{|t| rubric_outcome_ids.include?(t.learning_outcome_id) }
ContentTag.update_all({:rubric_association_id => self.id}, {:id => tags_to_update.map(&:id)})
ids_to_add.each do |id|
assignment.learning_outcome_tags.create(:context => assignment.context, :learning_outcome_id => id, :rubric_association_id => self.id, :tag_type => 'learning_outcome')
lot = assignment.learning_outcome_tags.build(:context => assignment.context, :rubric_association => self, :tag_type => 'learning_outcome')
lot.learning_outcome_id = id
lot.save
end
end
end
@ -158,7 +160,8 @@ class RubricAssociation < ActiveRecord::Base
def invite_assessor(assessee, assessor, asset, invite=false)
# Invitations should be unique per asset, user and assessor
assessment_request = self.assessment_requests.find_or_initialize_by_user_id_and_assessor_id(assessee.id, assessor.id)
assessment_request = self.assessment_requests.find_by_user_id_and_assessor_id(assessee.id, assessor.id)
assessment_request ||= self.assessment_requests.build(:user => assessee, :assessor => assessor)
assessment_request.workflow_state = "assigned" if assessment_request.new_record?
assessment_request.asset = asset
invite ? assessment_request.send_invitation! : assessment_request.save!
@ -166,7 +169,8 @@ class RubricAssociation < ActiveRecord::Base
end
def remind_user(assessee)
assessment_request = self.assessment_requests.find_or_initialize_by_user_id(assessee.id)
assessment_request = self.assessment_requests.find_by_user_id(assessee.id)
assessment_request ||= self.assessment_requests.build(:user => assessee)
assessment_request.send_reminder! if assessment_request.assigned?
assessment_request
end

View File

@ -20,6 +20,8 @@ class ScribdAccount < ActiveRecord::Base
belongs_to :scribdable, :polymorphic => true
has_many :attachments
attr_accessible :scribdable, :scribdable_id, :scribdable_type, :uuid
before_create :assure_uuid
def assure_uuid

View File

@ -18,4 +18,6 @@
class ScribdMimeType < ActiveRecord::Base
has_many :attachments
attr_accessible :extension, :name
end

View File

@ -17,6 +17,7 @@
#
class Setting < ActiveRecord::Base
attr_accessible :name, :value
@@cache = {}

View File

@ -27,6 +27,7 @@ class SisBatch < ActiveRecord::Base
belongs_to :batch_mode_term, :class_name => 'EnrollmentTerm'
attr_accessor :zip_path
attr_accessible
def self.max_attempts
5

View File

@ -19,6 +19,8 @@
class SisBatchLogEntry < ActiveRecord::Base
validates_length_of :text, :maximum => maximum_text_length, :allow_nil => true, :allow_blank => true
belongs_to :sis_batch
attr_accessible :text, :sis_batch
def text=(val)
if !val || val.length < self.class.maximum_text_length

View File

@ -20,4 +20,5 @@ class SisCrossListedSection < ActiveRecord::Base
named_scope :account_sections, lambda{|account, *source_ids|
{:conditions => {:root_account_id => account.id, :sis_source_id => source_ids}, :order => :sis_source_id }
}
attr_accessible
end

View File

@ -24,6 +24,8 @@ class StreamItem < ActiveRecord::Base
has_many :stream_item_instances, :dependent => :delete_all
has_many :users, :through => :stream_item_instances
attr_accessible
def stream_data(viewing_user_id)
res = data.is_a?(OpenObject) ? data : OpenObject.new

View File

@ -20,6 +20,8 @@ class StreamItemInstance < ActiveRecord::Base
belongs_to :user
belongs_to :stream_item
attr_accessible :user_id
before_save :set_context_code
def set_context_code
self.context_code = stream_item && stream_item.context_code

View File

@ -304,7 +304,8 @@ class Submission < ActiveRecord::Base
if((a.context_type == 'User' && a.context_id == user_id) ||
(a.context_type == 'Group' && a.context_id == group_id) ||
(a.context_type == 'Assignment' && a.context_id == assignment_id && a.available?))
self.attachment_associations.find_or_create_by_attachment_id(a.id)
aa = self.attachment_associations.find_by_attachment_id(a.id)
aa ||= self.attachment_associations.create(:attachment => a)
end
end
end
@ -722,6 +723,7 @@ class Submission < ActiveRecord::Base
user = obj.user rescue nil
association = self.assignment.rubric_association
res = self.assessment_requests.find_or_initialize_by_assessor_asset_id_and_assessor_asset_type_and_assessor_id_and_rubric_association_id(obj.id, obj.class.to_s, user.id, (association ? association.id : nil))
res || self.assessment_requests.build(:assessor_asset => obj, :assessor => user, :rubric_association => association)
res.user_id = self.user_id
res.workflow_state = 'assigned' if res.new_record?
just_created = res.new_record?

View File

@ -33,6 +33,8 @@ class SubmissionComment < ActiveRecord::Base
validates_length_of :comment, :maximum => maximum_text_length, :allow_nil => true, :allow_blank => true
validates_length_of :comment, :minimum => 1, :allow_nil => true, :allow_blank => true
attr_accessible :comment, :submission, :submission_id, :recipient_id, :author, :context_id, :context_type, :media_comment_id, :media_comment_type, :group_comment_id, :assessment_request, :attachments, :anonymous
before_save :infer_details
after_save :update_submission
@ -140,7 +142,7 @@ class SubmissionComment < ActiveRecord::Base
:comment => message,
:submission_id => self.submission_id,
:recipient_id => self.recipient_id,
:author_id => user.id,
:author => user,
:context_id => self.context_id,
:context_type => self.context_type
})

View File

@ -19,4 +19,6 @@
class SubmissionCommentParticipant < ActiveRecord::Base
belongs_to :user
belongs_to :submission_comment
attr_accessible :user_id, :participation_type
end

View File

@ -20,6 +20,8 @@
# concept pulled from the comments of this page:
# http://stackoverflow.com/questions/937429/activerecordbase-without-table-rails
class Tableless < ActiveRecord::Base
attr_accessible
def self.columns
@columns ||= [];
end

View File

@ -19,6 +19,8 @@
class Thumbnail < ActiveRecord::Base
belongs_to :attachment, :foreign_key => "parent_id"
attr_protected
# the ":keep_profile => true" part is in here so that we tell mini_magic to not try to pass the command line option -strip.
# this is because on the servers we are actually using graphics_magic not image_magic's mogrify and graphics_magick doesn't
# support -strip. you'd get something like:

View File

@ -19,4 +19,6 @@
class UserAccountAssociation < ActiveRecord::Base
belongs_to :user
belongs_to :account
attr_accessible :account_id, :depth
end

View File

@ -21,6 +21,7 @@ class UserService < ActiveRecord::Base
belongs_to :user
attr_accessor :password
attr_accessible :user, :service, :protocol, :token, :secret, :service_user_url, :service_user_id, :service_user_name, :service_domain
before_save :infer_defaults
after_save :assert_relations

View File

@ -144,7 +144,8 @@ class WebConference < ActiveRecord::Base
def add_user(user, type)
return unless user
p = self.web_conference_participants.find_or_initialize_by_web_conference_id_and_user_id(self.id, user.id)
p = self.web_conference_participants.find_by_web_conference_id_and_user_id(self.id, user.id)
p ||= self.web_conference_participants.build(:web_conference => self, :user => user)
p.participation_type = type unless type == 'attendee' && p.participation_type == 'initiator'
(@new_participants ||= []) << user if p.new_record?
# Once anyone starts attending the conference, mark it as started.

View File

@ -19,4 +19,6 @@
class WebConferenceParticipant < ActiveRecord::Base
belongs_to :web_conference
belongs_to :user
attr_accessible :web_conference, :user
end

View File

@ -23,6 +23,8 @@ class WikiPageComment < ActiveRecord::Base
belongs_to :context, :polymorphic => true
adheres_to_policy
after_create :update_wiki_page_comments_count
attr_accessible :comments, :user_name
def update_wiki_page_comments_count
WikiPage.update_all({:wiki_page_comments_count => self.wiki_page.wiki_page_comments.count}, {:id => self.wiki_page_id})

View File

@ -42,7 +42,8 @@ class ExternalFeedAggregator
require 'rss/2.0'
rss = RSS::Parser.parse(body, false)
raise "Invalid rss feed" unless rss
feed.update_attributes(:title => rss.channel.title)
feed.title = rss.channel.title
feed.save
@logger.info("#{rss.items.length} rss items found")
entries = feed.add_rss_entries(rss)
@logger.info("#{entries.length} new entries added")
@ -51,7 +52,8 @@ class ExternalFeedAggregator
begin
require 'atom'
atom = Atom::Feed.load_feed(body)
feed.update_attributes(:title => atom.title)
feed.title = atom.title
feed.save
@logger.info("#{atom.entries.length} atom entries found")
entries = feed.add_atom_entries(atom)
@logger.info("#{entries.length} new entries added")

View File

@ -49,7 +49,8 @@ module Facebook
end
def self.authorize_success(user, token)
@service = UserService.find_or_initialize_by_user_id_and_service(user.id, 'facebook')
@service = UserService.find_by_user_id_and_service(user.id, 'facebook')
@service ||= UserService.new(:user => user, :service => 'facebook')
@service.token = token
data = send_graph_request('/me', :get, @service)
return nil unless data

View File

@ -32,7 +32,8 @@ class TwitterSearcher
def process
count = 0
while hashtag = Hashtag.to_be_polled.first and (count += 1) < MAX_TAGS_PER_PROCESS
hashtag.update_attributes(:refresh_at => Time.now.utc + REFRESH_INTERVAL)
hashtag.refresh_at = Time.now.utc + REFRESH_INTERVAL
hashtag.save
require 'net/http'
@logger.info("hashtag found: #{hashtag} -- requesting public twitter search")
@ -54,7 +55,8 @@ class TwitterSearcher
hashtag.add_short_message(nil, result, true)
end
hashtag.last_result_id = since_id if since_id
hashtag.update_attributes(:refresh_at => Time.now.utc + (results.empty? ? REFRESH_INTERVAL_EMPTY : REFRESH_INTERVAL) )
hashtag.refresh_at = Time.now.utc + (results.empty? ? REFRESH_INTERVAL_EMPTY : REFRESH_INTERVAL)
hashtag.save
@logger.info('results successfully added')
rescue => e
ErrorReport.log_exception(:processing, e, {
@ -70,7 +72,8 @@ class TwitterSearcher
# TODO: This assumes that Retry-After will always be sent as delta-seconds. We should probably support HTTP-date too:
# http://webee.technion.ac.il/labs/comnet/netcourse/CIE/RFC/2068/201.htm
wait_time = response['Retry-After'].to_i if response['Retry-After']
hashtag.update_attributes(:refresh_at => Time.now.utc + wait_time)
hashtag.refresh_at = Time.now.utc + wait_time
hashtag.save
end
end

View File

@ -40,7 +40,8 @@ class TwitterUserPoller
count = 0
while service = UserService.to_be_polled.for_service('twitter').first and (count += 1) < MAX_PER_PROCESS
service.update_attributes(:updated_at => Time.now.utc)
service.updated_at => Time.now.utc
service.save
@logger.info("user found: #{service.service_user_name} retrieving tweets...")
since_id = nil
@ -61,7 +62,8 @@ class TwitterUserPoller
@logger.info("unexpected error: #{e.to_s} #{e.backtrace.join "\n"}")
end
retry_after = [REFRESH_INTERVAL_EMPTY, retry_after].max
service.update_attributes(:refresh_at => Time.now.utc + retry_after + 1.minute)
service.refresh_at Time.now.utc + retry_after + 1.minute
service.save
end
if tweets
@ -79,7 +81,8 @@ class TwitterUserPoller
since_id ||= tweet['id'] if tweet['id']
end
service.last_result_id = since_id if since_id
service.update_attributes(:refresh_at => Time.now.utc + (since_id ? REFRESH_INTERVAL : REFRESH_INTERVAL_EMPTY))
service.refresh_at = Time.now.utc + (since_id ? REFRESH_INTERVAL : REFRESH_INTERVAL_EMPTY)
service.save
end
end

View File

@ -17,7 +17,7 @@
#
def bookmark_service_model(opts={})
@bookmark_service = BookmarkService.create!(valid_bookmark_service_attributes.merge(opts))
@bookmark_service = factory_with_protected_attributes(BookmarkService, valid_bookmark_service_attributes.merge(opts))
end
def valid_bookmark_service_attributes

View File

@ -17,7 +17,7 @@
#
def message_model(opts={})
@message = Message.create!(message_valid_attributes.merge(opts))
@message = factory_with_protected_attributes(Message, message_valid_attributes.merge(opts))
end
def message_valid_attributes

View File

@ -17,7 +17,8 @@
#
def notification_policy_model(opts={})
@notification_policy = NotificationPolicy.create!(notification_policy_valid_attributes.merge(opts))
@notification_policy = factory_with_protected_attributes(NotificationPolicy,
notification_policy_valid_attributes.merge(opts))
end
def notification_policy_valid_attributes

View File

@ -17,7 +17,7 @@
#
def user_service_model(opts={})
@user_service = UserService.create!(valid_user_service_attributes.merge(opts))
@user_service = factory_with_protected_attributes(UserService, valid_user_service_attributes.merge(opts))
end
def valid_user_service_attributes

View File

@ -82,7 +82,7 @@ describe EnrollmentDateRestrictions do
@term = @course.enrollment_term
@term.should_not be_nil
@term.save!
@override = @term.enrollment_dates_overrides.create!(:enrollment_type => 'StudentEnrollment', :enrollment_term_id => @term.id, :start_at => start_at, :end_at => end_at)
@override = @term.enrollment_dates_overrides.create!(:enrollment_type => 'StudentEnrollment', :enrollment_term => @term, :start_at => start_at, :end_at => end_at)
@course = Course.find(@course.id)
@course.enrollment_dates_for(@enrollment).map(&:to_i).should eql([start_at, end_at].map(&:to_i))
@ -187,7 +187,7 @@ describe EnrollmentDateRestrictions do
@term = @course.enrollment_term
@term.should_not be_nil
@term.save!
@override = @term.enrollment_dates_overrides.create!(:enrollment_type => 'StudentEnrollment', :enrollment_term_id => @term.id, :start_at => start_at, :end_at => end_at)
@override = @term.enrollment_dates_overrides.create!(:enrollment_type => 'StudentEnrollment', :enrollment_term => @term, :start_at => start_at, :end_at => end_at)
@enrollment.workflow_state = 'inactive'
@enrollment.save!
@enrollment.state.should eql(:inactive)
@ -299,7 +299,7 @@ describe EnrollmentDateRestrictions do
@term = @course.enrollment_term
@term.should_not be_nil
@term.save!
@override = @term.enrollment_dates_overrides.create!(:enrollment_type => 'StudentEnrollment', :enrollment_term_id => @term.id, :start_at => start_at, :end_at => end_at)
@override = @term.enrollment_dates_overrides.create!(:enrollment_type => 'StudentEnrollment', :enrollment_term => @term, :start_at => start_at, :end_at => end_at)
@enrollment.workflow_state = 'active'
@enrollment.save!
@enrollment.state.should eql(:active)

View File

@ -370,7 +370,7 @@ describe Enrollment do
@term = @course.enrollment_term
@term.should_not be_nil
@term.save!
@override = @term.enrollment_dates_overrides.create!(:enrollment_type => 'StudentEnrollment', :enrollment_term_id => @term.id)
@override = @term.enrollment_dates_overrides.create!(:enrollment_type => 'StudentEnrollment', :enrollment_term => @term)
@override.start_at = 2.days.ago
@override.end_at = 2.days.from_now
@override.save!

View File

@ -18,6 +18,20 @@
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
class ProtectAttributes
def matches?(target)
@target = target
!(@target.accessible_attributes.nil? && @target.protected_attributes.nil?)
end
def failure_message_for_should
"expected #{@target} to protect attributes"
end
end
def protect_attributes
ProtectAttributes.new
end
describe 'Models' do
context "config/initializers/active_record.rb" do
@ -29,4 +43,19 @@ describe 'Models' do
TeacherEnrollment.base_ar_class.should == Enrollment
end
end
it "should use attr_accessible or attr_protected" do
ignore_classes = [
ActiveRecord::Base,
ActiveRecord::SessionStore::Session,
Delayed::Backend::ActiveRecord::Job,
Version
]
(ignore_classes << AddThumbnailUuid::Thumbnail) rescue nil
(ignore_classes << CustomField) rescue nil
(ignore_classes << CustomFieldValue) rescue nil
ActiveRecord::Base.send(:subclasses).each do |subclass|
subclass.should protect_attributes unless ignore_classes.include?(subclass)
end
end
end

View File

@ -21,7 +21,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
describe GroupMembership do
it "should ensure a mutually exclusive relationship" do
@gm = GroupMembership.new(valid_group_membership_attributes)
@gm = factory_with_protected_attributes(GroupMembership, valid_group_membership_attributes, false)
@gm.should_receive(:ensure_mutually_exclusive_membership)
@gm.save!
end
@ -29,7 +29,7 @@ describe GroupMembership do
end
def group_membership_model(opts={})
@group_membership = GroupMembership.create!(valid_group_membership_attributes.merge(opts))
@group_membership = factory_with_protected_attributes(GroupMembership, valid_group_membership_attributes.merge(opts))
end
def valid_group_membership_attributes