Skip to content

Commit

Permalink
create Lti::RegistrationAccountBindings model
Browse files Browse the repository at this point in the history
why:
* For the LIME project, we decided to rework the current data model for
  storing LTI related data. The current system is quite old and has
  accumulated a lot of tech debt from little patches over the years, so
  we hope to refine and simplify the data model as much as is reasonably
  possible.

closes INTEROP-8500
flag=none

test plan:
* in a rails console, get an Account `a`, a User `u`, and an
Lti::Registration `lr`
* create a new RAB (Lti::RegistrationAccountBinding):
```
Lti::RegistrationAccountBinding.create! account: a,
lti_registration: lr, created_by: u , updated_by: u
```
* the created RAB should have a workflow_state of "off"
* check out the associated MRA commit
* get a cross-shard User `xu`, like `User.find("2~1")`
* bonus points if that user hasn't already been associated
to something on shard 1
* update the RAB's updated_by to point to that user:
```
rab.updated_by = xu
rab.save!
```
* that should succeed and `rab.updated_by` should correctly
reference that cross-shard user
* create another RAB with a cross-shard user for both
created_by and updated_by - it should succeed

Change-Id: I750a725ec0c82fa08de3922c76c855b0a0618116
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/345691
Migration-Review: Cody Cutrer <cody@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Ryan Hawkins <ryan.hawkins@instructure.com>
QA-Review: Ryan Hawkins <ryan.hawkins@instructure.com>
Product-Review: Xander Moffatt <xmoffatt@instructure.com>
  • Loading branch information
xandroxygen committed Apr 23, 2024
1 parent 5ed2bfc commit c6cddcd
Show file tree
Hide file tree
Showing 10 changed files with 148 additions and 0 deletions.
1 change: 1 addition & 0 deletions app/models/account.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class Account < ActiveRecord::Base
has_many :active_folders, -> { where("folder.workflow_state<>'deleted'").order("folders.name") }, class_name: "Folder", as: :context, inverse_of: :context
has_many :developer_keys
has_many :developer_key_account_bindings, inverse_of: :account, dependent: :destroy
has_many :lti_registration_account_bindings, class_name: "Lti::RegistrationAccountBinding", inverse_of: :account, dependent: :destroy
has_many :authentication_providers,
-> { ordered },
inverse_of: :account,
Expand Down
1 change: 1 addition & 0 deletions app/models/developer_key_account_binding.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class DeveloperKeyAccountBinding < ApplicationRecord
belongs_to :account
belongs_to :developer_key
belongs_to :root_account, class_name: "Account"
has_one :lti_registration_account_binding, class_name: "Lti::RegistrationAccountBinding", inverse_of: :developer_key_account_binding

validates :account, :developer_key, presence: true

Expand Down
1 change: 1 addition & 0 deletions app/models/lti/registration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class Lti::Registration < ActiveRecord::Base
belongs_to :updated_by, class_name: "User", inverse_of: :updated_lti_registrations, optional: false
has_one :ims_registration, class_name: "Lti::IMS::Registration", inverse_of: :lti_registration, foreign_key: :lti_registration_id
has_one :developer_key, inverse_of: :lti_registration, foreign_key: :lti_registration_id
has_many :lti_registration_account_bindings, class_name: "Lti::RegistrationAccountBinding", dependent: :destroy, inverse_of: :registration

validates :name, :admin_nickname, :vendor, length: { maximum: 255 }
validates :name, presence: true
Expand Down
38 changes: 38 additions & 0 deletions app/models/lti/registration_account_binding.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# frozen_string_literal: true

#
# Copyright (C) 2024 - 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 Lti::RegistrationAccountBinding < ActiveRecord::Base
extend RootAccountResolver

include Workflow
workflow do
state :off
state :on
state :allow
end

belongs_to :account, inverse_of: :lti_registration_account_bindings, optional: false
belongs_to :registration, class_name: "Lti::Registration", inverse_of: :lti_registration_account_bindings, optional: false
belongs_to :root_account, class_name: "Account"
belongs_to :created_by, class_name: "User", inverse_of: :created_lti_registration_account_bindings
belongs_to :updated_by, class_name: "User", inverse_of: :updated_lti_registration_account_bindings
belongs_to :developer_key_account_binding, inverse_of: :lti_registration_account_binding

