squash old migrations 202001-202002
Change-Id: I17c208f94ba440976c0265f782b1cd57448a109f Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/342169 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Jacob Burroughs <jburroughs@instructure.com> Migration-Review: Jacob Burroughs <jburroughs@instructure.com> QA-Review: Cody Cutrer <cody@instructure.com> Product-Review: Cody Cutrer <cody@instructure.com>
This commit is contained in:
parent
1324efe12c
commit
5c6a4f9e04
|
@ -1230,7 +1230,6 @@ class GradebooksController < ApplicationController
|
|||
|
||||
def change_gradebook_column_size
|
||||
if authorized_action(@context, @current_user, [:manage_grades, :view_all_grades])
|
||||
@current_user.migrate_preferences_if_needed
|
||||
sub_key = @current_user.shared_gradebook_column?(params[:column_id]) ? "shared" : @context.global_id
|
||||
size_hash = @current_user.get_preference(:gradebook_column_size, sub_key) || {}
|
||||
size_hash[params[:column_id]] = params[:column_size]
|
||||
|
@ -1409,7 +1408,6 @@ class GradebooksController < ApplicationController
|
|||
|
||||
def change_gradebook_version
|
||||
update_preferred_gradebook_view!("gradebook")
|
||||
@current_user.migrate_preferences_if_needed
|
||||
@current_user.set_preference(:gradebook_version, params[:version])
|
||||
redirect_to polymorphic_url([@context, :gradebook])
|
||||
end
|
||||
|
@ -1712,7 +1710,6 @@ class GradebooksController < ApplicationController
|
|||
end
|
||||
|
||||
def gradebook_column_size_preferences
|
||||
@current_user.migrate_preferences_if_needed
|
||||
@current_user.save if @current_user.changed?
|
||||
shared_settings = @current_user.get_preference(:gradebook_column_size, "shared") || {}
|
||||
course_settings = @current_user.get_preference(:gradebook_column_size, @context.global_id) || {}
|
||||
|
|
|
@ -69,34 +69,6 @@ class UserPreferenceValue < ActiveRecord::Base
|
|||
end
|
||||
|
||||
module UserMethods
|
||||
# i could just stuff all this in user.rb directly but it's so full already
|
||||
def needs_preference_migration?
|
||||
preferences.any? do |key, value|
|
||||
UserPreferenceValue.settings[key] && value.present? && value != EXTERNAL
|
||||
end
|
||||
end
|
||||
|
||||
# can remove these when all preferences have been migrated
|
||||
def migrate_preferences_if_needed
|
||||
return unless needs_preference_migration?
|
||||
|
||||
reorganize_gradebook_preferences # may as well while we're at it
|
||||
UserPreferenceValue.settings.each do |key, settings|
|
||||
value = preferences[key]
|
||||
next unless value.present?
|
||||
next if value == EXTERNAL
|
||||
|
||||
if settings[:use_sub_keys]
|
||||
value.each do |sub_key, sub_value|
|
||||
create_user_preference_value(key, sub_key, sub_value)
|
||||
end
|
||||
else
|
||||
create_user_preference_value(key, nil, value)
|
||||
end
|
||||
preferences[key] = EXTERNAL
|
||||
end
|
||||
end
|
||||
|
||||
def get_preference(key, sub_key = nil)
|
||||
value = preferences[key]
|
||||
if value == EXTERNAL
|
||||
|
@ -122,9 +94,6 @@ class UserPreferenceValue < ActiveRecord::Base
|
|||
end
|
||||
raise "invalid key `#{key}`" unless UserPreferenceValue.settings[key]
|
||||
|
||||
# don't bother trying to merge things in - just move everything over
|
||||
migrate_preferences_if_needed
|
||||
|
||||
if value.present? || sub_key
|
||||
if value.nil?
|
||||
remove_user_preference_value(key, sub_key)
|
||||
|
|
|
@ -30,7 +30,7 @@ class ValidateMigrationIntegrity < ActiveRecord::Migration[4.2]
|
|||
|
||||
def self.up
|
||||
initial_migration_version = "20101210192618"
|
||||
last_squashed_migration_version = "20191031154616"
|
||||
last_squashed_migration_version = "20200227143541"
|
||||
|
||||
versions = if $canvas_rails == "7.1"
|
||||
ActiveRecord::SchemaMigration.new(ActiveRecord::Base.connection).versions
|
|
@ -682,6 +682,11 @@ class InitCanvasDb < ActiveRecord::Migration[4.2]
|
|||
add_index :attachments,
|
||||
%i[md5 namespace content_type],
|
||||
where: "root_attachment_id IS NULL and filename IS NOT NULL"
|
||||
add_index :attachments,
|
||||
%i[context_id context_type migration_id],
|
||||
opclass: { migration_id: :text_pattern_ops },
|
||||
where: "migration_id IS NOT NULL",
|
||||
name: "index_attachments_on_context_and_migration_id_pattern_ops"
|
||||
|
||||
create_table "calendar_events", force: true do |t|
|
||||
t.string "title", limit: 255
|
||||
|
@ -870,6 +875,7 @@ class InitCanvasDb < ActiveRecord::Migration[4.2]
|
|||
add_index :content_exports, :attachment_id
|
||||
add_index :content_exports, :content_migration_id
|
||||
add_index :content_exports, :user_id, where: "user_id IS NOT NULL"
|
||||
add_index :content_exports, [:context_id, :context_type]
|
||||
|
||||
create_table "content_migrations", force: true do |t|
|
||||
t.integer "context_id", limit: 8, null: false
|
||||
|
@ -961,6 +967,7 @@ class InitCanvasDb < ActiveRecord::Migration[4.2]
|
|||
t.integer "associated_asset_id", limit: 8
|
||||
t.string "associated_asset_type", limit: 255
|
||||
t.boolean "new_tab"
|
||||
t.jsonb :link_settings
|
||||
end
|
||||
|
||||
add_index "content_tags", ["content_id", "content_type"], name: "index_content_tags_on_content_id_and_content_type"
|
||||
|
@ -1383,6 +1390,7 @@ class InitCanvasDb < ActiveRecord::Migration[4.2]
|
|||
t.text :oidc_initiation_url
|
||||
t.string :public_jwk_url
|
||||
t.boolean :is_lti_key, default: false, null: false
|
||||
t.boolean :allow_includes, default: false, null: false
|
||||
end
|
||||
add_index :developer_keys, :vendor_code
|
||||
|
||||
|
@ -2077,6 +2085,7 @@ class InitCanvasDb < ActiveRecord::Migration[4.2]
|
|||
t.datetime "submitted_at"
|
||||
t.boolean :hide_points, default: false, null: false
|
||||
t.boolean :hidden, default: false, null: false
|
||||
t.string :user_uuid, limit: 255
|
||||
end
|
||||
|
||||
add_index :learning_outcome_results,
|
||||
|
@ -2328,6 +2337,10 @@ class InitCanvasDb < ActiveRecord::Migration[4.2]
|
|||
name: "index_child_content_tags_on_content"
|
||||
add_index :master_courses_child_content_tags, :child_subscription_id, name: "index_child_content_tags_on_subscription"
|
||||
add_index :master_courses_child_content_tags, :migration_id, name: "index_child_content_tags_on_migration_id"
|
||||
add_index :master_courses_child_content_tags,
|
||||
[:child_subscription_id, :migration_id],
|
||||
opclass: { migration_id: :text_pattern_ops },
|
||||
name: "index_mc_child_content_tags_on_sub_and_migration_id_pattern_ops"
|
||||
|
||||
create_table :master_courses_child_subscriptions do |t|
|
||||
t.integer :master_template_id, limit: 8, null: false
|
||||
|
@ -2586,6 +2599,33 @@ class InitCanvasDb < ActiveRecord::Migration[4.2]
|
|||
add_index :notification_endpoints, :access_token_id
|
||||
add_index :notification_endpoints, :workflow_state
|
||||
|
||||
create_table :notification_policy_overrides do |t|
|
||||
t.belongs_to :context,
|
||||
polymorphic: { default: "Course" },
|
||||
null: false,
|
||||
index: { name: "index_notification_policy_overrides_on_context" },
|
||||
limit: 8
|
||||
t.belongs_to :communication_channel, null: false, foreign_key: true, limit: 8, index: true
|
||||
t.integer :notification_id, limit: 8
|
||||
t.string :workflow_state, default: "active", null: false, index: true
|
||||
t.string :frequency
|
||||
t.timestamps null: false
|
||||
end
|
||||
add_index :notification_policy_overrides, :notification_id
|
||||
add_index :notification_policy_overrides,
|
||||
%i[communication_channel_id notification_id],
|
||||
name: "index_notification_policies_overrides_on_cc_id_and_notification"
|
||||
add_index :notification_policy_overrides,
|
||||
%i[context_id context_type communication_channel_id notification_id],
|
||||
where: "notification_id IS NOT NULL",
|
||||
unique: true,
|
||||
name: "index_notification_policies_overrides_uniq_context_notification"
|
||||
add_index :notification_policy_overrides,
|
||||
%i[context_id context_type communication_channel_id],
|
||||
where: "notification_id IS NULL",
|
||||
unique: true,
|
||||
name: "index_notification_policies_overrides_uniq_context_and_cc"
|
||||
|
||||
create_table "notification_policies", force: true do |t|
|
||||
t.integer "notification_id", limit: 8
|
||||
t.integer "communication_channel_id", limit: 8, null: false
|
||||
|
@ -3584,6 +3624,7 @@ class InitCanvasDb < ActiveRecord::Migration[4.2]
|
|||
t.integer :extra_attempts
|
||||
t.datetime :posted_at
|
||||
t.boolean :cached_quiz_lti, default: false, null: false
|
||||
t.string :cached_tardiness, limit: 16
|
||||
end
|
||||
|
||||
add_index "submissions", ["assignment_id", "submission_type"], name: "index_submissions_on_assignment_id_and_submission_type"
|
||||
|
@ -3628,6 +3669,10 @@ class InitCanvasDb < ActiveRecord::Migration[4.2]
|
|||
:user_id,
|
||||
where: "(score IS NOT NULL AND workflow_state = 'graded') OR excused = TRUE",
|
||||
name: "index_submissions_graded_or_excused_on_user_id"
|
||||
add_index :submissions,
|
||||
:assignment_id,
|
||||
where: "workflow_state <> 'deleted' AND ((score IS NOT NULL AND workflow_state = 'graded') OR excused = TRUE)",
|
||||
name: "index_submissions_graded_or_excused_on_assignment_id"
|
||||
|
||||
# rubocop:disable Rails/SquishedSQLHeredocs
|
||||
execute(<<~SQL)
|
||||
|
@ -3826,6 +3871,14 @@ class InitCanvasDb < ActiveRecord::Migration[4.2]
|
|||
add_index :user_past_lti_ids, :user_id
|
||||
add_index :user_past_lti_ids, :user_uuid
|
||||
|
||||
create_table :user_preference_values do |t|
|
||||
t.integer :user_id, limit: 8, null: false
|
||||
t.string :key, null: false
|
||||
t.string :sub_key
|
||||
t.text :value
|
||||
end
|
||||
add_index :user_preference_values, %i[user_id key sub_key], unique: true, name: "index_user_preference_values_on_keys"
|
||||
|
||||
create_table "user_services", force: true do |t|
|
||||
t.integer "user_id", limit: 8, null: false
|
||||
t.text "token"
|
||||
|
@ -4440,6 +4493,7 @@ class InitCanvasDb < ActiveRecord::Migration[4.2]
|
|||
add_foreign_key :moderation_graders, :users
|
||||
add_foreign_key :notification_endpoints, :access_tokens
|
||||
add_foreign_key :notification_policies, :communication_channels
|
||||
add_foreign_key :notification_policy_overrides, :notifications
|
||||
add_foreign_key :oauth_requests, :users
|
||||
add_foreign_key :observer_alert_thresholds, :users
|
||||
add_foreign_key :observer_alert_thresholds, :users, column: :observer_id
|
||||
|
@ -4536,6 +4590,7 @@ class InitCanvasDb < ActiveRecord::Migration[4.2]
|
|||
add_foreign_key :user_observers, :users
|
||||
add_foreign_key :user_observers, :users, column: :observer_id
|
||||
add_foreign_key :user_past_lti_ids, :users
|
||||
add_foreign_key :user_preference_values, :users
|
||||
add_foreign_key :user_profile_links, :user_profiles
|
||||
add_foreign_key :user_profiles, :users
|
||||
add_foreign_key :user_services, :users
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
#
|
||||
# Copyright (C) 2019 - present Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
class AddAllowIncludeParamsToDeveloperKey < ActiveRecord::Migration[5.2]
|
||||
tag :predeploy
|
||||
|
||||
def change
|
||||
add_column :developer_keys, :allow_includes, :boolean
|
||||
change_column_default(:developer_keys, :allow_includes, false)
|
||||
DataFixup::BackfillNulls.run(DeveloperKey, :allow_includes, default_value: false)
|
||||
change_column_null(:developer_keys, :allow_includes, false)
|
||||
end
|
||||
end
|
|
@ -1,26 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
#
|
||||
# Copyright (C) 2020 - present Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
class AddContextIndexToContentExports < ActiveRecord::Migration[5.2]
|
||||
tag :postdeploy
|
||||
disable_ddl_transaction!
|
||||
|
||||
def change
|
||||
add_index :content_exports, [:context_id, :context_type], algorithm: :concurrently
|
||||
end
|
||||
end
|
|
@ -1,29 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
#
|
||||
# Copyright (C) 2020 - present Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
class GranularWikiPagePermissions < ActiveRecord::Migration[5.2]
|
||||
tag :postdeploy
|
||||
|
||||
def up
|
||||
# Since the old permission has been removed, skip_validation to support users with slower deploy cycles
|
||||
DataFixup::AddRoleOverridesForNewPermission.run(:manage_wiki, :manage_wiki_create, skip_validation: true)
|
||||
DataFixup::AddRoleOverridesForNewPermission.run(:manage_wiki, :manage_wiki_delete, skip_validation: true)
|
||||
DataFixup::AddRoleOverridesForNewPermission.run(:manage_wiki, :manage_wiki_update, skip_validation: true)
|
||||
end
|
||||
end
|
|
@ -1,51 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
#
|
||||
# Copyright (C) 2020 - present Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
class CreateNotificationPolicyOverrides < ActiveRecord::Migration[5.2]
|
||||
tag :predeploy
|
||||
|
||||
def change
|
||||
create_table :notification_policy_overrides do |t|
|
||||
t.belongs_to :context,
|
||||
polymorphic: { default: "Course" },
|
||||
null: false,
|
||||
index: { name: "index_notification_policy_overrides_on_context" }
|
||||
t.belongs_to :communication_channel, null: false, foreign_key: true
|
||||
t.belongs_to :notification, index: true
|
||||
t.string :workflow_state, default: "active", null: false, index: true
|
||||
t.string :frequency
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
add_index :notification_policy_overrides,
|
||||
%i[communication_channel_id notification_id],
|
||||
name: "index_notification_policies_overrides_on_cc_id_and_notification"
|
||||
add_index :notification_policy_overrides,
|
||||
%i[context_id context_type communication_channel_id notification_id],
|
||||
where: "notification_id IS NOT NULL",
|
||||
unique: true,
|
||||
name: "index_notification_policies_overrides_uniq_context_notification"
|
||||
add_index :notification_policy_overrides,
|
||||
%i[context_id context_type communication_channel_id],
|
||||
where: "notification_id IS NULL",
|
||||
unique: true,
|
||||
name: "index_notification_policies_overrides_uniq_context_and_cc"
|
||||
end
|
||||
end
|
|
@ -1,20 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddBlueprintDeletionIndexes < ActiveRecord::Migration[5.2]
|
||||
tag :postdeploy
|
||||
disable_ddl_transaction!
|
||||
|
||||
def change
|
||||
add_index :attachments,
|
||||
%i[context_id context_type migration_id],
|
||||
opclass: { migration_id: :text_pattern_ops },
|
||||
where: "migration_id IS NOT NULL",
|
||||
algorithm: :concurrently,
|
||||
name: "index_attachments_on_context_and_migration_id_pattern_ops"
|
||||
add_index :master_courses_child_content_tags,
|
||||
[:child_subscription_id, :migration_id],
|
||||
opclass: { migration_id: :text_pattern_ops },
|
||||
algorithm: :concurrently,
|
||||
name: "index_mc_child_content_tags_on_sub_and_migration_id_pattern_ops"
|
||||
end
|
||||
end
|
|
@ -1,25 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
#
|
||||
# Copyright (C) 2020 - present Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
class AddLinkSettingsToContentTag < ActiveRecord::Migration[5.2]
|
||||
tag :predeploy
|
||||
|
||||
def change
|
||||
add_column :content_tags, :link_settings, :jsonb
|
||||
end
|
||||
end
|
|
@ -1,38 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
#
|
||||
# Copyright (C) 2020 - present Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
class CreateUserPreferenceValues < ActiveRecord::Migration[5.2]
|
||||
tag :predeploy
|
||||
|
||||
def up
|
||||
create_table :user_preference_values do |t|
|
||||
t.integer :user_id, limit: 8, null: false
|
||||
t.string :key, null: false
|
||||
t.string :sub_key
|
||||
t.text :value
|
||||
end
|
||||
|
||||
add_foreign_key :user_preference_values, :users
|
||||
add_index :user_preference_values, %i[user_id key sub_key], unique: true, name: "index_user_preference_values_on_keys"
|
||||
end
|
||||
|
||||
def down
|
||||
drop_table :user_preference_values
|
||||
end
|
||||
end
|
|
@ -1,25 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
#
|
||||
# Copyright (C) 2020 - present Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
class AddUserUuidToLearningOutcomeResults < ActiveRecord::Migration[5.2]
|
||||
tag :predeploy
|
||||
|
||||
def change
|
||||
add_column :learning_outcome_results, :user_uuid, :string, limit: 255
|
||||
end
|
||||
end
|
|
@ -1,18 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class SplitUpUserPreferences < ActiveRecord::Migration[5.2]
|
||||
tag :postdeploy
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
User.find_ids_in_ranges(batch_size: 20_000) do |min_id, max_id|
|
||||
DataFixup::SplitUpUserPreferences
|
||||
.delay_if_production(priority: Delayed::LOW_PRIORITY, n_strand: ["user_preference_migration", Shard.current.database_server.id])
|
||||
.run(min_id, max_id)
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
|
@ -1,26 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
#
|
||||
# Copyright (C) 2020 - present Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
class AddCachedTardinessToSubmissions < ActiveRecord::Migration[5.2]
|
||||
tag :predeploy
|
||||
|
||||
def change
|
||||
add_column :submissions, :cached_tardiness, :string, limit: 16
|
||||
end
|
||||
end
|
|
@ -1,31 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
#
|
||||
# Copyright (C) 2020 - present Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
class AddGradedOrExcusedIndexToSubmissions < ActiveRecord::Migration[5.2]
|
||||
tag :postdeploy
|
||||
disable_ddl_transaction!
|
||||
|
||||
def change
|
||||
add_index :submissions,
|
||||
:assignment_id,
|
||||
algorithm: :concurrently,
|
||||
where: "workflow_state <> 'deleted' AND ((score IS NOT NULL AND workflow_state = 'graded') OR excused = TRUE)",
|
||||
name: "index_submissions_graded_or_excused_on_assignment_id"
|
||||
end
|
||||
end
|
|
@ -1,31 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
#
|
||||
# Copyright (C) 2020 - present Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
module DataFixup::SplitUpUserPreferences
|
||||
def self.run(start_at, end_at)
|
||||
User.find_ids_in_ranges(start_at:, end_at:) do |min_id, max_id|
|
||||
User.where(id: min_id..max_id).where("id < ? AND preferences IS NOT NULL", Shard::IDS_PER_SHARD).each do |u|
|
||||
if u.needs_preference_migration?
|
||||
u.migrate_preferences_if_needed
|
||||
User.where(id: u).update_all(preferences: u.preferences, updated_at: Time.now.utc)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -69,12 +69,8 @@ class UserMerge
|
|||
merge_data.items.create!(user: from_user, item_type: "user_preferences", item: from_user.preferences)
|
||||
merge_data.items.create!(user: target_user, item_type: "user_preferences", item: target_user.preferences)
|
||||
|
||||
if from_user.needs_preference_migration?
|
||||
prefs = shard_aware_preferences
|
||||
else
|
||||
copy_migrated_preferences # uses new rows to store preferences
|
||||
prefs = from_user.preferences
|
||||
end
|
||||
copy_migrated_preferences # uses new rows to store preferences
|
||||
prefs = from_user.preferences
|
||||
target_user.preferences = target_user.preferences.merge(prefs)
|
||||
target_user.save if target_user.changed?
|
||||
|
||||
|
@ -225,25 +221,7 @@ class UserMerge
|
|||
key.is_a?(String) ? [key.split("_").first, new_id].join("_") : new_id
|
||||
end
|
||||
|
||||
# can remove when all preferences have been migrated
|
||||
def shard_aware_preferences
|
||||
return from_user.preferences if from_user.shard == target_user.shard
|
||||
|
||||
preferences = from_user.preferences.dup
|
||||
%i[custom_colors course_nicknames].each do |pref|
|
||||
preferences.delete(pref)
|
||||
new_pref = {}
|
||||
from_user.preferences[pref]&.each do |key, value|
|
||||
new_key = translate_course_id_or_asset_string(key)
|
||||
new_pref[new_key] = value
|
||||
end
|
||||
preferences[pref] = new_pref unless new_pref.empty?
|
||||
end
|
||||
preferences
|
||||
end
|
||||
|
||||
def copy_migrated_preferences
|
||||
target_user.migrate_preferences_if_needed # may as well
|
||||
from_values = from_user.user_preference_values.to_a
|
||||
target_values = target_user.user_preference_values.to_a.index_by { |r| [r.key, r.sub_key] }
|
||||
|
||||
|
@ -255,7 +233,6 @@ class UserMerge
|
|||
sub_key = from_record.sub_key
|
||||
value = from_record.value
|
||||
if from_user.shard != target_user.shard
|
||||
# tl;dr do the same thing as shard_aware_preferences
|
||||
case key
|
||||
when "custom_colors"
|
||||
value = value.transform_keys { |id| translate_course_id_or_asset_string(id) }
|
||||
|
|
|
@ -963,22 +963,7 @@ describe UserMerge do
|
|||
end
|
||||
end
|
||||
|
||||
it "moves prefs over with old format" do
|
||||
@shard1.activate do
|
||||
@user2 = user_model
|
||||
account = Account.create!
|
||||
@shard_course = course_factory(account:)
|
||||
@user2.preferences[:custom_colors] = { "course_#{@course.id}" => "#254284" }
|
||||
end
|
||||
course = course_factory
|
||||
user1 = user_model
|
||||
@user2.preferences[:custom_colors]["course_#{course.global_id}"] = "#346543"
|
||||
@user2.save!
|
||||
UserMerge.from(@user2).into(user1)
|
||||
expect(user1.reload.preferences[:custom_colors].keys).to eq ["course_#{@shard_course.global_id}", "course_#{course.id}"]
|
||||
end
|
||||
|
||||
it "moves prefs over with new format" do
|
||||
it "moves prefs over" do
|
||||
@shard1.activate do
|
||||
@user2 = user_model
|
||||
account = Account.create!
|
||||
|
@ -994,22 +979,7 @@ describe UserMerge do
|
|||
)
|
||||
end
|
||||
|
||||
it "moves nicknames with old format" do
|
||||
@shard1.activate do
|
||||
@user2 = user_model
|
||||
account = Account.create!
|
||||
@shard_course = course_factory(account:)
|
||||
@user2.preferences[:course_nicknames] = { @shard_course.id => "Marketing" }
|
||||
end
|
||||
course = course_factory
|
||||
user1 = user_model
|
||||
@user2.preferences[:course_nicknames][course.global_id] = "Math"
|
||||
@user2.save!
|
||||
UserMerge.from(@user2).into(user1)
|
||||
expect(user1.reload.preferences[:course_nicknames].keys).to eq [@shard_course.global_id, course.id]
|
||||
end
|
||||
|
||||
it "moves nicknames with new format" do
|
||||
it "moves nicknames" do
|
||||
@shard1.activate do
|
||||
@user2 = user_model
|
||||
account = Account.create!
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
#
|
||||
# Copyright (C) 2020 - present Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
require_relative "../spec_helper"
|
||||
|
||||
describe DataFixup::SplitUpUserPreferences do
|
||||
it "works" do
|
||||
u = User.create!
|
||||
original_prefs = { selected_calendar_contexts: ["course_1000"], course_nicknames: { 2 => "Why am i taking this course" }, some_other_thing: true }
|
||||
User.where(id: u).update_all(preferences: original_prefs)
|
||||
DataFixup::SplitUpUserPreferences.run(nil, nil)
|
||||
u.reload
|
||||
expect(u.reload.needs_preference_migration?).to be false
|
||||
rows = u.user_preference_values.to_a.index_by { |v| [v.key, v.sub_key] }
|
||||
expect(rows.count).to eq 2
|
||||
expect(rows[["selected_calendar_contexts", nil]].value).to eq ["course_1000"]
|
||||
expect(rows[["course_nicknames", 2]].value).to eq "Why am i taking this course"
|
||||
|
||||
expect(u.preferences).to eq(
|
||||
{
|
||||
selected_calendar_contexts: UserPreferenceValue::EXTERNAL,
|
||||
course_nicknames: UserPreferenceValue::EXTERNAL,
|
||||
some_other_thing: true
|
||||
}
|
||||
)
|
||||
expect(u.get_preference(:selected_calendar_contexts)).to eq ["course_1000"]
|
||||
expect(u.get_preference(:course_nicknames, 2)).to eq "Why am i taking this course"
|
||||
end
|
||||
end
|
|
@ -22,18 +22,11 @@ describe UserPreferenceValue do
|
|||
let(:regular_key) { :custom_colors }
|
||||
let(:subbed_key) { :course_nicknames }
|
||||
|
||||
let(:sample_preferences) do
|
||||
{ regular_key => [:arbitrary_data], subbed_key => { a: 1, b: [:other_stuff] } }
|
||||
end
|
||||
|
||||
let(:preexisting_user) do
|
||||
User.create!(preferences: sample_preferences)
|
||||
end
|
||||
|
||||
let(:migrated_user) do
|
||||
u = User.create!(preferences: sample_preferences)
|
||||
u.migrate_preferences_if_needed
|
||||
u.save!
|
||||
u = User.create!
|
||||
u.set_preference(regular_key, [:arbitrary_data])
|
||||
u.set_preference(subbed_key, :a, 1)
|
||||
u.set_preference(subbed_key, :b, [:other_stuff])
|
||||
u
|
||||
end
|
||||
|
||||
|
@ -59,30 +52,6 @@ describe UserPreferenceValue do
|
|||
expect(migrated_user.get_preference(subbed_key, :a)).to eq "more new data"
|
||||
end
|
||||
|
||||
it "uses the existing data if the user's preferences hasn't been migrated yet" do
|
||||
expect(preexisting_user.preferences[regular_key]).to eq sample_preferences[regular_key]
|
||||
expect(preexisting_user.preferences[subbed_key]).to eq sample_preferences[subbed_key]
|
||||
end
|
||||
|
||||
it "does not migrate all existing preferences automatically on save unless to a migrated preference" do
|
||||
expect(preexisting_user.needs_preference_migration?).to be true
|
||||
preexisting_user.save!
|
||||
|
||||
expect(preexisting_user.reload.needs_preference_migration?).to be true
|
||||
preexisting_user.set_preference(regular_key, "new_value")
|
||||
expect(preexisting_user.reload.needs_preference_migration?).to be false
|
||||
|
||||
rows = preexisting_user.user_preference_values.to_a.index_by { |v| [v.key, v.sub_key] }
|
||||
expect(rows.count).to eq 3
|
||||
expect(rows[[regular_key.to_s, nil]].value).to eq "new_value"
|
||||
expect(rows[[subbed_key.to_s, "a"]].value).to eq sample_preferences[subbed_key][:a]
|
||||
expect(rows[[subbed_key.to_s, "b"]].value).to eq sample_preferences[subbed_key][:b]
|
||||
|
||||
expect(preexisting_user.preferences).to eq(
|
||||
{ regular_key => UserPreferenceValue::EXTERNAL, subbed_key => UserPreferenceValue::EXTERNAL }
|
||||
)
|
||||
end
|
||||
|
||||
it "does not query for preferences when saving an unrelated attribute on an already migrated user" do
|
||||
expect(migrated_user).to_not receive(:user_preference_values)
|
||||
migrated_user.update_attribute(:name, "name1")
|
||||
|
@ -115,76 +84,4 @@ describe UserPreferenceValue do
|
|||
expect(migrated_user.user_preference_values.where(key: subbed_key).pluck(:sub_key)).to eq(["a"])
|
||||
expect(migrated_user.preferences[subbed_key]).to eq(UserPreferenceValue::EXTERNAL)
|
||||
end
|
||||
|
||||
context "gradebook_column_size" do
|
||||
specs_require_sharding
|
||||
|
||||
let(:course1) { Course.create! }
|
||||
let(:course2) { Course.create! }
|
||||
let(:assignment1) { course1.assignments.create! }
|
||||
let(:assignment2) { course2.assignments.create! }
|
||||
let(:assignment_group1) { course1.assignment_groups.create! }
|
||||
let(:assignment_group2) { course2.assignment_groups.create! }
|
||||
let(:column1) { course1.custom_gradebook_columns.create!(title: "1") }
|
||||
let(:column2) { course2.custom_gradebook_columns.create!(title: "2") }
|
||||
|
||||
let(:old_format) do
|
||||
{
|
||||
"student" => "100",
|
||||
"assignment_#{assignment1.id}" => "10",
|
||||
"assignment_#{assignment2.id}" => "20",
|
||||
"assignment_group_#{assignment_group1.id}" => "30",
|
||||
"assignment_group_#{assignment_group2.id}" => "40",
|
||||
"custom_col_#{column1.id}" => "50",
|
||||
"custom_col_#{column2.id}" => "60"
|
||||
}
|
||||
end
|
||||
|
||||
it "splits the old gradebook column size preference by course" do
|
||||
u = User.create!
|
||||
User.where(id: u).update_all(preferences: { gradebook_column_size: old_format })
|
||||
u.reload
|
||||
u.migrate_preferences_if_needed
|
||||
u.save!
|
||||
expect(u.get_preference(:gradebook_column_size, "shared")).to eq old_format.slice("student")
|
||||
expect(u.get_preference(:gradebook_column_size, course1.global_id)).to eq old_format.slice(
|
||||
"assignment_#{assignment1.id}", "assignment_group_#{assignment_group1.id}", "custom_col_#{column1.id}"
|
||||
)
|
||||
expect(u.get_preference(:gradebook_column_size, course2.global_id)).to eq old_format.slice(
|
||||
"assignment_#{assignment2.id}", "assignment_group_#{assignment_group2.id}", "custom_col_#{column2.id}"
|
||||
)
|
||||
end
|
||||
|
||||
it "does not attempt to re-migrate when a new non-migrated preference value appears" do
|
||||
u = User.create!
|
||||
User.where(id: u).update_all(preferences: { closed_notifications: [], gradebook_column_size: old_format })
|
||||
u.reload
|
||||
u.migrate_preferences_if_needed
|
||||
u.save!
|
||||
u.preferences[:closed_notifications] << 123
|
||||
expect(u.needs_preference_migration?).to be true
|
||||
expect { u.migrate_preferences_if_needed }.not_to raise_error
|
||||
expect(u.user_preference_values.where(key: "closed_notifications").take.value).to eq [123]
|
||||
end
|
||||
|
||||
it "works even if the objects are from a different shard than the user" do
|
||||
old_format # instantiate on default shard
|
||||
@shard1.activate do
|
||||
u = User.create!
|
||||
u.associate_with_shard(Shard.default)
|
||||
User.where(id: u).update_all(preferences: { gradebook_column_size: old_format })
|
||||
u.reload
|
||||
u.migrate_preferences_if_needed
|
||||
u.save!
|
||||
expect(u.get_preference(:gradebook_column_size, "shared")).to eq old_format.slice("student")
|
||||
# save the subkey as a global but the columns with local ids since we'll only ever access them from their own shard
|
||||
expect(u.get_preference(:gradebook_column_size, course1.global_id)).to eq old_format.slice(
|
||||
"assignment_#{assignment1.local_id}", "assignment_group_#{assignment_group1.local_id}", "custom_col_#{column1.local_id}"
|
||||
)
|
||||
expect(u.get_preference(:gradebook_column_size, course2.global_id)).to eq old_format.slice(
|
||||
"assignment_#{assignment2.local_id}", "assignment_group_#{assignment_group2.local_id}", "custom_col_#{column2.local_id}"
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue