Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config/database.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ default: &default
adapter: postgresql
encoding: unicode
host: <%= ENV.fetch('POSTGRES_HOST', 'db') %>
port: <%= ENV.fetch('POSTGRES_PORT', '5432') %>
username: <%= ENV.fetch('POSTGRES_USER', 'no_pg_user_set') %>
password: <%= ENV.fetch('POSTGRES_PASSWORD', '') %>
pool: <%= ENV.fetch('RAILS_MAX_THREADS', 5) %>
Expand Down
53 changes: 53 additions & 0 deletions lib/tasks/school_management.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# frozen_string_literal: true

namespace :school_management do
desc 'Transfer ownership of a school'
task :transfer_ownership, %i[old_owner_email new_owner_email keep_old_owner_as_teacher] => :environment do |_task, args|
old_owner = UserInfoApiClient.find_user_by_email(args[:old_owner_email])
new_owner = UserInfoApiClient.find_user_by_email(args[:new_owner_email])

unless old_owner
Rails.logger.error("No user found for email #{args[:old_owner_email]}. Did you spell it correctly?")
next
end

unless new_owner
Rails.logger.error("No user found for email #{args[:new_owner_email]}. Did you spell it correctly?")
next
end

if Role.exists?(user_id: new_owner[:id], role: 'owner')
Rails.logger.error("User #{new_owner[:id]} is already the owner of a school")
next
end

if School.exists?(creator_id: new_owner[:id])
Rails.logger.error("User #{new_owner[:id]} is already the creator of a school")
next
end

school = Role.find_by(roles: { user_id: old_owner[:id], role: 'owner' }).school

school.transaction do
remove_old_owner(school, old_owner[:id], args[:keep_old_owner_as_teacher])
assign_roles_to_new_owner(school, new_owner[:id])

school.update!(creator_id: new_owner[:id], creator_agree_to_ux_contact: false)
end

Rails.logger.info "Ownership transfered to #{new_owner[:email]} successfully."
Rails.logger.warn '⚠️ You must now manually remove the owner safeguarding flag from the old owner.'
Rails.logger.warn 'Open a bash console on the rpf-profile app: `heroku run bash -a rpf-profile`'
Rails.logger.warn "Remove the owner safeguarding flag from the old owner: `node profile-cli remove-safeguarding-flag #{args[:old_owner_email]} school:owner`"
end

def remove_old_owner(school, user_id, keep_old_owner_as_teacher)
school.roles.owner.find_by(user_id: user_id).destroy!
school.roles.teacher.find_by(user_id: user_id)&.destroy! unless keep_old_owner_as_teacher
end

def assign_roles_to_new_owner(school, user_id)
school.roles.create!(user_id: user_id, role: 'owner')
school.roles.find_or_create_by!(user_id: user_id, role: 'teacher')
end
end
118 changes: 118 additions & 0 deletions spec/lib/tasks/school_management_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# frozen_string_literal: true

require 'rails_helper'
require 'rake'

RSpec.describe 'school_management', type: :task do
describe ':transfer_ownership' do
let(:task) { Rake::Task['school_management:transfer_ownership'] }
let(:old_user_id) { SecureRandom.uuid }
let(:new_user_id) { SecureRandom.uuid }
let(:school) { create(:school, creator_id: old_user_id) }

before do
stub_user_info_api_find_by_email(
email: 'old_owner@example.com',
user: { id: old_user_id, email: 'old_owner@example.com' }
)

stub_user_info_api_find_by_email(
email: 'new_owner@example.com',
user: { id: new_user_id, email: 'new_owner@example.com' }
)

create(:owner_role, school:, user_id: old_user_id)
create(:teacher_role, school:, user_id: old_user_id)
end

it "exits early if new owner doesn't exist" do
allow(UserInfoApiClient).to receive(:find_user_by_email)
.with('not_real_owner@example.com')
.and_return(nil)

task.invoke('old_owner@example.com', 'not_real_owner@example.com')

expect(school.creator_id).to eq(old_user_id)
end

it "exits early if old owner doesn't exist" do
allow(UserInfoApiClient).to receive(:find_user_by_email)
.with('not_real_owner@example.com')
.and_return(nil)

task.invoke('old_owner@example.com', 'new_owner@example.com')

expect(school.creator_id).to eq(old_user_id)
end

it 'exits early if new owner is already owner of a school' do
create(:owner_role, school:, user_id: new_user_id)

task.invoke('old_owner@example.com', 'new_owner@example.com')

expect(school.creator_id).to eq(old_user_id)
end

it 'exits early if new owner is already creator of a school' do
create(:school, creator_id: new_user_id)

task.invoke('old_owner@example.com', 'new_owner@example.com')

expect(school.creator_id).to eq(old_user_id)
end

it 'creates owner and teacher roles for the new owner' do
task.invoke('old_owner@example.com', 'new_owner@example.com')

owners = school.roles.owner
owner_user_ids = owners.map(&:user_id)
teachers = school.roles.teacher
teacher_user_ids = teachers.map(&:user_id)

expect(owner_user_ids).to eq([new_user_id])
expect(teacher_user_ids).to include(new_user_id)
end

it 'does not error if new owner already has teacher role' do
create(:teacher_role, school:, user_id: new_user_id)
task.invoke('old_owner@example.com', 'new_owner@example.com')

owners = school.roles.owner
owner_user_ids = owners.map(&:user_id)
teachers = school.roles.teacher
teacher_user_ids = teachers.map(&:user_id)

expect(owner_user_ids).to eq([new_user_id])
expect(teacher_user_ids).to include(new_user_id)
end

it 'keeps the old owner as a teacher if keep parameter is true' do
task.invoke('old_owner@example.com', 'new_owner@example.com', 'true')
teachers = school.roles.teacher
teacher_user_ids = teachers.map(&:user_id)
expect(teacher_user_ids).to include(old_user_id)
end

it 'removes the old owner as a teacher by default' do
task.invoke('old_owner@example.com', 'new_owner@example.com')
teachers = school.roles.teacher
teacher_user_ids = teachers.map(&:user_id)
expect(teacher_user_ids).not_to include(old_user_id)
end

it 'switches creator to the new owner' do
task.invoke('old_owner@example.com', 'new_owner@example.com')
school.reload
expect(school.creator_id).to eq(new_user_id)
end

it 'sets the school UX contact flag to false' do
school.update!(creator_agree_to_ux_contact: true)

task.invoke('old_owner@example.com', 'new_owner@example.com')
school.reload

expect(school.creator_agree_to_ux_contact).to be(false)
end
end
end