resolves_root_account through: :account
end
8 changes: 8 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,14 @@ def self.enrollment_conditions(state)
inverse_of: :user
has_many :created_lti_registrations, class_name: "Lti::Registration", foreign_key: "created_by_id", inverse_of: :created_by
has_many :updated_lti_registrations, class_name: "Lti::Registration", foreign_key: "updated_by_id", inverse_of: :updated_by
has_many :created_lti_registration_account_bindings,
class_name: "Lti::RegistrationAccountBinding",
foreign_key: :created_by_id,
inverse_of: :created_by
has_many :updated_lti_registration_account_bindings,
class_name: "Lti::RegistrationAccountBinding",
foreign_key: :updated_by_id,
inverse_of: :updated_by

has_many :comment_bank_items, -> { where("workflow_state<>'deleted'") }
has_many :microsoft_sync_partial_sync_changes, class_name: "MicrosoftSync::PartialSyncChange", dependent: :destroy, inverse_of: :user
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# frozen_string_literal: true

#
# Copyright (C) 2024 - 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 CreateLtiRegistrationAccountBindings < ActiveRecord::Migration[7.0]
tag :predeploy

def change
create_table :lti_registration_account_bindings do |t|
t.belongs_to :registration, null: false, foreign_key: { to_table: :lti_registrations }
t.belongs_to :account, null: false, foreign_key: true
t.belongs_to :created_by, foreign_key: { to_table: :users }
t.belongs_to :updated_by, foreign_key: { to_table: :users }
t.string :workflow_state, null: false, default: "off"

t.references :root_account, foreign_key: { to_table: :accounts }, index: false, null: false
t.references :developer_key_account_binding, foreign_key: true, index: { name: "index_lrab_on_developer_key_account_binding_id" }
t.replica_identity_index
t.timestamps

t.index %i[account_id registration_id], name: "index_lti_reg_bindings_on_account_id_and_registration_id", unique: true
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

#
# Copyright (C) 2024 - 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 AddReplicaIdentityToLtiRegistrationAccountBindings < ActiveRecord::Migration[7.0]
tag :predeploy

def up
set_replica_identity :lti_registration_account_bindings
end

def down
set_replica_identity :lti_registration_account_bindings, :default
end
end
1 change: 1 addition & 0 deletions spec/models/account_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
it { is_expected.to have_one(:outcome_proficiency).dependent(:destroy) }
it { is_expected.to have_many(:lti_resource_links).class_name("Lti::ResourceLink") }
it { is_expected.to have_many(:lti_registrations).class_name("Lti::Registration").dependent(:destroy) }
it { is_expected.to have_many(:lti_registration_account_bindings).class_name("Lti::RegistrationAccountBinding").dependent(:destroy) }
end

describe "validations" do
Expand Down
28 changes: 28 additions & 0 deletions spec/models/lti/registration_account_binding_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# frozen_string_literal: true

#
# Copyright (C) 2024 - 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/>.

RSpec.describe Lti::RegistrationAccountBinding do
describe "validations" do
it { is_expected.to belong_to(:registration).class_name("Lti::Registration").optional(false).inverse_of(:lti_registration_account_bindings) }
it { is_expected.to belong_to(:account).class_name("Account").optional(false).inverse_of(:lti_registration_account_bindings) }
it { is_expected.to belong_to(:created_by).class_name("User").inverse_of(:created_lti_registration_account_bindings) }
it { is_expected.to belong_to(:updated_by).class_name("User").inverse_of(:updated_lti_registration_account_bindings) }
it { is_expected.to belong_to(:developer_key_account_binding).class_name("DeveloperKeyAccountBinding") }
end
end
1 change: 1 addition & 0 deletions spec/models/lti/registration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@
it { is_expected.to have_one(:developer_key).class_name("DeveloperKey").inverse_of(:lti_registration).with_foreign_key(:lti_registration_id) }
it { is_expected.to belong_to(:created_by).class_name("User").optional(false) }
it { is_expected.to belong_to(:updated_by).class_name("User").optional(false) }
it { is_expected.to have_many(:lti_registration_account_bindings).class_name("Lti::RegistrationAccountBinding").dependent(:destroy) }
end
end

0 comments on commit c6cddcd

Please sign in to comment.