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:
Cody Cutrer 2021-09-21 15:21:00 -06:00
parent cf0045a411
commit 4896de008e
79 changed files with 404 additions and 374 deletions

View File

@ -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

View File

@ -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

View File

@ -59,4 +59,4 @@ unless defined?(CANVAS_RAILS6_0)
CANVAS_RAILS6_0 = true
end
end
end
end

View File

@ -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:

View File

@ -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

View File

@ -56,7 +56,6 @@ end
ActionController::Base.include(DataStreamingContentLength)
module FileAccessUserOnSession
def self.included(klass)
klass.attr_writer :file_access_user

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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!

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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 }

View File

@ -19,4 +19,4 @@
require 'canvas_sanitize'
ActiveRecord::Base.send :include, CanvasSanitize
ActiveRecord::Base.send :include, CanvasSanitize

View File

@ -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 }

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -28,4 +28,4 @@ class InstAccessSupport
)
end
end
end
end

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true
#encoding:ASCII-8BIT
# encoding:ASCII-8BIT
#
# Copyright (C) 2012 - present Instructure, Inc.
#

View File

@ -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

View File

@ -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

View File

@ -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|

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -87,6 +87,7 @@ module ArbitraryStrongishParams
def convert_hashes_to_parameters(key, value, *args)
return value if @anythings.key?(key)
super
end

View File

@ -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

View File

@ -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

View File

@ -20,6 +20,7 @@
module JsonTimeInUTC
def as_json(options = {})
return super if utc?
utc.as_json(options)
end
end

View File

@ -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

View File

@ -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

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -22,4 +22,4 @@
}
}
}
}
}

View File

@ -35,4 +35,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -19,4 +19,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -19,4 +19,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -33,4 +33,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -27,4 +27,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -15,4 +15,4 @@
}
}
}
}
}

View File

@ -18,4 +18,4 @@
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
threads 0,1
threads 0, 1

View File

@ -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