Migrate database and models for study-group-based authorization
This commit is contained in:

committed by
Sebastian Serth

parent
ec4c6207f0
commit
04ed45ea73
@ -4,6 +4,7 @@ require 'securerandom'
|
||||
|
||||
class AuthenticationToken < ApplicationRecord
|
||||
include Creation
|
||||
belongs_to :study_group, optional: true
|
||||
|
||||
def self.generate!(user)
|
||||
create!(
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
class Consumer < ApplicationRecord
|
||||
has_many :users
|
||||
has_many :study_groups, dependent: :destroy
|
||||
|
||||
scope :with_internal_users, -> { where('id IN (SELECT DISTINCT consumer_id FROM internal_users)') }
|
||||
scope :with_external_users, -> { where('id IN (SELECT DISTINCT consumer_id FROM external_users)') }
|
||||
|
@ -6,6 +6,8 @@ class StudyGroup < ApplicationRecord
|
||||
has_many :internal_users, through: :study_group_memberships, source_type: 'InternalUser', source: :user
|
||||
has_many :submissions, dependent: :nullify
|
||||
has_many :remote_evaluation_mappings, dependent: :nullify
|
||||
has_many :subscriptions, dependent: :nullify
|
||||
has_many :authentication_tokens, dependent: :nullify
|
||||
belongs_to :consumer
|
||||
|
||||
def users
|
||||
|
@ -4,5 +4,11 @@ class StudyGroupMembership < ApplicationRecord
|
||||
belongs_to :user, polymorphic: true
|
||||
belongs_to :study_group
|
||||
|
||||
enum role: {
|
||||
learner: 0,
|
||||
teacher: 1,
|
||||
}, _default: :learner, _prefix: true
|
||||
|
||||
validates :role, presence: true
|
||||
validates :user_id, uniqueness: {scope: %i[user_type study_group_id]}
|
||||
end
|
||||
|
@ -3,4 +3,5 @@
|
||||
class Subscription < ApplicationRecord
|
||||
belongs_to :user, polymorphic: true
|
||||
belongs_to :request_for_comment
|
||||
belongs_to :study_group, optional: true
|
||||
end
|
||||
|
11
db/migrate/20220906142041_add_study_group_authorization.rb
Normal file
11
db/migrate/20220906142041_add_study_group_authorization.rb
Normal file
@ -0,0 +1,11 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class AddStudyGroupAuthorization < ActiveRecord::Migration[6.1]
|
||||
def change
|
||||
add_column :external_users, :platform_admin, :boolean, default: false, nil: false
|
||||
add_column :internal_users, :platform_admin, :boolean, default: false, nil: false
|
||||
add_column :study_group_memberships, :role, :integer, limit: 1, null: false, default: 0, comment: 'Used as enum in Rails'
|
||||
add_reference :subscriptions, :study_group, index: true, null: true, foreign_key: true
|
||||
add_reference :authentication_tokens, :study_group, index: true, null: true, foreign_key: true
|
||||
end
|
||||
end
|
@ -0,0 +1,39 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class MigratePermissionsToStudyGroup < ActiveRecord::Migration[6.1]
|
||||
# rubocop:disable Rails/SkipsModelValidations
|
||||
def up
|
||||
create_default_groups
|
||||
migrate_internal_users
|
||||
migrate_external_users
|
||||
end
|
||||
|
||||
def create_default_groups
|
||||
Consumer.find_each do |consumer|
|
||||
StudyGroup.find_or_create_by!(consumer: consumer, external_id: nil) do |new_group|
|
||||
new_group.name = "Default Study Group for #{consumer.name}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def migrate_internal_users
|
||||
# Internal users don't necessarily have a study group yet, which is needed for the teacher role
|
||||
InternalUser.find_each do |user|
|
||||
user.update_columns(platform_admin: true) if user.role == 'admin'
|
||||
|
||||
study_group = StudyGroup.find_by!(consumer: user.consumer, external_id: nil)
|
||||
|
||||
# All platform admins will "just" be a teacher in the study group
|
||||
new_role = %w[admin teacher].include?(user.role) ? :teacher : :learner
|
||||
membership = StudyGroupMembership.find_or_create_by!(study_group: study_group, user: user)
|
||||
membership.update_columns(role: new_role)
|
||||
end
|
||||
end
|
||||
|
||||
def migrate_external_users
|
||||
# All external users are (or will be) in a study group once launched through LTI
|
||||
# and therefore don't need a new StudyGroupMembership
|
||||
ExternalUser.where(role: 'admin').update(platform_admin: true)
|
||||
end
|
||||
# rubocop:enable Rails/SkipsModelValidations
|
||||
end
|
8
db/migrate/20220906142603_remove_role_from_users.rb
Normal file
8
db/migrate/20220906142603_remove_role_from_users.rb
Normal file
@ -0,0 +1,8 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class RemoveRoleFromUsers < ActiveRecord::Migration[6.1]
|
||||
def change
|
||||
remove_column :external_users, :role
|
||||
remove_column :internal_users, :role
|
||||
end
|
||||
end
|
13
db/schema.rb
13
db/schema.rb
@ -10,7 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2022_07_21_131946) do
|
||||
ActiveRecord::Schema.define(version: 2022_09_06_142603) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "pg_trgm"
|
||||
@ -37,7 +37,9 @@ ActiveRecord::Schema.define(version: 2022_07_21_131946) do
|
||||
t.datetime "expire_at", null: false
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.bigint "study_group_id"
|
||||
t.index ["shared_secret"], name: "index_authentication_tokens_on_shared_secret", unique: true
|
||||
t.index ["study_group_id"], name: "index_authentication_tokens_on_study_group_id"
|
||||
t.index ["user_type", "user_id"], name: "index_authentication_tokens_on_user"
|
||||
end
|
||||
|
||||
@ -238,7 +240,7 @@ ActiveRecord::Schema.define(version: 2022_07_21_131946) do
|
||||
t.string "name"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "role", default: "learner", null: false
|
||||
t.boolean "platform_admin", default: false
|
||||
end
|
||||
|
||||
create_table "file_templates", id: :serial, force: :cascade do |t|
|
||||
@ -288,7 +290,6 @@ ActiveRecord::Schema.define(version: 2022_07_21_131946) do
|
||||
t.integer "consumer_id"
|
||||
t.string "email"
|
||||
t.string "name"
|
||||
t.string "role"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "crypted_password"
|
||||
@ -304,6 +305,7 @@ ActiveRecord::Schema.define(version: 2022_07_21_131946) do
|
||||
t.string "activation_state"
|
||||
t.string "activation_token"
|
||||
t.datetime "activation_token_expires_at"
|
||||
t.boolean "platform_admin", default: false
|
||||
t.index ["activation_token"], name: "index_internal_users_on_activation_token"
|
||||
t.index ["email"], name: "index_internal_users_on_email", unique: true
|
||||
t.index ["remember_me_token"], name: "index_internal_users_on_remember_me_token"
|
||||
@ -429,6 +431,7 @@ ActiveRecord::Schema.define(version: 2022_07_21_131946) do
|
||||
t.bigint "study_group_id"
|
||||
t.string "user_type"
|
||||
t.bigint "user_id"
|
||||
t.integer "role", limit: 2, default: 0, null: false, comment: "Used as enum in Rails"
|
||||
t.index ["study_group_id"], name: "index_study_group_memberships_on_study_group_id"
|
||||
t.index ["user_type", "user_id"], name: "index_study_group_memberships_on_user"
|
||||
end
|
||||
@ -465,6 +468,8 @@ ActiveRecord::Schema.define(version: 2022_07_21_131946) do
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.boolean "deleted"
|
||||
t.bigint "study_group_id"
|
||||
t.index ["study_group_id"], name: "index_subscriptions_on_study_group_id"
|
||||
end
|
||||
|
||||
create_table "tags", id: :serial, force: :cascade do |t|
|
||||
@ -563,6 +568,7 @@ ActiveRecord::Schema.define(version: 2022_07_21_131946) do
|
||||
t.index ["user_type", "user_id"], name: "index_user_proxy_exercise_exercises_on_user"
|
||||
end
|
||||
|
||||
add_foreign_key "authentication_tokens", "study_groups"
|
||||
add_foreign_key "community_solution_contributions", "community_solution_locks"
|
||||
add_foreign_key "community_solution_contributions", "community_solutions"
|
||||
add_foreign_key "community_solution_contributions", "study_groups"
|
||||
@ -573,6 +579,7 @@ ActiveRecord::Schema.define(version: 2022_07_21_131946) do
|
||||
add_foreign_key "exercise_tips", "tips"
|
||||
add_foreign_key "remote_evaluation_mappings", "study_groups"
|
||||
add_foreign_key "submissions", "study_groups"
|
||||
add_foreign_key "subscriptions", "study_groups"
|
||||
add_foreign_key "testrun_execution_environments", "execution_environments"
|
||||
add_foreign_key "testrun_execution_environments", "testruns"
|
||||
add_foreign_key "testrun_messages", "testruns"
|
||||
|
Reference in New Issue
Block a user