diff --git a/app/models/event.rb b/app/models/event.rb index 5e12746ba..fbb5d403d 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -75,6 +75,7 @@ def create_dummy_user_if_non_production(user_id) ActiveRecord::Base.uncached do User.find_or_initialize_by(id: user_id) do |user| user.update!(dummy_attributes(user_id)) + user.roles.create! role_type: Role::VIEWER end end end @@ -84,7 +85,6 @@ def create_dummy_user_if_non_production(user_id) def dummy_attributes(user_id) { first_name: user_id.split('-').first, - role: User::CASEWORKER, email: "#{user_id}@fake.com", last_name: 'branchbuilder', auth_oid: user_id, diff --git a/app/models/role.rb b/app/models/role.rb new file mode 100644 index 000000000..e5e3763e3 --- /dev/null +++ b/app/models/role.rb @@ -0,0 +1,15 @@ +class Role < ApplicationRecord + ROLE_TYPES = [ + CASEWORKER = 'caseworker'.freeze, + SUPERVISOR = 'supervisor'.freeze, + VIEWER = 'viewer'.freeze + ].freeze + + belongs_to :user + + validates :role_type, inclusion: { in: ROLE_TYPES } + + scope :caseworker, -> { where(role_type: CASEWORKER) } + scope :supervisor, -> { where(role_type: SUPERVISOR) } + scope :viewer, -> { where(role_type: VIEWER) } +end diff --git a/app/models/user.rb b/app/models/user.rb index 09b60f0ed..d4378a3cc 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,18 +1,12 @@ class User < ApplicationRecord has_many :access_logs, dependent: :destroy + has_many :roles, dependent: :destroy - ROLES = [ - CASEWORKER = 'caseworker'.freeze, - SUPERVISOR = 'supervisor'.freeze, - VIEWER = 'viewer'.freeze - ].freeze devise :omniauthable, :timeoutable include AuthUpdateable include Reauthable - validates :role, inclusion: { in: ROLES } - scope :active, -> { where(deactivated_at: nil).where.not(auth_subject_id: nil) } scope :pending_activation, -> { where(auth_subject_id: nil, deactivated_at: nil) } @@ -21,11 +15,11 @@ def display_name end def supervisor? - role == SUPERVISOR + roles.supervisor.any? end def viewer? - role == VIEWER + roles.viewer.any? end def pending_activation? diff --git a/db/migrate/20241015110647_create_roles.rb b/db/migrate/20241015110647_create_roles.rb new file mode 100644 index 000000000..a27a4df2b --- /dev/null +++ b/db/migrate/20241015110647_create_roles.rb @@ -0,0 +1,26 @@ +class CreateRoles < ActiveRecord::Migration[7.1] + def up + create_table :roles do |t| + t.references :user, null: false, foreign_key: true, type: :uuid + t.string :role_type + + t.timestamps + end + + User.find_each do |user| + user.roles.create! role_type: user.role + end + + remove_column :users, :role, :string + end + + def down + add_column :users, :role, :string + + User.find_each do |user| + user.update!(role: user.roles.first.role_type) + end + + drop_table :roles + end +end diff --git a/db/schema.rb b/db/schema.rb index 5ead2d646..6b0101e7c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_10_15_091931) do +ActiveRecord::Schema[7.1].define(version: 2024_10_15_110647) do # These are extensions that must be enabled in order to support this database enable_extension "citext" enable_extension "plpgsql" @@ -70,6 +70,14 @@ t.index ["submission_id"], name: "index_events_on_submission_id" end + create_table "roles", force: :cascade do |t| + t.uuid "user_id", null: false + t.string "role_type" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["user_id"], name: "index_roles_on_user_id" + end + create_table "solid_cache_entries", force: :cascade do |t| t.binary "key", null: false t.binary "value", null: false @@ -104,7 +112,6 @@ create_table "users", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.string "first_name" - t.string "role" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.citext "email" @@ -125,4 +132,5 @@ add_foreign_key "events", "submissions" add_foreign_key "events", "users", column: "primary_user_id" add_foreign_key "events", "users", column: "secondary_user_id" + add_foreign_key "roles", "users" end diff --git a/db/seeds/caseworkers.rb b/db/seeds/caseworkers.rb index c529d6504..269651738 100644 --- a/db/seeds/caseworkers.rb +++ b/db/seeds/caseworkers.rb @@ -4,24 +4,24 @@ case_worker.update( first_name: 'case', last_name: 'worker', - role: 'caseworker', auth_oid: SecureRandom.uuid, auth_subject_id: SecureRandom.uuid, ) +case_worker.roles.create! role_type: 'caseworker' -case_worker = User.find_or_initialize_by(email: 'super.visor@test.com') -case_worker.update( +super_visor = User.find_or_initialize_by(email: 'super.visor@test.com') +super_visor.update( first_name: 'super', last_name: 'visor', - role: 'supervisor', auth_oid: SecureRandom.uuid, auth_subject_id: SecureRandom.uuid, ) +super_visor.roles.create! role_type: 'supervisor' viewer = User.find_or_initialize_by(email: 'viewer@test.com') viewer.update( first_name: 'Reid', last_name: "O'Nly", - role: 'viewer', auth_subject_id: SecureRandom.uuid, ) +viewer.roles.create! role_type: 'viewer' diff --git a/lib/tasks/custom_seeds.rake b/lib/tasks/custom_seeds.rake index 7a80e8219..e10ec7249 100644 --- a/lib/tasks/custom_seeds.rake +++ b/lib/tasks/custom_seeds.rake @@ -26,19 +26,19 @@ namespace :custom_seeds do case_worker.update( first_name: 'case', last_name: 'worker', - role: 'caseworker', auth_oid: SecureRandom.uuid, auth_subject_id: SecureRandom.uuid, ) + case_worker.roles.create! role_type: 'caseworker' - case_worker = User.find_or_initialize_by(email: 'super.visor@test.com') - case_worker.update( + supervisor = User.find_or_initialize_by(email: 'super.visor@test.com') + supervisor.update( first_name: 'super', last_name: 'visor', - role: 'supervisor', auth_oid: SecureRandom.uuid, auth_subject_id: SecureRandom.uuid, ) + supervisor.roles.create! role_type: 'supervisor' Dir[Rails.root.join("db/seeds/*")].each do |path| claim_id = path.split('/').last @@ -71,4 +71,4 @@ namespace :custom_seeds do end end -end \ No newline at end of file +end diff --git a/lib/tasks/user.rake b/lib/tasks/user.rake index 1fdc9a458..4dbf44d6b 100644 --- a/lib/tasks/user.rake +++ b/lib/tasks/user.rake @@ -6,8 +6,8 @@ namespace :user do user.update!( first_name: args[:first_name], last_name: args[:last_name], - role: args[:role], auth_oid: SecureRandom.uuid ) + user.roles.create! role_type: args[:role] end end diff --git a/spec/factories/role.rb b/spec/factories/role.rb new file mode 100644 index 000000000..acf922e58 --- /dev/null +++ b/spec/factories/role.rb @@ -0,0 +1,17 @@ +FactoryBot.define do + factory :role do + user { nil } + + trait :supervisor do + role_type { 'supervisor' } + end + + trait :caseworker do + role_type { 'caseworker' } + end + + trait :viewer do + role_type { 'viewer' } + end + end +end diff --git a/spec/factories/users.rb b/spec/factories/users.rb index 1c4c94b62..a1076e3ba 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -3,9 +3,9 @@ email { 'case.worker@test.com' } first_name { 'case' } last_name { 'worker' } - role { 'caseworker' } auth_oid { SecureRandom.uuid } auth_subject_id { SecureRandom.uuid } + roles { [build(:role, :caseworker)] } trait :deactivated do deactivated_at { Time.zone.now } @@ -16,16 +16,16 @@ email { 'super.visor@test.com' } first_name { 'super' } last_name { 'visor' } - role { 'supervisor' } auth_oid { SecureRandom.uuid } auth_subject_id { SecureRandom.uuid } + roles { [build(:role, :supervisor)] } end factory :viewer, class: 'User' do email { 'readonly.viewer@test.com' } first_name { 'cannot' } last_name { 'edit' } - role { 'viewer' } auth_subject_id { SecureRandom.uuid } + roles { [build(:role, :viewer)] } end end diff --git a/spec/services/update_submission_spec.rb b/spec/services/update_submission_spec.rb index ef62ed2d7..070075b62 100644 --- a/spec/services/update_submission_spec.rb +++ b/spec/services/update_submission_spec.rb @@ -163,7 +163,6 @@ ) expect(Event::Edit.last.primary_user).to have_attributes( first_name: primary_user_id.split('-').first, - role: User::CASEWORKER, email: "#{primary_user_id}@fake.com", last_name: 'branchbuilder', auth_oid: primary_user_id,