RuboCop: Layout config
Change-Id: I33da473d52ba626e821d03f3c29d1c5ffddde4cd Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/274067 Reviewed-by: Simon Williams <simon@instructure.com> Tested-by: Cody Cutrer <cody@instructure.com> QA-Review: Cody Cutrer <cody@instructure.com> Product-Review: Cody Cutrer <cody@instructure.com>
This commit is contained in:
parent
cf0045a411
commit
4896de008e
|
@ -16,7 +16,7 @@ AllCops:
|
|||
# values are an array of directories to opt in for (nil being all directories)
|
||||
OPT_IN = {
|
||||
nil => %w[Gemfile.d].freeze,
|
||||
'Layout' => %w[gems].freeze
|
||||
'Layout' => %w[config gems].freeze
|
||||
}.freeze
|
||||
|
||||
# this code generates a configuration that disables all cops for all files
|
||||
|
|
|
@ -48,7 +48,6 @@ end
|
|||
|
||||
module CanvasRails
|
||||
class Application < Rails::Application
|
||||
|
||||
# this CANVAS_ZEITWERK constant flag is defined above in this file.
|
||||
# It should be temporary,
|
||||
# and removed once we've fully upgraded to zeitwerk autoloading,
|
||||
|
@ -60,7 +59,7 @@ module CanvasRails
|
|||
# For now, this lets us figure out why constant loading
|
||||
# is not behaving as expected quickly and easily:
|
||||
Rails.autoloaders.logger = Logger.new("#{Rails.root}/log/autoloading.log")
|
||||
#Rails.autoloaders.log!
|
||||
# Rails.autoloaders.log!
|
||||
|
||||
# TODO: someday we can use this line, which will NOT
|
||||
# add anything on the autoload paths the actual ruby
|
||||
|
@ -110,30 +109,30 @@ module CanvasRails
|
|||
opts[:skip_thread_context] = true if log_config['log_context'] == false
|
||||
|
||||
case log_config["logger"]
|
||||
when "syslog"
|
||||
require 'syslog_wrapper'
|
||||
log_config["app_ident"] ||= "canvas-lms"
|
||||
log_config["daemon_ident"] ||= "canvas-lms-daemon"
|
||||
facilities = 0
|
||||
(log_config["facilities"] || []).each do |facility|
|
||||
facilities |= Syslog.const_get "LOG_#{facility.to_s.upcase}"
|
||||
end
|
||||
ident = ENV['RUNNING_AS_DAEMON'] == 'true' ? log_config["daemon_ident"] : log_config["app_ident"]
|
||||
opts[:include_pid] = true if log_config["include_pid"] == true
|
||||
config.logger = SyslogWrapper.new(ident, facilities, opts)
|
||||
config.logger.level = log_level
|
||||
else
|
||||
log_path = config.paths['log'].first
|
||||
when "syslog"
|
||||
require 'syslog_wrapper'
|
||||
log_config["app_ident"] ||= "canvas-lms"
|
||||
log_config["daemon_ident"] ||= "canvas-lms-daemon"
|
||||
facilities = 0
|
||||
(log_config["facilities"] || []).each do |facility|
|
||||
facilities |= Syslog.const_get "LOG_#{facility.to_s.upcase}"
|
||||
end
|
||||
ident = ENV['RUNNING_AS_DAEMON'] == 'true' ? log_config["daemon_ident"] : log_config["app_ident"]
|
||||
opts[:include_pid] = true if log_config["include_pid"] == true
|
||||
config.logger = SyslogWrapper.new(ident, facilities, opts)
|
||||
config.logger.level = log_level
|
||||
else
|
||||
log_path = config.paths['log'].first
|
||||
|
||||
if ENV['RUNNING_AS_DAEMON'] == 'true'
|
||||
log_path = Rails.root+'log/delayed_job.log'
|
||||
end
|
||||
if ENV['RUNNING_AS_DAEMON'] == 'true'
|
||||
log_path = Rails.root + 'log/delayed_job.log'
|
||||
end
|
||||
|
||||
config.logger = CanvasLogger.new(log_path, log_level, opts)
|
||||
config.logger = CanvasLogger.new(log_path, log_level, opts)
|
||||
end
|
||||
|
||||
# Activate observers that should always be running
|
||||
config.active_record.observers = [:cacher, :stream_item_cache, :live_events_observer ]
|
||||
config.active_record.observers = [:cacher, :stream_item_cache, :live_events_observer]
|
||||
config.active_record.allow_unsafe_raw_sql = :disabled
|
||||
|
||||
config.active_support.encode_big_decimal_as_string = false
|
||||
|
@ -148,10 +147,10 @@ module CanvasRails
|
|||
#{Rails.root}/ui)
|
||||
|
||||
config.middleware.use Rack::Chunked
|
||||
config.middleware.use Rack::Deflater, if: -> (*) {
|
||||
config.middleware.use Rack::Deflater, if: ->(*) {
|
||||
::Canvas::DynamicSettings.find(tree: :private)["enable_rack_deflation", failsafe: true]
|
||||
}
|
||||
config.middleware.use Rack::Brotli, if: -> (*) {
|
||||
config.middleware.use Rack::Brotli, if: ->(*) {
|
||||
::Canvas::DynamicSettings.find(tree: :private)["enable_rack_brotli", failsafe: true]
|
||||
}
|
||||
|
||||
|
@ -229,8 +228,8 @@ module CanvasRails
|
|||
end
|
||||
|
||||
Autoextend.hook(:"ActiveRecord::Base",
|
||||
PostgreSQLEarlyExtensions::ConnectionHandling,
|
||||
singleton: true)
|
||||
PostgreSQLEarlyExtensions::ConnectionHandling,
|
||||
singleton: true)
|
||||
Autoextend.hook(:"ActiveRecord::ConnectionAdapters::PostgreSQLAdapter",
|
||||
PostgreSQLEarlyExtensions,
|
||||
method: :prepend)
|
||||
|
@ -247,6 +246,7 @@ module CanvasRails
|
|||
# Easiest way to avoid the warning for now is to patch thor
|
||||
def validate_default_type!
|
||||
return if switch_name == "--serializer"
|
||||
|
||||
super
|
||||
end
|
||||
end
|
||||
|
|
|
@ -59,4 +59,4 @@ unless defined?(CANVAS_RAILS6_0)
|
|||
CANVAS_RAILS6_0 = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -29,7 +29,7 @@ environment_configuration(defined?(config) && config) do |config|
|
|||
config.action_controller.perform_caching = true
|
||||
|
||||
# run rake js:build to build the optimized JS if set to true
|
||||
ENV['USE_OPTIMIZED_JS'] = "true"
|
||||
ENV['USE_OPTIMIZED_JS'] = "true"
|
||||
|
||||
# Specifies the header that your web server uses for directly sending files
|
||||
# If you have mod_xsendfile enabled in apache:
|
||||
|
|
|
@ -41,7 +41,7 @@ environment_configuration(defined?(config) && config) do |config|
|
|||
# ActionMailer::Base.deliveries array.
|
||||
config.action_mailer.delivery_method = :test
|
||||
|
||||
#hairtrigger parallelized runtime race conditions
|
||||
# hairtrigger parallelized runtime race conditions
|
||||
config.active_record.schema_format = :sql
|
||||
|
||||
config.cache_store = :null_store
|
||||
|
|
|
@ -56,7 +56,6 @@ end
|
|||
|
||||
ActionController::Base.include(DataStreamingContentLength)
|
||||
|
||||
|
||||
module FileAccessUserOnSession
|
||||
def self.included(klass)
|
||||
klass.attr_writer :file_access_user
|
||||
|
|
|
@ -81,6 +81,7 @@ module ActiveModel
|
|||
|
||||
def value
|
||||
return if attribute == :base
|
||||
|
||||
base.send :read_attribute, attribute
|
||||
end
|
||||
|
||||
|
@ -91,8 +92,8 @@ module ActiveModel
|
|||
def i18n_keys
|
||||
self_and_descendants = ([base.class] + base.class.descendants)
|
||||
keys = self_and_descendants.map do |klass|
|
||||
[ :"models.#{klass.name.underscore}.attributes.#{attribute}.#{type}",
|
||||
:"models.#{klass.name.underscore}.#{type}" ]
|
||||
[:"models.#{klass.name.underscore}.attributes.#{attribute}.#{type}",
|
||||
:"models.#{klass.name.underscore}.#{type}"]
|
||||
end.flatten
|
||||
|
||||
keys << options.delete(:default)
|
||||
|
@ -108,6 +109,7 @@ module ActiveModel
|
|||
class InstructureHumanMessageReporter < HumanMessageReporter
|
||||
def full_message(attribute, message)
|
||||
return message if attribute == :base
|
||||
|
||||
str = attribute.to_s.gsub('.', '_').humanize
|
||||
str = base.class.human_attribute_name(attribute, default: str)
|
||||
|
||||
|
@ -117,10 +119,10 @@ module ActiveModel
|
|||
]
|
||||
|
||||
I18n.send(:t,
|
||||
keys.shift,
|
||||
default: keys,
|
||||
attribute: str,
|
||||
message: message)
|
||||
keys.shift,
|
||||
default: keys,
|
||||
attribute: str,
|
||||
message: message)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ class ActiveRecord::Base
|
|||
class << self
|
||||
delegate :distinct_on, :find_ids_in_batches, :explain, to: :all
|
||||
|
||||
def find_ids_in_ranges(opts={}, &block)
|
||||
def find_ids_in_ranges(opts = {}, &block)
|
||||
opts.reverse_merge!(:loose => true)
|
||||
all.find_ids_in_ranges(opts, &block)
|
||||
end
|
||||
|
@ -39,6 +39,7 @@ class ActiveRecord::Base
|
|||
# unless specifically requested
|
||||
def in_transaction_in_test?
|
||||
return false unless Rails.env.test?
|
||||
|
||||
stacktrace = caller
|
||||
|
||||
transaction_index, wrap_index, after_index = [
|
||||
|
@ -48,13 +49,13 @@ class ActiveRecord::Base
|
|||
].map do |method|
|
||||
if method
|
||||
regex = /\A#{Regexp.escape(method.source_location.first)}:\d+:in `#{Regexp.escape(method.name)}'\z/.freeze
|
||||
stacktrace.index{|s| s =~ regex}
|
||||
stacktrace.index { |s| s =~ regex }
|
||||
end
|
||||
end
|
||||
|
||||
if transaction_index
|
||||
# we wrap a transaction around controller actions, so try to see if this call came from that
|
||||
if wrap_index && (transaction_index..wrap_index).all?{|i| stacktrace[i].match?(/transaction|synchronize/)}
|
||||
if wrap_index && (transaction_index..wrap_index).all? { |i| stacktrace[i].match?(/transaction|synchronize/) }
|
||||
false
|
||||
else
|
||||
# check if this is being run through an after_transaction_commit since the last transaction
|
||||
|
@ -97,10 +98,11 @@ class ActiveRecord::Base
|
|||
|
||||
def self.all_models
|
||||
return @all_models if @all_models.present?
|
||||
|
||||
@all_models = (ActiveRecord::Base.models_from_files +
|
||||
[Version]).compact.uniq.reject { |model|
|
||||
(model < Tableless) ||
|
||||
model.abstract_class?
|
||||
model.abstract_class?
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -112,6 +114,7 @@ class ActiveRecord::Base
|
|||
"#{Rails.root}/gems/plugins/*/app/models/**/*.rb",
|
||||
].sort.each do |file|
|
||||
next if const_defined?(file.sub(%r{.*/app/models/(.*)\.rb$}, '\1').camelize)
|
||||
|
||||
ActiveSupport::Dependencies.require_or_load(file)
|
||||
end
|
||||
ActiveRecord::Base.descendants
|
||||
|
@ -119,11 +122,11 @@ class ActiveRecord::Base
|
|||
end
|
||||
|
||||
def self.maximum_text_length
|
||||
@maximum_text_length ||= 64.kilobytes-1
|
||||
@maximum_text_length ||= 64.kilobytes - 1
|
||||
end
|
||||
|
||||
def self.maximum_long_text_length
|
||||
@maximum_long_text_length ||= 500.kilobytes-1
|
||||
@maximum_long_text_length ||= 500.kilobytes - 1
|
||||
end
|
||||
|
||||
def self.maximum_string_length
|
||||
|
@ -258,7 +261,7 @@ class ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def self.skip_touch_context(skip=true)
|
||||
def self.skip_touch_context(skip = true)
|
||||
@@skip_touch_context = skip
|
||||
end
|
||||
|
||||
|
@ -270,6 +273,7 @@ class ActiveRecord::Base
|
|||
|
||||
def touch_context
|
||||
return if (@@skip_touch_context ||= false || @skip_touch_context ||= false)
|
||||
|
||||
if self.respond_to?(:context_type) && self.respond_to?(:context_id) && self.context_type && self.context_id
|
||||
self.class.connection.after_transaction_commit do
|
||||
self.context_type.constantize.where(id: self.context_id).update_all(updated_at: Time.now.utc)
|
||||
|
@ -377,11 +381,11 @@ class ActiveRecord::Base
|
|||
value = options[:delimiter] + value + options[:delimiter]
|
||||
delimiter = connection.quote(options[:delimiter])
|
||||
column_str = "#{delimiter} || %s || #{delimiter}"
|
||||
args = args.map{ |a| column_str % a.to_s }
|
||||
args = args.map { |a| column_str % a.to_s }
|
||||
end
|
||||
|
||||
value = wildcard_pattern(value, options)
|
||||
cols = args.map{ |col| like_condition(col, '?', !options[:case_sensitive]) }
|
||||
cols = args.map { |col| like_condition(col, '?', !options[:case_sensitive]) }
|
||||
sanitize_sql_array ["(" + cols.join(" OR ") + ")", *([value] * cols.size)]
|
||||
end
|
||||
|
||||
|
@ -402,7 +406,7 @@ class ActiveRecord::Base
|
|||
end
|
||||
|
||||
def self.coalesce_chain(cols)
|
||||
"(#{cols.map{|col| coalesce_clause(col)}.join(" || ' ' || ")})"
|
||||
"(#{cols.map { |col| coalesce_clause(col) }.join(" || ' ' || ")})"
|
||||
end
|
||||
|
||||
def self.coalesce_clause(column)
|
||||
|
@ -416,31 +420,31 @@ class ActiveRecord::Base
|
|||
|
||||
def self.best_unicode_collation_key(col)
|
||||
val = if ActiveRecord::Base.configurations[Rails.env]['adapter'] == 'postgresql'
|
||||
# For PostgreSQL, we can't trust a simple LOWER(column), with any collation, since
|
||||
# Postgres just defers to the C library which is different for each platform. The best
|
||||
# choice is the collkey function from pg_collkey which uses ICU to get a full unicode sort.
|
||||
# If that extension isn't around, casting to a bytea sucks for international characters,
|
||||
# but at least it's consistent, and orders commas before letters so you don't end up with
|
||||
# Johnson, Bob sorting before Johns, Jimmy
|
||||
unless @collkey&.key?(Shard.current.database_server.id)
|
||||
@collkey ||= {}
|
||||
@collkey[Shard.current.database_server.id] = connection.extension(:pg_collkey)&.schema
|
||||
end
|
||||
if (collation = Canvas::ICU.choose_pg12_collation(connection.icu_collations) && false)
|
||||
"(#{col} COLLATE #{collation})"
|
||||
elsif (schema = @collkey[Shard.current.database_server.id])
|
||||
# The collation level of 3 is the default, but is explicitly specified here and means that
|
||||
# case, accents and base characters are all taken into account when creating a collation key
|
||||
# for a string - more at https://pgxn.org/dist/pg_collkey/0.5.1/
|
||||
# if you change these arguments, you need to rebuild all db indexes that use them,
|
||||
# and you should also match the settings with Canvas::ICU::Collator and natcompare.js
|
||||
"#{schema}.collkey(#{col}, '#{Canvas::ICU.locale_for_collation}', false, 3, true)"
|
||||
else
|
||||
"CAST(LOWER(replace(#{col}, '\\', '\\\\')) AS bytea)"
|
||||
end
|
||||
else
|
||||
col
|
||||
end
|
||||
# For PostgreSQL, we can't trust a simple LOWER(column), with any collation, since
|
||||
# Postgres just defers to the C library which is different for each platform. The best
|
||||
# choice is the collkey function from pg_collkey which uses ICU to get a full unicode sort.
|
||||
# If that extension isn't around, casting to a bytea sucks for international characters,
|
||||
# but at least it's consistent, and orders commas before letters so you don't end up with
|
||||
# Johnson, Bob sorting before Johns, Jimmy
|
||||
unless @collkey&.key?(Shard.current.database_server.id)
|
||||
@collkey ||= {}
|
||||
@collkey[Shard.current.database_server.id] = connection.extension(:pg_collkey)&.schema
|
||||
end
|
||||
if (collation = Canvas::ICU.choose_pg12_collation(connection.icu_collations) && false)
|
||||
"(#{col} COLLATE #{collation})"
|
||||
elsif (schema = @collkey[Shard.current.database_server.id])
|
||||
# The collation level of 3 is the default, but is explicitly specified here and means that
|
||||
# case, accents and base characters are all taken into account when creating a collation key
|
||||
# for a string - more at https://pgxn.org/dist/pg_collkey/0.5.1/
|
||||
# if you change these arguments, you need to rebuild all db indexes that use them,
|
||||
# and you should also match the settings with Canvas::ICU::Collator and natcompare.js
|
||||
"#{schema}.collkey(#{col}, '#{Canvas::ICU.locale_for_collation}', false, 3, true)"
|
||||
else
|
||||
"CAST(LOWER(replace(#{col}, '\\', '\\\\')) AS bytea)"
|
||||
end
|
||||
else
|
||||
col
|
||||
end
|
||||
Arel.sql(val)
|
||||
end
|
||||
|
||||
|
@ -448,37 +452,36 @@ class ActiveRecord::Base
|
|||
column = options[:column] || "created_at"
|
||||
max_date = (options[:max_date] || Time.zone.now).midnight
|
||||
num_days = options[:num_days] || 20
|
||||
min_date = (options[:min_date] || max_date.advance(:days => -(num_days-1))).midnight
|
||||
min_date = (options[:min_date] || max_date.advance(:days => -(num_days - 1))).midnight
|
||||
|
||||
offset = max_date.utc_offset
|
||||
|
||||
expression = "((#{column} || '-00')::TIMESTAMPTZ AT TIME ZONE '#{Time.zone.tzinfo.name}')::DATE"
|
||||
|
||||
result = where(
|
||||
"#{column} >= ? AND #{column} < ?",
|
||||
min_date,
|
||||
max_date.advance(:days => 1)
|
||||
).
|
||||
group(expression).
|
||||
order(Arel.sql(expression)).
|
||||
count
|
||||
result = where("#{column} >= ? AND #{column} < ?",
|
||||
min_date,
|
||||
max_date.advance(:days => 1))
|
||||
.group(expression)
|
||||
.order(Arel.sql(expression))
|
||||
.count
|
||||
|
||||
return result if result.keys.first.is_a?(Date)
|
||||
|
||||
Hash[result.map { |date, count|
|
||||
[Time.zone.parse(date).to_date, count]
|
||||
}]
|
||||
end
|
||||
|
||||
def self.rank_sql(ary, col)
|
||||
sql = ary.each_with_index.inject(+'CASE '){ |string, (values, i)|
|
||||
string << "WHEN #{col} IN (" << Array(values).map{ |value| connection.quote(value) }.join(', ') << ") THEN #{i} "
|
||||
sql = ary.each_with_index.inject(+'CASE ') { |string, (values, i)|
|
||||
string << "WHEN #{col} IN (" << Array(values).map { |value| connection.quote(value) }.join(', ') << ") THEN #{i} "
|
||||
} << "ELSE #{ary.size} END"
|
||||
Arel.sql(sql)
|
||||
end
|
||||
|
||||
def self.rank_hash(ary)
|
||||
ary.each_with_index.inject(Hash.new(ary.size + 1)){ |hash, (values, i)|
|
||||
Array(values).each{ |value| hash[value] = i + 1 }
|
||||
ary.each_with_index.inject(Hash.new(ary.size + 1)) { |hash, (values, i)|
|
||||
Array(values).each { |value| hash[value] = i + 1 }
|
||||
hash
|
||||
}
|
||||
end
|
||||
|
@ -487,24 +490,24 @@ class ActiveRecord::Base
|
|||
column = column.to_s
|
||||
|
||||
result = if ActiveRecord::Base.configurations[Rails.env]['adapter'] == 'postgresql'
|
||||
sql = +''
|
||||
sql << "SELECT NULL AS #{column} WHERE EXISTS (SELECT * FROM #{quoted_table_name} WHERE #{column} IS NULL) UNION ALL (" if include_nil
|
||||
sql << <<~SQL
|
||||
WITH RECURSIVE t AS (
|
||||
SELECT MIN(#{column}) AS #{column} FROM #{quoted_table_name}
|
||||
UNION ALL
|
||||
SELECT (SELECT MIN(#{column}) FROM #{quoted_table_name} WHERE #{column} > t.#{column})
|
||||
FROM t
|
||||
WHERE t.#{column} IS NOT NULL
|
||||
)
|
||||
SELECT #{column} FROM t WHERE #{column} IS NOT NULL
|
||||
SQL
|
||||
sql << ")" if include_nil
|
||||
find_by_sql(sql)
|
||||
else
|
||||
conditions = "#{column} IS NOT NULL" unless include_nil
|
||||
find(:all, :select => "DISTINCT #{column}", :conditions => conditions, :order => column)
|
||||
end
|
||||
sql = +''
|
||||
sql << "SELECT NULL AS #{column} WHERE EXISTS (SELECT * FROM #{quoted_table_name} WHERE #{column} IS NULL) UNION ALL (" if include_nil
|
||||
sql << <<~SQL
|
||||
WITH RECURSIVE t AS (
|
||||
SELECT MIN(#{column}) AS #{column} FROM #{quoted_table_name}
|
||||
UNION ALL
|
||||
SELECT (SELECT MIN(#{column}) FROM #{quoted_table_name} WHERE #{column} > t.#{column})
|
||||
FROM t
|
||||
WHERE t.#{column} IS NOT NULL
|
||||
)
|
||||
SELECT #{column} FROM t WHERE #{column} IS NOT NULL
|
||||
SQL
|
||||
sql << ")" if include_nil
|
||||
find_by_sql(sql)
|
||||
else
|
||||
conditions = "#{column} IS NOT NULL" unless include_nil
|
||||
find(:all, :select => "DISTINCT #{column}", :conditions => conditions, :order => column)
|
||||
end
|
||||
result.map(&column.to_sym)
|
||||
end
|
||||
|
||||
|
@ -516,7 +519,7 @@ class ActiveRecord::Base
|
|||
elsif first_or_last == :last && direction == :desc
|
||||
" NULLS LAST"
|
||||
end
|
||||
|
||||
|
||||
Arel.sql("#{column} #{direction.to_s.upcase}#{clause}".strip)
|
||||
else
|
||||
Arel.sql("#{column} IS#{" NOT" unless first_or_last == :last} NULL, #{column} #{direction.to_s.upcase}".strip)
|
||||
|
@ -547,7 +550,7 @@ class ActiveRecord::Base
|
|||
Canvas::AccountCacher.apply_to_reflections(self)
|
||||
|
||||
if reflection.options[:polymorphic].is_a?(Array) ||
|
||||
reflection.options[:polymorphic].is_a?(Hash)
|
||||
reflection.options[:polymorphic].is_a?(Hash)
|
||||
reflection.options[:exhaustive] = exhaustive
|
||||
reflection.options[:polymorphic_prefix] = polymorphic_prefix
|
||||
add_polymorph_methods(reflection)
|
||||
|
@ -676,6 +679,7 @@ class ActiveRecord::Base
|
|||
|
||||
def self.bulk_insert_objects(objects, excluded_columns: ['primary_key'])
|
||||
return if objects.empty?
|
||||
|
||||
hashed_objects = []
|
||||
excluded_columns << objects.first.class.primary_key if excluded_columns.delete('primary_key')
|
||||
objects.each do |object|
|
||||
|
@ -691,7 +695,8 @@ class ActiveRecord::Base
|
|||
|
||||
def self.bulk_insert(records)
|
||||
return if records.empty?
|
||||
array_columns = records.first.select{|k, v| v.is_a?(Array)}.map(&:first)
|
||||
|
||||
array_columns = records.first.select { |k, v| v.is_a?(Array) }.map(&:first)
|
||||
array_columns.each do |column_name|
|
||||
cast_type = connection.send(:lookup_cast_type_from_column, self.columns_hash[column_name.to_s])
|
||||
records.each do |row|
|
||||
|
@ -731,6 +736,7 @@ class ActiveRecord::Base
|
|||
# rely on no callbacks or validations
|
||||
def save_without_transaction(touch: true)
|
||||
return unless changed?
|
||||
|
||||
self.updated_at = Time.now.utc if touch
|
||||
if new_record?
|
||||
self.created_at = updated_at if touch
|
||||
|
@ -884,30 +890,30 @@ module UsefulFindInBatches
|
|||
# make sure to log _something_, even if the dbtime is totally off
|
||||
conn.send(:log, full_query, "#{klass.name} Load") do
|
||||
decoder = if load
|
||||
# set up all our metadata based on a dummy query (COPY doesn't return any metadata)
|
||||
result = conn.raw_connection.exec(limited_query)
|
||||
type_map = conn.raw_connection.type_map_for_results.build_column_map(result)
|
||||
# see PostgreSQLAdapter#exec_query
|
||||
types = {}
|
||||
fields = result.fields
|
||||
fields.each_with_index do |fname, i|
|
||||
ftype = result.ftype i
|
||||
fmod = result.fmod i
|
||||
types[fname] = conn.send(:get_oid_type, ftype, fmod, fname)
|
||||
end
|
||||
# set up all our metadata based on a dummy query (COPY doesn't return any metadata)
|
||||
result = conn.raw_connection.exec(limited_query)
|
||||
type_map = conn.raw_connection.type_map_for_results.build_column_map(result)
|
||||
# see PostgreSQLAdapter#exec_query
|
||||
types = {}
|
||||
fields = result.fields
|
||||
fields.each_with_index do |fname, i|
|
||||
ftype = result.ftype i
|
||||
fmod = result.fmod i
|
||||
types[fname] = conn.send(:get_oid_type, ftype, fmod, fname)
|
||||
end
|
||||
|
||||
column_types = types.dup
|
||||
columns_hash.each_key { |k| column_types.delete k }
|
||||
column_types = types.dup
|
||||
columns_hash.each_key { |k| column_types.delete k }
|
||||
|
||||
PG::TextDecoder::CopyRow.new(type_map: type_map)
|
||||
else
|
||||
pkey_oid = columns_hash[primary_key].sql_type_metadata.oid
|
||||
# this is really dumb that we have to manually search through this, but
|
||||
# PG::TypeMapByOid doesn't have a direct lookup method
|
||||
coder = conn.raw_connection.type_map_for_results.coders.find { |c| c.oid == pkey_oid }
|
||||
PG::TextDecoder::CopyRow.new(type_map: type_map)
|
||||
else
|
||||
pkey_oid = columns_hash[primary_key].sql_type_metadata.oid
|
||||
# this is really dumb that we have to manually search through this, but
|
||||
# PG::TypeMapByOid doesn't have a direct lookup method
|
||||
coder = conn.raw_connection.type_map_for_results.coders.find { |c| c.oid == pkey_oid }
|
||||
|
||||
PG::TextDecoder::CopyRow.new(type_map: PG::TypeMapByColumn.new([coder]))
|
||||
end
|
||||
PG::TextDecoder::CopyRow.new(type_map: PG::TypeMapByColumn.new([coder]))
|
||||
end
|
||||
|
||||
rows = []
|
||||
|
||||
|
@ -970,11 +976,11 @@ module UsefulFindInBatches
|
|||
def in_batches_with_temp_table(of: 1000, start: nil, finish: nil, load: false, ignore_transaction: false)
|
||||
Shard.current.database_server.unguard do
|
||||
can_do_it = ignore_transaction ||
|
||||
Rails.env.production? ||
|
||||
ActiveRecord::Base.in_migration ||
|
||||
GuardRail.environment == :deploy ||
|
||||
(!Rails.env.test? && connection.open_transactions > 0) ||
|
||||
ActiveRecord::Base.in_transaction_in_test?
|
||||
Rails.env.production? ||
|
||||
ActiveRecord::Base.in_migration ||
|
||||
GuardRail.environment == :deploy ||
|
||||
(!Rails.env.test? && connection.open_transactions > 0) ||
|
||||
ActiveRecord::Base.in_transaction_in_test?
|
||||
unless can_do_it
|
||||
raise ArgumentError, "in_batches with temp_table probably won't work outside a migration
|
||||
and outside a transaction. Unfortunately, it's impossible to automatically
|
||||
|
@ -1000,12 +1006,12 @@ module UsefulFindInBatches
|
|||
begin
|
||||
old_proc = connection.raw_connection.set_notice_processor {}
|
||||
index = if (select_values.empty? || select_values.any? { |v| v.to_s == primary_key.to_s }) && order_values.empty?
|
||||
connection.execute(%{CREATE INDEX "temp_primary_key" ON #{connection.quote_local_table_name(table)}(#{connection.quote_column_name(primary_key)})})
|
||||
primary_key.to_s
|
||||
else
|
||||
connection.execute "ALTER TABLE #{table} ADD temp_primary_key SERIAL PRIMARY KEY"
|
||||
'temp_primary_key'
|
||||
end
|
||||
connection.execute(%{CREATE INDEX "temp_primary_key" ON #{connection.quote_local_table_name(table)}(#{connection.quote_column_name(primary_key)})})
|
||||
primary_key.to_s
|
||||
else
|
||||
connection.execute "ALTER TABLE #{table} ADD temp_primary_key SERIAL PRIMARY KEY"
|
||||
'temp_primary_key'
|
||||
end
|
||||
ensure
|
||||
connection.raw_connection.set_notice_processor(&old_proc) if old_proc
|
||||
end
|
||||
|
@ -1023,10 +1029,10 @@ module UsefulFindInBatches
|
|||
break if remaining <= 0
|
||||
|
||||
last_value = if yielded_relation.loaded?
|
||||
yielded_relation.last[index]
|
||||
else
|
||||
yielded_relation.offset(of - 1).limit(1).pluck(index).first
|
||||
end
|
||||
yielded_relation.last[index]
|
||||
else
|
||||
yielded_relation.offset(of - 1).limit(1).pluck(index).first
|
||||
end
|
||||
break if last_value.nil?
|
||||
|
||||
yielded_relation = batch_relation.where("#{connection.quote_column_name(index)} > ?", last_value)
|
||||
|
@ -1108,8 +1114,8 @@ module UsefulBatchEnumerator
|
|||
return to_enum(:pluck, *args) unless block_given?
|
||||
|
||||
@relation.except(:select)
|
||||
.select(*args)
|
||||
.in_batches(strategy: @strategy, load: false, **@kwargs) do |relation|
|
||||
.select(*args)
|
||||
.in_batches(strategy: @strategy, load: false, **@kwargs) do |relation|
|
||||
yield relation.pluck(*args)
|
||||
end
|
||||
end
|
||||
|
@ -1132,7 +1138,7 @@ module UsefulBatchEnumerator
|
|||
|
||||
found_match = true
|
||||
|
||||
raw_update = update.value.value_before_type_cast
|
||||
raw_update = update.value.value_before_type_cast
|
||||
# we want to check exact class here, not ancestry, since we want to ignore
|
||||
# subclasses we don't understand
|
||||
if pred.class == Arel::Nodes::Equality
|
||||
|
@ -1200,7 +1206,7 @@ ActiveRecord::Relation.class_eval do
|
|||
|
||||
def not_recently_touched
|
||||
scope = self
|
||||
if((personal_space = Setting.get('touch_personal_space', 0).to_i) != 0)
|
||||
if ((personal_space = Setting.get('touch_personal_space', 0).to_i) != 0)
|
||||
personal_space -= 1
|
||||
# truncate to seconds
|
||||
bound = Time.at(Time.now.to_i - personal_space).utc
|
||||
|
@ -1278,6 +1284,7 @@ ActiveRecord::Relation.class_eval do
|
|||
while ids.present?
|
||||
yield ids
|
||||
break if ids.size < batch_size
|
||||
|
||||
last_value = ids.last
|
||||
ids = connection.select_values(scope.where("#{key}>?", last_value).to_sql)
|
||||
ids = ids.map(&:to_i) unless options[:no_integer_cast]
|
||||
|
@ -1316,7 +1323,7 @@ ActiveRecord::Relation.class_eval do
|
|||
end
|
||||
|
||||
module UpdateAndDeleteWithJoins
|
||||
def deconstruct_joins(joins_sql=nil)
|
||||
def deconstruct_joins(joins_sql = nil)
|
||||
unless joins_sql
|
||||
joins_sql = ''
|
||||
add_joins!(joins_sql, nil)
|
||||
|
@ -1326,6 +1333,7 @@ module UpdateAndDeleteWithJoins
|
|||
joins_sql.strip.split('INNER JOIN')[1..-1].each do |join|
|
||||
# this could probably be improved
|
||||
raise "PostgreSQL update_all/delete_all only supports INNER JOIN" unless join.strip =~ /([a-zA-Z0-9'"_\.]+(?:(?:\s+[aA][sS])?\s+[a-zA-Z0-9'"_]+)?)\s+ON\s+(.*)/m
|
||||
|
||||
tables << $1
|
||||
join_conditions << $2
|
||||
end
|
||||
|
@ -1336,7 +1344,7 @@ module UpdateAndDeleteWithJoins
|
|||
db = Shard.current(klass.shard_category).database_server
|
||||
if joins_values.empty?
|
||||
if ::GuardRail.environment != db.guard_rail_environment
|
||||
Shard.current.database_server.unguard {return super }
|
||||
Shard.current.database_server.unguard { return super }
|
||||
else
|
||||
return super
|
||||
end
|
||||
|
@ -1376,7 +1384,7 @@ module UpdateAndDeleteWithJoins
|
|||
where_sql = collector.value
|
||||
sql.concat('WHERE ' + where_sql)
|
||||
if ::GuardRail.environment != db.guard_rail_environment
|
||||
Shard.current.database_server.unguard {connection.update(sql, "#{name} Update")}
|
||||
Shard.current.database_server.unguard { connection.update(sql, "#{name} Update") }
|
||||
else
|
||||
connection.update(sql, "#{name} Update")
|
||||
end
|
||||
|
@ -1431,6 +1439,7 @@ ActiveRecord::Relation.prepend(UpdateAndDeleteAllWithLimit)
|
|||
ActiveRecord::Associations::CollectionProxy.class_eval do
|
||||
def respond_to?(name, include_private = false)
|
||||
return super if [:marshal_dump, :_dump, 'marshal_dump', '_dump'].include?(name)
|
||||
|
||||
super ||
|
||||
(load_target && target.respond_to?(name, include_private)) ||
|
||||
proxy_association.klass.respond_to?(name, include_private)
|
||||
|
@ -1451,13 +1460,13 @@ end
|
|||
ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do
|
||||
def bulk_insert(table_name, records)
|
||||
keys = records.first.keys
|
||||
quoted_keys = keys.map{ |k| quote_column_name(k) }.join(', ')
|
||||
quoted_keys = keys.map { |k| quote_column_name(k) }.join(', ')
|
||||
records.each do |record|
|
||||
execute <<~SQL
|
||||
INSERT INTO #{quote_table_name(table_name)}
|
||||
(#{quoted_keys})
|
||||
VALUES
|
||||
(#{keys.map{ |k| quote(record[k]) }.join(', ')})
|
||||
(#{keys.map { |k| quote(record[k]) }.join(', ')})
|
||||
SQL
|
||||
end
|
||||
end
|
||||
|
@ -1473,7 +1482,7 @@ class ActiveRecord::ConnectionAdapters::AbstractAdapter
|
|||
# string_agg(name::text, '|') (postgres)
|
||||
|
||||
def func(name, *args)
|
||||
"#{name}(#{args.map{ |arg| func_arg_esc(arg) }.join(', ')})"
|
||||
"#{name}(#{args.map { |arg| func_arg_esc(arg) }.join(', ')})"
|
||||
end
|
||||
|
||||
def func_arg_esc(arg)
|
||||
|
@ -1552,6 +1561,7 @@ class ActiveRecord::MigrationProxy
|
|||
load(filename)
|
||||
@migration = name.constantize
|
||||
raise "#{self.name} (#{self.version}) is not tagged as exactly one of predeploy or postdeploy!" unless (@migration.tags & ActiveRecord::Migration::DEPLOY_TAGS).length == 1
|
||||
|
||||
@migration
|
||||
end
|
||||
end
|
||||
|
@ -1575,6 +1585,7 @@ module Migrator
|
|||
|
||||
def pending_migrations(call_super: false)
|
||||
return super() if call_super
|
||||
|
||||
super().select(&:runnable?)
|
||||
end
|
||||
|
||||
|
@ -1592,6 +1603,7 @@ module Migrator
|
|||
if HighLine.new.ask("Revert migration #{migration.name} (#{migration.version}) ? [y/N/a] > ") !~ /^([ya])/i
|
||||
raise("Revert not confirmed")
|
||||
end
|
||||
|
||||
$confirmed_migrate_down = true if $1.downcase == 'a'
|
||||
end
|
||||
|
||||
|
@ -1634,6 +1646,7 @@ ActiveRecord::ConnectionAdapters::SchemaStatements.class_eval do
|
|||
|
||||
def foreign_key_for(from_table, **options)
|
||||
return unless supports_foreign_keys?
|
||||
|
||||
fks = foreign_keys(from_table).select { |fk| fk.defined_for?(options) }
|
||||
# prefer a FK on a column named after the table
|
||||
if options[:to_table]
|
||||
|
@ -1714,7 +1727,6 @@ end
|
|||
|
||||
ActiveRecord::Migration::CommandRecorder.prepend(ExistenceInversions)
|
||||
|
||||
|
||||
ActiveRecord::Associations::CollectionAssociation.class_eval do
|
||||
# CollectionAssociation implements uniq for :uniq option, in its
|
||||
# own special way. re-implement, but as a relation
|
||||
|
@ -1741,6 +1753,7 @@ module MatchWithDiscard
|
|||
def match(model, name)
|
||||
result = super
|
||||
return nil if result && !result.is_a?(ActiveRecord::DynamicMatchers::FindBy)
|
||||
|
||||
result
|
||||
end
|
||||
end
|
||||
|
@ -1793,6 +1806,7 @@ module SkipTouchCallbacks
|
|||
module BelongsTo
|
||||
def touch_record(o, _changes, _foreign_key, name, *)
|
||||
return if o.class.touch_callbacks_skipped?(name)
|
||||
|
||||
super
|
||||
end
|
||||
end
|
||||
|
@ -1831,6 +1845,7 @@ module IgnoreOutOfSequenceMigrationDates
|
|||
migration_lookup_at(dirname).map do |file|
|
||||
digits = File.basename(file).split("_").first
|
||||
next if ActiveRecord::Base.timestamped_migrations && digits.length != 14
|
||||
|
||||
digits.to_i
|
||||
end.compact.max.to_i
|
||||
end
|
||||
|
@ -1875,7 +1890,7 @@ module ExplainAnalyze
|
|||
end
|
||||
|
||||
def explain(analyze: false)
|
||||
#TODO: Fix for binds.
|
||||
# TODO: Fix for binds.
|
||||
exec_explain(collecting_queries_for_explain do
|
||||
if block_given?
|
||||
yield
|
||||
|
@ -1959,6 +1974,7 @@ module RestoreConnectionConnectionPool
|
|||
def restore_connection(conn)
|
||||
# If the connection got closed before we restored it, don't try to return it
|
||||
return unless conn.active?
|
||||
|
||||
synchronize do
|
||||
adopt_connection(conn)
|
||||
# check if a new connection was checked out in the meantime, and check it back in
|
||||
|
@ -1978,7 +1994,6 @@ module RestoreConnectionConnectionPool
|
|||
end
|
||||
ActiveRecord::ConnectionAdapters::ConnectionPool.prepend(RestoreConnectionConnectionPool)
|
||||
|
||||
|
||||
module MaxRuntimeConnectionPool
|
||||
def max_runtime
|
||||
# TODO: Rails 6.1 uses a PoolConfig object instead
|
||||
|
@ -2019,6 +2034,7 @@ module MaxRuntimeConnectionPool
|
|||
old_connections = synchronize do
|
||||
# TODO: Rails 6.1 adds a `discarded?` method instead of checking this directly
|
||||
return unless @connections
|
||||
|
||||
@connections.select do |conn|
|
||||
!conn.in_use? && conn.runtime >= max_runtime
|
||||
end.each do |conn|
|
||||
|
@ -2071,10 +2087,10 @@ module Serialization
|
|||
|
||||
serializable_add_includes(options) do |association, records, opts|
|
||||
hash[association.to_s] = if records.respond_to?(:to_ary)
|
||||
records.to_ary.map { |a| a.serializable_hash(opts) }
|
||||
else
|
||||
records.serializable_hash(opts)
|
||||
end
|
||||
records.to_ary.map { |a| a.serializable_hash(opts) }
|
||||
else
|
||||
records.serializable_hash(opts)
|
||||
end
|
||||
end
|
||||
|
||||
hash
|
||||
|
@ -2095,7 +2111,7 @@ module UserContentSerialization
|
|||
end
|
||||
end
|
||||
if options && options[:include_root]
|
||||
result = {self.class.base_class.model_name.element => result}
|
||||
result = { self.class.base_class.model_name.element => result }
|
||||
end
|
||||
result
|
||||
end
|
||||
|
|
|
@ -64,7 +64,6 @@ module ActiveSupport::Cache
|
|||
Entry.prepend(AllowMocksInStore)
|
||||
end
|
||||
|
||||
|
||||
module IgnoreMonkeyPatchesInDeprecations
|
||||
def extract_callstack(callstack)
|
||||
return _extract_callstack(callstack) if callstack.first.is_a?(String)
|
||||
|
@ -79,11 +78,11 @@ module IgnoreMonkeyPatchesInDeprecations
|
|||
|
||||
def ignored_callstack(frame)
|
||||
if frame.is_a?(String)
|
||||
if md = frame.match(/^(.+?):(\d+)(?::in `(.*?)')?/)
|
||||
path, _, label = md.captures
|
||||
else
|
||||
return false
|
||||
end
|
||||
if md = frame.match(/^(.+?):(\d+)(?::in `(.*?)')?/)
|
||||
path, _, label = md.captures
|
||||
else
|
||||
return false
|
||||
end
|
||||
else
|
||||
path, _, label = frame.absolute_path, frame.lineno, frame.label
|
||||
end
|
||||
|
@ -91,6 +90,7 @@ module IgnoreMonkeyPatchesInDeprecations
|
|||
return true if path&.start_with?(File.expand_path(File.dirname(__FILE__) + "/../../gems/activesupport-suspend_callbacks"))
|
||||
return true if path == File.expand_path(File.dirname(__FILE__) + "/../../spec/support/blank_slate_protection.rb")
|
||||
return true if path == File.expand_path(File.dirname(__FILE__) + "/../../spec/selenium/common.rb")
|
||||
|
||||
@switchman ||= File.expand_path(Gem.loaded_specs['switchman'].full_gem_path) + "/"
|
||||
return true if path&.start_with?(@switchman)
|
||||
return true if label == 'render' && path&.end_with?("application_controller.rb")
|
||||
|
@ -99,6 +99,7 @@ module IgnoreMonkeyPatchesInDeprecations
|
|||
return true if label == 'block in wrap_block_in_transaction' && path == File.expand_path(File.dirname(__FILE__) + "/../../spec/spec_helper.rb")
|
||||
|
||||
return false unless path
|
||||
|
||||
super(path)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -46,8 +46,8 @@ module IgnoreSlaveErrors
|
|||
rescue ActiveRecord::StatementInvalid => error
|
||||
# "simulated" secondary of a user with read-only access; probably the same error for Slony
|
||||
raise if !error.message.match(/PG(?:::)?Error: ERROR: +permission denied for relation/) &&
|
||||
# real secondary that's in recovery
|
||||
!error.message.match(/PG(?:::)?Error: ERROR: +cannot execute UPDATE in a read-only transaction/)
|
||||
# real secondary that's in recovery
|
||||
!error.message.match(/PG(?:::)?Error: ERROR: +cannot execute UPDATE in a read-only transaction/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -26,6 +26,7 @@ load_cache_config = -> do
|
|||
while !clusters_to_search.empty?
|
||||
cluster = clusters_to_search.shift
|
||||
next if searched.include?(cluster)
|
||||
|
||||
searched << cluster
|
||||
config = Canvas.cache_store_config_for(cluster)
|
||||
|
||||
|
|
|
@ -16,4 +16,4 @@
|
|||
# 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/>.
|
||||
|
||||
CanvasCacheInit.apply!
|
||||
CanvasCacheInit.apply!
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
#
|
||||
# Copyright (C) 2021 - present Instructure, Inc.
|
||||
#
|
||||
|
@ -17,4 +18,4 @@
|
|||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
CanvasCassandra.logger = Rails.logger
|
||||
CanvasCassandra.settings_store = Setting # to avoid having to pull this out as a full engine yet.
|
||||
CanvasCassandra.settings_store = Setting # to avoid having to pull this out as a full engine yet.
|
||||
|
|
|
@ -20,4 +20,4 @@
|
|||
require 'canvas_crummy'
|
||||
|
||||
ActionController::Base.send :include, CanvasCrummy::ControllerMethods
|
||||
ActionView::Base.send :include, CanvasCrummy::ViewMethods
|
||||
ActionView::Base.send :include, CanvasCrummy::ViewMethods
|
||||
|
|
|
@ -24,18 +24,19 @@ CanvasHttp.blocked_ip_filters = -> { Setting.get('http_blocked_ip_ranges', '127.
|
|||
|
||||
module CanvasHttpInitializer
|
||||
def self.configure_circuit_breaker!
|
||||
# need some place to store circuit breaker information so we don't
|
||||
# need some place to store circuit breaker information so we don't
|
||||
# have to have each process store it's own circuit breaker
|
||||
# state
|
||||
CanvasHttp::CircuitBreaker.redis = lambda {
|
||||
return MultiCache.cache.redis if MultiCache.cache.respond_to?(:redis)
|
||||
return Canvas.redis if Canvas.redis_enabled?
|
||||
|
||||
nil
|
||||
}
|
||||
|
||||
# how many failures for a domain trips the circuit breaker
|
||||
CanvasHttp::CircuitBreaker.threshold = lambda do |domain|
|
||||
(Setting.get("http_cb_#{domain}_threshold", nil) ||
|
||||
(Setting.get("http_cb_#{domain}_threshold", nil) ||
|
||||
Setting.get("http_cb_generic_threshold", CanvasHttp::CircuitBreaker::DEFAULT_THRESHOLD)).to_i
|
||||
end
|
||||
|
||||
|
|
|
@ -16,4 +16,4 @@
|
|||
#
|
||||
# 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/>.
|
||||
CanvasPartman.timeout_seconds = ->{ Setting.get('partman_timeout_seconds', '30').to_i }
|
||||
CanvasPartman.timeout_seconds = -> { Setting.get('partman_timeout_seconds', '30').to_i }
|
||||
|
|
|
@ -19,4 +19,4 @@
|
|||
|
||||
require 'canvas_sanitize'
|
||||
|
||||
ActiveRecord::Base.send :include, CanvasSanitize
|
||||
ActiveRecord::Base.send :include, CanvasSanitize
|
||||
|
|
|
@ -21,4 +21,4 @@ require 'config_file'
|
|||
|
||||
# make sure we drop the object and yaml caches so we force
|
||||
# config file reloads whenever we reset settings
|
||||
Canvas::Reloader.on_reload { ConfigFile.reset_cache }
|
||||
Canvas::Reloader.on_reload { ConfigFile.reset_cache }
|
||||
|
|
|
@ -59,17 +59,17 @@ module Delayed::Backend::DefaultJobAccount
|
|||
end
|
||||
Delayed::Backend::ActiveRecord::Job.include(Delayed::Backend::DefaultJobAccount)
|
||||
|
||||
Delayed::Settings.default_job_options = ->{ { current_shard: Shard.current }}
|
||||
Delayed::Settings.fetch_batch_size = ->{ Setting.get('jobs_get_next_batch_size', '5').to_i }
|
||||
Delayed::Settings.job_detailed_log_format = ->(job){ job.to_log_format }
|
||||
Delayed::Settings.default_job_options = -> { { current_shard: Shard.current } }
|
||||
Delayed::Settings.fetch_batch_size = -> { Setting.get('jobs_get_next_batch_size', '5').to_i }
|
||||
Delayed::Settings.job_detailed_log_format = ->(job) { job.to_log_format }
|
||||
Delayed::Settings.max_attempts = 1
|
||||
Delayed::Settings.num_strands = ->(strand_name){ Setting.get("#{strand_name}_num_strands", nil) }
|
||||
Delayed::Settings.num_strands = ->(strand_name) { Setting.get("#{strand_name}_num_strands", nil) }
|
||||
Delayed::Settings.pool_procname_suffix = " (#{Canvas.revision})" if Canvas.revision
|
||||
Delayed::Settings.queue = "canvas_queue"
|
||||
Delayed::Settings.select_random_from_batch = ->{ Setting.get('jobs_select_random', 'false') == 'true' }
|
||||
Delayed::Settings.sleep_delay = ->{ Setting.get('delayed_jobs_sleep_delay', '2.0').to_f }
|
||||
Delayed::Settings.sleep_delay_stagger = ->{ Setting.get('delayed_jobs_sleep_delay_stagger', '2.0').to_f }
|
||||
Delayed::Settings.worker_procname_prefix = ->{ "#{Shard.current(:delayed_jobs).id}~" }
|
||||
Delayed::Settings.select_random_from_batch = -> { Setting.get('jobs_select_random', 'false') == 'true' }
|
||||
Delayed::Settings.sleep_delay = -> { Setting.get('delayed_jobs_sleep_delay', '2.0').to_f }
|
||||
Delayed::Settings.sleep_delay_stagger = -> { Setting.get('delayed_jobs_sleep_delay_stagger', '2.0').to_f }
|
||||
Delayed::Settings.worker_procname_prefix = -> { "#{Shard.current(:delayed_jobs).id}~" }
|
||||
Delayed::Settings.worker_health_check_type = Delayed::CLI.instance&.config&.dig('health_check', 'type')&.to_sym || :none
|
||||
Delayed::Settings.worker_health_check_config = Delayed::CLI.instance&.config&.[]('health_check')
|
||||
# transitional
|
||||
|
@ -82,7 +82,6 @@ if ActiveRecord::Base.configurations[Rails.env]['queue']
|
|||
ActiveSupport::Deprecation.warn("A queue section in database.yml is no longer supported. Please run migrations, then remove it.")
|
||||
end
|
||||
|
||||
|
||||
Rails.application.config.after_initialize do
|
||||
# configure autoscaling plugin
|
||||
if (config = Delayed::CLI.instance&.config&.[](:auto_scaling))
|
||||
|
@ -92,8 +91,8 @@ Rails.application.config.after_initialize do
|
|||
aws_config = config[:aws_config] || {}
|
||||
aws_config[:region] ||= ApplicationController.region
|
||||
actions << JobsAutoscaling::AwsAction.new(asg_name: config[:asg_name],
|
||||
aws_config: aws_config,
|
||||
instance_id: ApplicationController.instance_id)
|
||||
aws_config: aws_config,
|
||||
instance_id: ApplicationController.instance_id)
|
||||
end
|
||||
autoscaler = JobsAutoscaling::Monitor.new(action: actions)
|
||||
autoscaler.activate!
|
||||
|
@ -209,7 +208,7 @@ WARNABLE_DELAYED_EXCEPTIONS = [
|
|||
].freeze
|
||||
|
||||
Delayed::Worker.lifecycle.before(:error) do |worker, job, exception|
|
||||
is_warnable = WARNABLE_DELAYED_EXCEPTIONS.any?{|klass| exception.is_a?(klass) }
|
||||
is_warnable = WARNABLE_DELAYED_EXCEPTIONS.any? { |klass| exception.is_a?(klass) }
|
||||
error_level = is_warnable ? :warn : :error
|
||||
info = Canvas::Errors::JobInfo.new(job, worker)
|
||||
begin
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
module DynamoDBDateSupport
|
||||
def format(obj)
|
||||
if obj.respond_to?(:iso8601)
|
||||
{s: obj.iso8601}
|
||||
{ s: obj.iso8601 }
|
||||
else
|
||||
super(obj)
|
||||
end
|
||||
|
@ -31,4 +31,3 @@ module DynamoDBDateSupport
|
|||
end
|
||||
|
||||
Aws::DynamoDB::AttributeValue::Marshaler.prepend(DynamoDBDateSupport)
|
||||
|
||||
|
|
|
@ -28,12 +28,12 @@
|
|||
#
|
||||
Rails.configuration.to_prepare do
|
||||
ErrorReport.configure_to_ignore(%w{
|
||||
AuthenticationMethods::AccessTokenError
|
||||
ActionController::InvalidAuthenticityToken
|
||||
Turnitin::Errors::SubmissionNotScoredError
|
||||
ActionController::ParameterMissing
|
||||
SearchTermHelper::SearchTermTooShortError
|
||||
})
|
||||
AuthenticationMethods::AccessTokenError
|
||||
ActionController::InvalidAuthenticityToken
|
||||
Turnitin::Errors::SubmissionNotScoredError
|
||||
ActionController::ParameterMissing
|
||||
SearchTermHelper::SearchTermTooShortError
|
||||
})
|
||||
|
||||
# write a database record to our application DB capturing useful info for looking
|
||||
# at this error later
|
||||
|
|
|
@ -20,17 +20,17 @@
|
|||
require 'folio/core_ext/enumerable'
|
||||
|
||||
module Folio::WillPaginate::ActiveRecord::Pagination
|
||||
def paginate(options={})
|
||||
def paginate(options = {})
|
||||
if !options.has_key?(:total_entries)
|
||||
scope = if ::Rails.version < '4'
|
||||
self.scoped
|
||||
elsif self.is_a?(::ActiveRecord::Relation)
|
||||
self
|
||||
elsif self < ::ActiveRecord::Base
|
||||
self.all
|
||||
else
|
||||
self.scope
|
||||
end
|
||||
self.scoped
|
||||
elsif self.is_a?(::ActiveRecord::Relation)
|
||||
self
|
||||
elsif self < ::ActiveRecord::Base
|
||||
self.all
|
||||
else
|
||||
self.scope
|
||||
end
|
||||
group_values = scope.group_values
|
||||
unless group_values.empty?
|
||||
begin
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
# 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/>.
|
||||
|
||||
|
||||
# NOTE: this initializer is only necessary while some object types are still
|
||||
# using the legacy graphql api. This should be removed when we all objects
|
||||
# have been migrated to the graphql-ruby-1.8-style api.
|
||||
|
|
|
@ -116,6 +116,7 @@ module FormatInterpolatedNumbers
|
|||
values = values.dup
|
||||
values.each do |key, value|
|
||||
next unless value.is_a?(Numeric)
|
||||
|
||||
values[key] = ActiveSupport::NumberHelper.number_to_delimited(value)
|
||||
end
|
||||
super(string, values)
|
||||
|
@ -128,10 +129,11 @@ I18nliner.infer_interpolation_values = false
|
|||
module I18nliner
|
||||
module RehashArrays
|
||||
def infer_pluralization_hash(default, *args)
|
||||
if default.is_a?(Array) && default.all?{|a| a.is_a?(Array) && a.size == 2 && a.first.is_a?(Symbol)}
|
||||
if default.is_a?(Array) && default.all? { |a| a.is_a?(Array) && a.size == 2 && a.first.is_a?(Symbol) }
|
||||
# this was a pluralization hash but rails 4 made it an array in the view helpers
|
||||
return Hash[default]
|
||||
end
|
||||
|
||||
super
|
||||
end
|
||||
end
|
||||
|
@ -276,6 +278,7 @@ I18n.send(:extend, Module.new {
|
|||
# english, rather than asploding
|
||||
key, options = I18nliner::CallHelpers.infer_arguments(args)
|
||||
raise if (options[:locale] || locale) == default_locale
|
||||
|
||||
super(key, options.merge(locale: default_locale))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
ActiveSupport::Inflector.inflections do |inflect|
|
||||
inflect.singular /(criteri)a$/i, '\1on'
|
||||
inflect.plural /(criteri)on$/i, '\1a'
|
||||
inflect.acronym "GraphQL"
|
||||
inflect.singular /(criteri)a$/i, '\1on'
|
||||
inflect.plural /(criteri)on$/i, '\1a'
|
||||
inflect.acronym "GraphQL"
|
||||
end
|
||||
|
|
|
@ -28,4 +28,4 @@ class InstAccessSupport
|
|||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -21,7 +21,7 @@ module JobLiveEventsContext
|
|||
def live_events_context
|
||||
ctx = {
|
||||
job_id: global_id,
|
||||
job_tag:tag,
|
||||
job_tag: tag,
|
||||
producer: 'canvas',
|
||||
root_account_id: Account.default.global_id,
|
||||
root_account_uuid: Account.default.uuid,
|
||||
|
|
|
@ -32,7 +32,7 @@ ActiveSupport::JSON::Encoding.time_precision = 0
|
|||
class BigDecimal
|
||||
remove_method :as_json
|
||||
|
||||
def as_json(options = nil) #:nodoc:
|
||||
def as_json(options = nil) # :nodoc:
|
||||
if finite?
|
||||
CanvasRails::Application.instance.config.active_support.encode_big_decimal_as_string ? to_s : to_f
|
||||
else
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
class CanvasLinkedInConfig
|
||||
|
||||
def self.call
|
||||
settings = Canvas::Plugin.find(:linked_in).try(:settings)
|
||||
if settings
|
||||
|
@ -29,7 +28,6 @@ class CanvasLinkedInConfig
|
|||
else
|
||||
ConfigFile.load('linked_in').dup
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ class StubbedClient
|
|||
events = records.map { |e| JSON.parse(e[:data]).dig('attributes', 'event_name') }.join(' | ')
|
||||
puts "Events #{events} put to stream #{stream_name}: #{records}"
|
||||
OpenStruct.new(
|
||||
records: records.map { |r| OpenStruct.new(error_code: 'failure', error_message: 'this fails' ) }
|
||||
records: records.map { |r| OpenStruct.new(error_code: 'failure', error_message: 'this fails') }
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -37,7 +37,7 @@ Rails.configuration.to_prepare do
|
|||
LiveEvents.statsd = InstStatsd::Statsd
|
||||
LiveEvents.max_queue_size = -> { Setting.get('live_events_max_queue_size', 5000).to_i }
|
||||
LiveEvents.settings = -> { Canvas::DynamicSettings.find('live-events', default_ttl: 2.hours) }
|
||||
LiveEvents.aws_credentials = -> (settings) {
|
||||
LiveEvents.aws_credentials = ->(settings) {
|
||||
if settings['vault_credential_path']
|
||||
Canvas::Vault::AwsCredentialProvider.new(settings['vault_credential_path'])
|
||||
else
|
||||
|
|
|
@ -38,7 +38,7 @@ Rails.configuration.to_prepare do
|
|||
HostUrl.outgoing_email_default_name = config[:default_name]
|
||||
|
||||
IncomingMail::ReplyToAddress.address_pool = config[:reply_to_addresses] ||
|
||||
Array(HostUrl.outgoing_email_address)
|
||||
Array(HostUrl.outgoing_email_address)
|
||||
IncomingMailProcessor::MailboxAccount.default_outgoing_email = HostUrl.outgoing_email_address
|
||||
IncomingMailProcessor::MailboxAccount.reply_to_enabled = config[:reply_to_disabled].blank?
|
||||
end
|
||||
|
|
|
@ -44,7 +44,7 @@ class PeriodicJobs
|
|||
end
|
||||
|
||||
if jitter.present?
|
||||
run_at = rand((run_at+10.seconds)..(run_at + jitter))
|
||||
run_at = rand((run_at + 10.seconds)..(run_at + jitter))
|
||||
end
|
||||
run_at
|
||||
end
|
||||
|
@ -55,6 +55,7 @@ class PeriodicJobs
|
|||
strand = "#{klass}.#{method}:#{Shard.current.database_server.id}"
|
||||
# TODO: allow this to work with redis jobs
|
||||
next if Delayed::Job == Delayed::Backend::ActiveRecord::Job && Delayed::Job.where(strand: strand, shard_id: Shard.current.id, locked_by: nil).exists?
|
||||
|
||||
dj_params = {
|
||||
strand: strand,
|
||||
priority: 40
|
||||
|
@ -200,8 +201,8 @@ Rails.configuration.after_initialize do
|
|||
AuthenticationProvider::SAML::Federation.descendants.each do |federation|
|
||||
Delayed::Periodic.cron "AuthenticationProvider::SAML::#{federation.class_name}.refresh_providers", '45 0 * * *' do
|
||||
DatabaseServer.send_in_each_region(federation,
|
||||
:refresh_providers,
|
||||
singleton: "AuthenticationProvider::SAML::#{federation.class_name}.refresh_providers")
|
||||
:refresh_providers,
|
||||
singleton: "AuthenticationProvider::SAML::#{federation.class_name}.refresh_providers")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -285,11 +286,10 @@ Rails.configuration.after_initialize do
|
|||
if MultiCache.cache.is_a?(ActiveSupport::Cache::HaStore) && MultiCache.cache.options[:consul_event] && InstStatsd.settings.present?
|
||||
Delayed::Periodic.cron 'HaStore.validate_consul_event', '5 * * * *' do
|
||||
DatabaseServer.send_in_each_region(MultiCache, :validate_consul_event,
|
||||
{
|
||||
run_current_region_asynchronously: true,
|
||||
singleton: 'HaStore.validate_consul_event'
|
||||
}
|
||||
)
|
||||
{
|
||||
run_current_region_asynchronously: true,
|
||||
singleton: 'HaStore.validate_consul_event'
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -25,6 +25,7 @@ end
|
|||
module PostgreSQLAdapterExtensions
|
||||
def receive_timeout_wrapper
|
||||
return yield unless @config[:receive_timeout]
|
||||
|
||||
Timeout.timeout(@config[:receive_timeout], PG::ConnectionBad, "receive timeout") { yield }
|
||||
end
|
||||
|
||||
|
@ -36,7 +37,6 @@ module PostgreSQLAdapterExtensions
|
|||
RUBY
|
||||
end
|
||||
|
||||
|
||||
def explain(arel, binds = [], analyze: false)
|
||||
sql = "EXPLAIN #{"ANALYZE " if analyze}#{to_sql(arel, binds)}"
|
||||
ActiveRecord::ConnectionAdapters::PostgreSQL::ExplainPrettyPrinter.new.pp(exec_query(sql, "EXPLAIN", binds))
|
||||
|
@ -44,15 +44,16 @@ module PostgreSQLAdapterExtensions
|
|||
|
||||
def readonly?(table = nil, column = nil)
|
||||
return @readonly unless @readonly.nil?
|
||||
|
||||
@readonly = in_recovery?
|
||||
end
|
||||
|
||||
def bulk_insert(table_name, records)
|
||||
keys = records.first.keys
|
||||
quoted_keys = keys.map{ |k| quote_column_name(k) }.join(', ')
|
||||
quoted_keys = keys.map { |k| quote_column_name(k) }.join(', ')
|
||||
execute "COPY #{quote_table_name(table_name)} (#{quoted_keys}) FROM STDIN"
|
||||
raw_connection.put_copy_data records.inject(+''){ |result, record|
|
||||
result << keys.map{ |k| quote_text(record[k]) }.join("\t") << "\n"
|
||||
raw_connection.put_copy_data records.inject(+'') { |result, record|
|
||||
result << keys.map { |k| quote_text(record[k]) }.join("\t") << "\n"
|
||||
}
|
||||
ActiveRecord::Base.connection.clear_query_cache
|
||||
raw_connection.put_copy_end
|
||||
|
@ -71,8 +72,8 @@ module PostgreSQLAdapterExtensions
|
|||
elsif value.is_a?(ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Array::Data)
|
||||
quote_text(encode_array(value))
|
||||
else
|
||||
hash = {"\n" => "\\n", "\r" => "\\r", "\t" => "\\t", "\\" => "\\\\"}
|
||||
value.to_s.gsub(/[\n\r\t\\]/){ |c| hash[c] }
|
||||
hash = { "\n" => "\\n", "\r" => "\\r", "\t" => "\\t", "\\" => "\\\\" }
|
||||
value.to_s.gsub(/[\n\r\t\\]/) { |c| hash[c] }
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -102,10 +103,10 @@ module PostgreSQLAdapterExtensions
|
|||
|
||||
def func(name, *args)
|
||||
case name
|
||||
when :group_concat
|
||||
"string_agg((#{func_arg_esc(args.first)})::text, #{quote(args[1] || ',')})"
|
||||
else
|
||||
super
|
||||
when :group_concat
|
||||
"string_agg((#{func_arg_esc(args.first)})::text, #{quote(args[1] || ',')})"
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -124,15 +125,15 @@ module PostgreSQLAdapterExtensions
|
|||
schema = shard.name
|
||||
|
||||
result = query(<<~SQL, 'SCHEMA')
|
||||
SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid
|
||||
FROM pg_class t
|
||||
INNER JOIN pg_index d ON t.oid = d.indrelid
|
||||
INNER JOIN pg_class i ON d.indexrelid = i.oid
|
||||
WHERE i.relkind = 'i'
|
||||
AND d.indisprimary = 'f'
|
||||
AND t.relname = '#{table_name}'
|
||||
AND t.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = #{schema ? "'#{schema}'" : 'ANY (current_schemas(false))'} )
|
||||
ORDER BY i.relname
|
||||
SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid
|
||||
FROM pg_class t
|
||||
INNER JOIN pg_index d ON t.oid = d.indrelid
|
||||
INNER JOIN pg_class i ON d.indexrelid = i.oid
|
||||
WHERE i.relkind = 'i'
|
||||
AND d.indisprimary = 'f'
|
||||
AND t.relname = '#{table_name}'
|
||||
AND t.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = #{schema ? "'#{schema}'" : 'ANY (current_schemas(false))'} )
|
||||
ORDER BY i.relname
|
||||
SQL
|
||||
|
||||
result.map do |row|
|
||||
|
@ -153,7 +154,7 @@ module PostgreSQLAdapterExtensions
|
|||
|
||||
# add info on sort order for columns (only desc order is explicitly specified, asc is the default)
|
||||
desc_order_columns = inddef.scan(/(\w+) DESC/).flatten
|
||||
orders = desc_order_columns.any? ? Hash[desc_order_columns.map {|order_column| [order_column, :desc]}] : {}
|
||||
orders = desc_order_columns.any? ? Hash[desc_order_columns.map { |order_column| [order_column, :desc] }] : {}
|
||||
|
||||
ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, index_name, unique, column_names, orders: orders)
|
||||
end
|
||||
|
@ -162,6 +163,7 @@ module PostgreSQLAdapterExtensions
|
|||
def index_exists?(_table_name, columns, _options = {})
|
||||
raise ArgumentError.new("if you're identifying an index by name only, you should use index_name_exists?") if columns.is_a?(Hash) && columns[:name]
|
||||
raise ArgumentError.new("columns should be a string, a symbol, or an array of those ") unless columns.is_a?(String) || columns.is_a?(Symbol) || columns.is_a?(Array)
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
|
@ -235,6 +237,7 @@ module PostgreSQLAdapterExtensions
|
|||
"Specify an index name from #{matching_indexes.map(&:name).join(', ')}"
|
||||
elsif matching_indexes.none?
|
||||
return if options.is_a?(Hash) && options[:if_exists]
|
||||
|
||||
raise ArgumentError, "No indexes found on #{table_name} with the options provided."
|
||||
else
|
||||
matching_indexes.first.name
|
||||
|
@ -247,11 +250,13 @@ module PostgreSQLAdapterExtensions
|
|||
|
||||
def add_column(table_name, column_name, type, if_not_exists: false, **options)
|
||||
return if if_not_exists && column_exists?(table_name, column_name)
|
||||
|
||||
super(table_name, column_name, type, **options)
|
||||
end
|
||||
|
||||
def remove_column(table_name, column_name, type = nil, if_exists: false, **options)
|
||||
return if if_exists && !column_exists?(table_name, column_name)
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
|
@ -289,6 +294,7 @@ module PostgreSQLAdapterExtensions
|
|||
|
||||
def icu_collations
|
||||
return [] if postgresql_version < 120000
|
||||
|
||||
@collations ||= select_rows <<~SQL, "SCHEMA"
|
||||
SELECT nspname, collname
|
||||
FROM pg_collation
|
||||
|
@ -302,6 +308,7 @@ module PostgreSQLAdapterExtensions
|
|||
|
||||
def create_icu_collations
|
||||
return if postgresql_version < 120000
|
||||
|
||||
original_locale = I18n.locale
|
||||
|
||||
collation = "und-u-kn-true"
|
||||
|
@ -311,10 +318,13 @@ module PostgreSQLAdapterExtensions
|
|||
|
||||
I18n.available_locales.each do |locale|
|
||||
next if locale =~ /-x-/
|
||||
|
||||
I18n.locale = locale
|
||||
next if Canvas::ICU.collator.rules.empty?
|
||||
|
||||
collation = "#{locale}-u-kn-true"
|
||||
next if icu_collations.find { |_schema, extant_collation| extant_collation == collation }
|
||||
|
||||
update("CREATE COLLATION public.#{quote_column_name(collation)} (LOCALE=#{quote(collation)}, PROVIDER='icu', DETERMINISTIC=false)")
|
||||
end
|
||||
ensure
|
||||
|
@ -347,7 +357,6 @@ end
|
|||
|
||||
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(PostgreSQLAdapterExtensions)
|
||||
|
||||
|
||||
module SchemaCreationExtensions
|
||||
def set_table_context(table)
|
||||
@table = table
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
#encoding:ASCII-8BIT
|
||||
# encoding:ASCII-8BIT
|
||||
#
|
||||
# Copyright (C) 2012 - present Instructure, Inc.
|
||||
#
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
#
|
||||
# Copyright (C) 2020 - present Instructure, Inc.
|
||||
#
|
||||
|
@ -25,4 +26,4 @@ Rails.configuration.to_prepare do
|
|||
AccountReports.handle_error = lambda do |exception, context, level|
|
||||
Canvas::Errors.capture(exception, context, level)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,8 +22,6 @@
|
|||
# eg: instead of '/images/whatever.png?12345', we want '/dist/images/whatever-<md5 of file>.png'.
|
||||
# There is a different method that needs to be monkeypatched for rails 3 vs rails 4
|
||||
|
||||
|
||||
|
||||
require 'action_view/helpers'
|
||||
|
||||
module RevAssetPaths
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
# This makes it so all parameters get converted to UTF-8 before they hit your
|
||||
# app. If someone sends invalid UTF-8 to your server, raise an exception.
|
||||
class ActionController::InvalidByteSequenceErrorFromParams < Encoding::InvalidByteSequenceError; end
|
||||
|
||||
class ActionController::Base
|
||||
def force_utf8_params
|
||||
traverse = lambda do |object, block|
|
||||
|
|
|
@ -89,7 +89,7 @@ module YAMLSingletonFix
|
|||
if klass < Singleton
|
||||
klass.instance
|
||||
elsif klass == Set
|
||||
super.tap{|s| s.instance_variable_get(:@hash).default = false}
|
||||
super.tap { |s| s.instance_variable_get(:@hash).default = false }
|
||||
else
|
||||
super
|
||||
end
|
||||
|
|
|
@ -24,8 +24,8 @@
|
|||
# Make sure the secret is at least 30 characters and all random,
|
||||
# no regular words or you'll be exposed to dictionary attacks.
|
||||
config = {
|
||||
:key => '_normandy_session',
|
||||
:secret => (Setting.get("session_secret_key", SecureRandom.hex(64), set_if_nx: true) rescue SecureRandom.hex(64)),
|
||||
:key => '_normandy_session',
|
||||
:secret => (Setting.get("session_secret_key", SecureRandom.hex(64), set_if_nx: true) rescue SecureRandom.hex(64)),
|
||||
legacy_key: '_legacy_normandy_session',
|
||||
same_site: :none
|
||||
}.merge((ConfigFile.load("session_store").dup || {}).symbolize_keys)
|
||||
|
|
|
@ -31,7 +31,8 @@ Rails.configuration.to_prepare do
|
|||
:submission,
|
||||
:wiki_page,
|
||||
{ quiz: 'Quizzes::Quiz',
|
||||
quiz_submission: 'Quizzes::QuizSubmission' }]
|
||||
quiz_submission: 'Quizzes::QuizSubmission' }
|
||||
]
|
||||
Version.add_polymorph_methods(reflection)
|
||||
|
||||
Version.include(CanvasPartman::Concerns::Partitioned)
|
||||
|
|
|
@ -87,6 +87,7 @@ module ArbitraryStrongishParams
|
|||
|
||||
def convert_hashes_to_parameters(key, value, *args)
|
||||
return value if @anythings.key?(key)
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ Rails.application.config.after_initialize do
|
|||
|
||||
def settings
|
||||
return {} unless self.class.columns_hash.key?('settings')
|
||||
|
||||
s = super
|
||||
if s.nil?
|
||||
self.settings = s = {}
|
||||
|
@ -124,6 +125,7 @@ Rails.application.config.after_initialize do
|
|||
# either way there's only one shard, and we always want to see it
|
||||
return [default] unless default.is_a?(Switchman::Shard)
|
||||
return all if !ApplicationController.region || DatabaseServer.all.all? { |db| !db.config[:region] }
|
||||
|
||||
in_region(ApplicationController.region)
|
||||
end
|
||||
end
|
||||
|
@ -154,7 +156,7 @@ Rails.application.config.after_initialize do
|
|||
start_day.send("#{ordinal}_#{maintenance_window_weekday}_in_month".downcase)
|
||||
end + relevant_weeks.map do |ordinal|
|
||||
(start_day + 1.month).send("#{ordinal}_#{maintenance_window_weekday}_in_month".downcase)
|
||||
end
|
||||
end
|
||||
|
||||
next_day = maintenance_days.find { |d| d.future? }
|
||||
# Time offsets are strange
|
||||
|
@ -199,6 +201,7 @@ Rails.application.config.after_initialize do
|
|||
all.each do |db|
|
||||
next if (regions.include?(db.config[:region]) || !db.config[:region])
|
||||
next if db.shards.empty?
|
||||
|
||||
regions << db.config[:region]
|
||||
db.shards.first.activate do
|
||||
klass.delay(**enqueue_args).__send__(method, *args)
|
||||
|
@ -219,6 +222,7 @@ Rails.application.config.after_initialize do
|
|||
end
|
||||
|
||||
raise "Could not find a shard in region #{region}" unless shard
|
||||
|
||||
shard.activate do
|
||||
klass.delay(**enqueue_args).__send__(method, *args)
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module MarkTemplateStreaming
|
||||
def render_to_body(options={})
|
||||
def render_to_body(options = {})
|
||||
@streaming_template = true if options[:stream]
|
||||
super
|
||||
end
|
||||
|
@ -100,7 +100,7 @@ ActionView::StreamingFlow.prepend(StreamingContentChecks) unless ::Rails.env.pro
|
|||
|
||||
module SkipEmptyTemplateConcats
|
||||
def initialize(original_block)
|
||||
new_block = -> (value) { original_block.call(value) if value.size > 0}
|
||||
new_block = ->(value) { original_block.call(value) if value.size > 0 }
|
||||
super(new_block)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
module JsonTimeInUTC
|
||||
def as_json(options = {})
|
||||
return super if utc?
|
||||
|
||||
utc.as_json(options)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
class CanvasTwitterConfig
|
||||
|
||||
def self.call
|
||||
settings = Canvas::Plugin.find(:twitter).try(:settings)
|
||||
if settings
|
||||
|
@ -29,9 +28,7 @@ class CanvasTwitterConfig
|
|||
else
|
||||
ConfigFile.load('twitter').dup
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Twitter::Connection.config = CanvasTwitterConfig
|
||||
|
|
|
@ -24,22 +24,22 @@ if CANVAS_ZEITWERK
|
|||
# This is because the jsx folder does not contain ruby to
|
||||
# autoload. You should NOT use this pattern as a workaround
|
||||
# for badly-named ruby code.
|
||||
Rails.autoloaders.main.ignore(Rails.root.join('app','jsx'))
|
||||
Rails.autoloaders.main.ignore(Rails.root.join('app', 'jsx'))
|
||||
|
||||
# This one exists because we require plugins to be const get'd from Canvas::Plugins::Validators::
|
||||
#require 'canvas'
|
||||
#require 'canvas/plugins'
|
||||
#require 'canvas/plugins/validators'
|
||||
# # This one exists because we require plugins to be const get'd from Canvas::Plugins::Validators::
|
||||
# require 'canvas'
|
||||
# require 'canvas/plugins'
|
||||
# require 'canvas/plugins/validators'
|
||||
|
||||
# TODO: Load things that are not being properly loaded by zeitwerk right now
|
||||
#require 'canvas_connect'
|
||||
#require 'canvas_connect/version'
|
||||
# in the canvas_connect gem, the "to_prepare"
|
||||
# block uses this.
|
||||
#require 'canvas/plugins/adobe_connect'
|
||||
#require 'canvas_webex'
|
||||
#require 'canvas_webex/version'
|
||||
#byebug
|
||||
# # TODO: Load things that are not being properly loaded by zeitwerk right now
|
||||
# require 'canvas_connect'
|
||||
# require 'canvas_connect/version'
|
||||
# # in the canvas_connect gem, the "to_prepare"
|
||||
# # block uses this.
|
||||
# require 'canvas/plugins/adobe_connect'
|
||||
# require 'canvas_webex'
|
||||
# require 'canvas_webex/version'
|
||||
# byebug
|
||||
|
||||
Rails.autoloaders.each do |autoloader|
|
||||
autoloader.inflector.inflect(
|
||||
|
@ -54,4 +54,4 @@ if CANVAS_ZEITWERK
|
|||
"xml_helper" => "XMLHelper",
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,4 +22,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,4 +35,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,4 +19,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,4 +19,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,4 +33,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,4 +27,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,4 +18,4 @@
|
|||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
threads 0,1
|
||||
threads 0, 1
|
||||
|
|
132
config/routes.rb
132
config/routes.rb
|
@ -112,12 +112,12 @@ CanvasRails::Application.routes.draw do
|
|||
get 'contents' => 'files#attachment_content', as: :attachment_content
|
||||
get 'file_preview' => 'file_previews#show'
|
||||
collection do
|
||||
get "folder#{full_path_glob}" => 'files#react_files', format: false, defaults: {format: 'html'}
|
||||
get "search" => 'files#react_files', format: false, defaults: {format: 'html'}
|
||||
get "folder#{full_path_glob}" => 'files#react_files', format: false, defaults: { format: 'html' }
|
||||
get "search" => 'files#react_files', format: false, defaults: { format: 'html' }
|
||||
get :quota
|
||||
post :reorder
|
||||
end
|
||||
get ':file_path' => 'files#show_relative', as: :relative_path, file_path: /.+/ #needs to stay below react_files route
|
||||
get ':file_path' => 'files#show_relative', as: :relative_path, file_path: /.+/ # needs to stay below react_files route
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -262,26 +262,26 @@ CanvasRails::Application.routes.draw do
|
|||
get 'moderate' => 'assignments#show_moderate'
|
||||
|
||||
get 'anonymous_submissions/:anonymous_id', to: 'submissions/anonymous_previews#show',
|
||||
constraints: ->(request) do
|
||||
request.query_parameters.key?(:preview) && request.format == :html
|
||||
end
|
||||
constraints: ->(request) do
|
||||
request.query_parameters.key?(:preview) && request.format == :html
|
||||
end
|
||||
|
||||
get 'anonymous_submissions/:anonymous_id', to: 'submissions/anonymous_downloads#show',
|
||||
constraints: ->(request) do
|
||||
request.query_parameters.key?(:download)
|
||||
end
|
||||
constraints: ->(request) do
|
||||
request.query_parameters.key?(:download)
|
||||
end
|
||||
|
||||
get 'anonymous_submissions/:anonymous_id', to: 'anonymous_submissions#show', as: :anonymous_submission
|
||||
|
||||
get 'submissions/:id', to: 'submissions/previews#show',
|
||||
constraints: ->(request) do
|
||||
request.query_parameters.key?(:preview) && request.format == :html
|
||||
end
|
||||
constraints: ->(request) do
|
||||
request.query_parameters.key?(:preview) && request.format == :html
|
||||
end
|
||||
|
||||
get 'submissions/:id', to: 'submissions/downloads#show',
|
||||
constraints: ->(request) do
|
||||
request.query_parameters.key?(:download)
|
||||
end
|
||||
constraints: ->(request) do
|
||||
request.query_parameters.key?(:download)
|
||||
end
|
||||
|
||||
put 'anonymous_submissions/:anonymous_id', to: 'anonymous_submissions#update'
|
||||
put 'anonymous_submissions/:anonymous_id/reassign', to: 'anonymous_submissions#redo_submission'
|
||||
|
@ -296,20 +296,20 @@ CanvasRails::Application.routes.draw do
|
|||
end
|
||||
|
||||
get 'anonymous_submissions/:anonymous_id/originality_report/:asset_string',
|
||||
to: 'anonymous_submissions#originality_report',
|
||||
as: :anonymous_submission_originality_report
|
||||
to: 'anonymous_submissions#originality_report',
|
||||
as: :anonymous_submission_originality_report
|
||||
post 'anonymous_submissions/:anonymous_id/turnitin/resubmit',
|
||||
to: 'anonymous_submissions#resubmit_to_turnitin',
|
||||
as: :anonymous_submission_resubmit_to_turnitin
|
||||
to: 'anonymous_submissions#resubmit_to_turnitin',
|
||||
as: :anonymous_submission_resubmit_to_turnitin
|
||||
get 'anonymous_submissions/:anonymous_id/turnitin/:asset_string',
|
||||
to: 'anonymous_submissions#turnitin_report',
|
||||
as: :anonymous_submission_turnitin_report
|
||||
to: 'anonymous_submissions#turnitin_report',
|
||||
as: :anonymous_submission_turnitin_report
|
||||
post 'anonymous_submissions/:anonymous_id/vericite/resubmit',
|
||||
to: 'anonymous_submissions#resubmit_to_vericite',
|
||||
as: :anonymous_submission_resubmit_to_vericite
|
||||
to: 'anonymous_submissions#resubmit_to_vericite',
|
||||
as: :anonymous_submission_resubmit_to_vericite
|
||||
get 'anonymous_submissions/:anonymous_id/vericite/:asset_string',
|
||||
to: 'anonymous_submissions#vericite_report',
|
||||
as: :anonymous_submission_vericite_report
|
||||
to: 'anonymous_submissions#vericite_report',
|
||||
as: :anonymous_submission_vericite_report
|
||||
|
||||
get :rubric
|
||||
resource :rubric_association, path: :rubric do
|
||||
|
@ -333,7 +333,7 @@ CanvasRails::Application.routes.draw do
|
|||
end
|
||||
|
||||
get 'lti/resource/:resource_link_id', controller: 'lti/message',
|
||||
action: 'resource', as: :resource_link_id
|
||||
action: 'resource', as: :resource_link_id
|
||||
end
|
||||
|
||||
resources :grading_standards, only: [:index, :create, :update, :destroy]
|
||||
|
@ -356,14 +356,14 @@ CanvasRails::Application.routes.draw do
|
|||
end
|
||||
|
||||
get 'lti/resource/:resource_link_id', controller: 'lti/message',
|
||||
action: 'resource', as: :resource_link_id
|
||||
action: 'resource', as: :resource_link_id
|
||||
get 'lti/basic_lti_launch_request/:message_handler_id', controller: 'lti/message',
|
||||
action: 'basic_lti_launch_request', as: :basic_lti_launch_request
|
||||
action: 'basic_lti_launch_request', as: :basic_lti_launch_request
|
||||
post 'lti/tool_proxy_registration', controller: 'lti/message', action: 'registration', as: :tool_proxy_registration
|
||||
get 'lti/tool_proxy_reregistration/:tool_proxy_id', controller: 'lti/message', action: 'reregistration',
|
||||
as: :tool_proxy_reregistration
|
||||
as: :tool_proxy_reregistration
|
||||
get 'lti/registration_return', controller: 'lti/message', action: 'registration_return',
|
||||
as: :registration_return
|
||||
as: :registration_return
|
||||
|
||||
resources :submissions
|
||||
resources :calendar_events
|
||||
|
@ -684,14 +684,14 @@ CanvasRails::Application.routes.draw do
|
|||
end
|
||||
|
||||
get 'lti/resource/:resource_link_id', controller: 'lti/message',
|
||||
action: 'resource', as: :resource_link_id
|
||||
action: 'resource', as: :resource_link_id
|
||||
get 'lti/basic_lti_launch_request/:message_handler_id', controller: 'lti/message',
|
||||
action: 'basic_lti_launch_request', as: :basic_lti_launch_request
|
||||
action: 'basic_lti_launch_request', as: :basic_lti_launch_request
|
||||
post 'lti/tool_proxy_registration', controller: 'lti/message', action: 'registration', as: :tool_proxy_registration
|
||||
get 'lti/tool_proxy_reregistration/:tool_proxy_id', controller: 'lti/message', action: 'reregistration',
|
||||
as: :tool_proxy_reregistration
|
||||
as: :tool_proxy_reregistration
|
||||
get 'lti/registration_return', controller: 'lti/message', action: 'registration_return',
|
||||
as: :registration_return
|
||||
as: :registration_return
|
||||
|
||||
get 'outcomes/users/:user_id' => 'outcomes#user_outcome_results', as: :user_outcomes_results
|
||||
resources :outcomes do
|
||||
|
@ -917,8 +917,8 @@ CanvasRails::Application.routes.draw do
|
|||
get 'calendar2' => 'calendars#show'
|
||||
get 'course_sections/:course_section_id/calendar_events/:id' => 'calendar_events#show', as: :course_section_calendar_event
|
||||
get 'files' => 'files#index'
|
||||
get "files/folder#{full_path_glob}", controller: 'files', action: 'react_files', format: false, defaults: {format: 'html'}
|
||||
get "files/search", controller: 'files', action: 'react_files', format: false, defaults: {format: 'html'}
|
||||
get "files/folder#{full_path_glob}", controller: 'files', action: 'react_files', format: false, defaults: { format: 'html' }
|
||||
get "files/search", controller: 'files', action: 'react_files', format: false, defaults: { format: 'html' }
|
||||
get 'files/:id/public_url' => 'files#public_url', as: :public_url
|
||||
post 'files/pending' => 'files#create_pending', as: :file_create_pending
|
||||
resources :assignments, only: :index do
|
||||
|
@ -1208,18 +1208,18 @@ CanvasRails::Application.routes.draw do
|
|||
|
||||
scope(controller: :anonymous_provisional_grades) do
|
||||
get "courses/:course_id/assignments/:assignment_id/anonymous_provisional_grades/status",
|
||||
action: :status, as: "course_assignment_anonymous_provisional_status"
|
||||
action: :status, as: "course_assignment_anonymous_provisional_status"
|
||||
end
|
||||
|
||||
scope(controller: :provisional_grades) do
|
||||
put "courses/:course_id/assignments/:assignment_id/provisional_grades/bulk_select",
|
||||
action: :bulk_select, as: 'bulk_select_provisional_grades'
|
||||
action: :bulk_select, as: 'bulk_select_provisional_grades'
|
||||
get "courses/:course_id/assignments/:assignment_id/provisional_grades/status",
|
||||
action: :status, as: "course_assignment_provisional_status"
|
||||
action: :status, as: "course_assignment_provisional_status"
|
||||
post "courses/:course_id/assignments/:assignment_id/provisional_grades/publish",
|
||||
action: :publish, as: 'publish_provisional_grades'
|
||||
action: :publish, as: 'publish_provisional_grades'
|
||||
put "courses/:course_id/assignments/:assignment_id/provisional_grades/:provisional_grade_id/select",
|
||||
action: :select, as: 'select_provisional_grade'
|
||||
action: :select, as: 'select_provisional_grade'
|
||||
end
|
||||
|
||||
scope(controller: :submission_comments_api) do
|
||||
|
@ -1346,17 +1346,17 @@ CanvasRails::Application.routes.draw do
|
|||
scope(controller: 'lti/tool_proxy') do
|
||||
%w(course account).each do |context|
|
||||
delete "#{context}s/:#{context}_id/tool_proxies/:tool_proxy_id", action: :destroy,
|
||||
as: "#{context}_delete_tool_proxy"
|
||||
as: "#{context}_delete_tool_proxy"
|
||||
put "#{context}s/:#{context}_id/tool_proxies/:tool_proxy_id", action: :update,
|
||||
as: "#{context}_update_tool_proxy"
|
||||
as: "#{context}_update_tool_proxy"
|
||||
|
||||
delete "#{context}s/:#{context}_id/tool_proxies/:tool_proxy_id/update", action: :dismiss_update,
|
||||
as: "#{context}_dismiss_update_tool_proxy"
|
||||
as: "#{context}_dismiss_update_tool_proxy"
|
||||
put "#{context}s/:#{context}_id/tool_proxies/:tool_proxy_id/update", action: :accept_update,
|
||||
as: "#{context}_accept_update_tool_proxy"
|
||||
as: "#{context}_accept_update_tool_proxy"
|
||||
|
||||
get "#{context}s/:#{context}_id/tool_proxies/:tool_proxy_id/recreate_subscriptions", action: :recreate_subscriptions,
|
||||
as: "#{context}_recreate_subscriptions_tool_proxy"
|
||||
as: "#{context}_recreate_subscriptions_tool_proxy"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1670,7 +1670,7 @@ CanvasRails::Application.routes.draw do
|
|||
resources :users, path: "groups/:group_id/users", name_prefix: "group_", controller: :group_memberships, except: [:index, :create]
|
||||
end
|
||||
|
||||
get 'groups/:group_id/files', controller: :files, action: :api_index, as: 'group_files'
|
||||
get 'groups/:group_id/files', controller: :files, action: :api_index, as: 'group_files'
|
||||
get 'groups/:group_id/folders', controller: :folders, action: :list_all_folders, as: 'group_folders'
|
||||
post 'groups/:group_id/folders', controller: :folders, action: :create
|
||||
get 'groups/:group_id/folders/by_path/*full_path', controller: :folders, action: :resolve_path
|
||||
|
@ -1716,7 +1716,6 @@ CanvasRails::Application.routes.draw do
|
|||
match '/api/v1/files/:id/create_success', via: [:options], action: :api_create_success_cors
|
||||
post 'files/capture', action: :api_capture, as: 'files_capture'
|
||||
|
||||
|
||||
# 'attachment' (rather than 'file') is used below so modules API can use polymorphic_url to generate an item API link
|
||||
get 'files/:id', action: :api_show, as: 'attachment'
|
||||
delete 'files/:id', action: :destroy
|
||||
|
@ -2361,17 +2360,17 @@ CanvasRails::Application.routes.draw do
|
|||
end
|
||||
end
|
||||
|
||||
# this is not a "normal" api endpoint in the sense that it is not documented or
|
||||
# generally available to hosted customers. it also does not respect the normal
|
||||
# pagination options; however, jobs_controller already accepts `limit` and `offset`
|
||||
# paramaters and defines a sane default limit
|
||||
ApiRouteSet::V1.draw(self) do
|
||||
scope(controller: :jobs) do
|
||||
get 'jobs', action: :index
|
||||
get 'jobs/:id', action: :show
|
||||
post 'jobs/batch_update', action: :batch_update
|
||||
end
|
||||
# this is not a "normal" api endpoint in the sense that it is not documented or
|
||||
# generally available to hosted customers. it also does not respect the normal
|
||||
# pagination options; however, jobs_controller already accepts `limit` and `offset`
|
||||
# paramaters and defines a sane default limit
|
||||
ApiRouteSet::V1.draw(self) do
|
||||
scope(controller: :jobs) do
|
||||
get 'jobs', action: :index
|
||||
get 'jobs/:id', action: :show
|
||||
post 'jobs/batch_update', action: :batch_update
|
||||
end
|
||||
end
|
||||
|
||||
# this is not a "normal" api endpoint in the sense that it is not documented
|
||||
# or called directly, it's used as the redirect in the file upload process
|
||||
|
@ -2397,7 +2396,6 @@ CanvasRails::Application.routes.draw do
|
|||
end
|
||||
|
||||
ApiRouteSet.draw(self, "/api/lti") do
|
||||
|
||||
scope(controller: 'lti/tool_configurations_api') do
|
||||
put 'developer_keys/:developer_key_id/tool_configuration', action: :update
|
||||
post 'accounts/:account_id/developer_keys/tool_configuration', action: :create
|
||||
|
@ -2436,25 +2434,25 @@ CanvasRails::Application.routes.draw do
|
|||
|
||||
post "#{prefix}/authorize", controller: 'lti/ims/authorization', action: :authorize, as: "#{context}_lti_oauth2_authorize"
|
||||
get "#{prefix}/tool_consumer_profile(/:tool_consumer_profile_id)", controller: 'lti/ims/tool_consumer_profile',
|
||||
action: 'show', as: "#{context}_tool_consumer_profile"
|
||||
action: 'show', as: "#{context}_tool_consumer_profile"
|
||||
post "#{prefix}/tool_proxy", controller: 'lti/ims/tool_proxy', action: :re_reg,
|
||||
as: "re_reg_#{context}_lti_tool_proxy", constraints: Lti::ReRegConstraint.new
|
||||
as: "re_reg_#{context}_lti_tool_proxy", constraints: Lti::ReRegConstraint.new
|
||||
post "#{prefix}/tool_proxy", controller: 'lti/ims/tool_proxy', action: :create,
|
||||
as: "create_#{context}_lti_tool_proxy"
|
||||
as: "create_#{context}_lti_tool_proxy"
|
||||
get "#{prefix}/jwt_token", controller: 'external_tools', action: :jwt_token
|
||||
get "tool_proxy/:tool_proxy_guid/#{prefix}/tool_setting", controller: 'lti/ims/tool_setting', action: :show, as: "show_#{context}_tool_setting"
|
||||
get "tool_proxy/:tool_proxy_guid/#{prefix}/resource_link_id/:resource_link_id/tool_setting", controller: 'lti/ims/tool_setting', action: :show, as: "show_#{context}_resource_link_id_tool_setting"
|
||||
put "tool_proxy/:tool_proxy_guid/#{prefix}/tool_setting", controller: 'lti/ims/tool_setting', action: :update, as: "update_#{context}_tool_setting"
|
||||
put "tool_proxy/:tool_proxy_guid/#{prefix}/resource_link_id/:resource_link_id/tool_setting", controller: 'lti/ims/tool_setting', action: :update, as: "update_#{context}_update_resource_link_id_tool_setting"
|
||||
end
|
||||
#Tool Setting Services
|
||||
get "tool_settings/:tool_setting_id", controller: 'lti/ims/tool_setting', action: :show, as: :show_lti_tool_settings
|
||||
# Tool Setting Services
|
||||
get "tool_settings/:tool_setting_id", controller: 'lti/ims/tool_setting', action: :show, as: :show_lti_tool_settings
|
||||
get "tool_proxy/:tool_proxy_guid/tool_setting", controller: 'lti/ims/tool_setting', action: :show, as: :show_tool_proxy_lti_tool_settings
|
||||
put "tool_settings/:tool_setting_id", controller: 'lti/ims/tool_setting', action: :update, as: :update_lti_tool_settings
|
||||
put "tool_settings/:tool_setting_id", controller: 'lti/ims/tool_setting', action: :update, as: :update_lti_tool_settings
|
||||
put "tool_proxy/:tool_proxy_guid/tool_setting", controller: 'lti/ims/tool_setting', action: :update, as: :update_tool_proxy_lti_tool_settings
|
||||
|
||||
#Tool Proxy Services
|
||||
get "tool_proxy/:tool_proxy_guid", controller: 'lti/ims/tool_proxy', action: :show, as: "show_lti_tool_proxy"
|
||||
# Tool Proxy Services
|
||||
get "tool_proxy/:tool_proxy_guid", controller: 'lti/ims/tool_proxy', action: :show, as: "show_lti_tool_proxy"
|
||||
|
||||
# Membership Service
|
||||
get "courses/:course_id/membership_service", controller: "lti/membership_service", action: :course_index, as: :course_membership_service
|
||||
|
|
Loading…
Reference in New Issue