Skip to content

Commit 261246f

Browse files
committed
Create rake task to transfer school ownership
This is a manual task that we often have to do. Make it easier by creating a re-usable script. We wearn't able to turn off the safeguarding flag for the old user as the API currently requires a user token to do this so have kept it a manual step. ```bash bundle exec rails school_management:transfer_ownership[jane.doe@example.com,john.doe@example.com] bundle exec rails school_management:transfer_ownership[jane.doe@example.com,john.doe@example.com,true] ``` We based this on the documented process here: https://digital-docs.rpf-internal.org/docs/technology/codebases-and-products/editor/processes/code-editor-for-education/transferring-owners
1 parent fa970e4 commit 261246f

2 files changed

Lines changed: 169 additions & 0 deletions

File tree

lib/tasks/school_management.rake

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
namespace :school_management do
2+
desc 'Transfer ownership of a school'
3+
task :transfer_ownership, %i[old_owner_email new_owner_email keep_old_owner_as_teacher] => :environment do |_task, args|
4+
old_owner = UserInfoApiClient.find_user_by_email(args[:old_owner_email])
5+
new_owner = UserInfoApiClient.find_user_by_email(args[:new_owner_email])
6+
7+
unless old_owner
8+
Rails.logger.error("No user found for email #{args[:old_owner_email]}. Did you spell it correctly?")
9+
next
10+
end
11+
12+
unless new_owner
13+
Rails.logger.error("No user found for email #{args[:new_owner_email]}. Did you spell it correctly?")
14+
next
15+
end
16+
17+
if Role.exists?(user_id: new_owner[:id], role: 'owner')
18+
Rails.logger.error("User #{new_owner[:id]} is already the owner of a school")
19+
next
20+
end
21+
22+
if School.exists?(creator_id: new_owner[:id])
23+
Rails.logger.error("User #{new_owner[:id]} is already the creator of a school")
24+
next
25+
end
26+
27+
school = Role.find_by(roles: { user_id: old_owner[:id], role: 'owner' }).school
28+
29+
school.transaction do
30+
remove_old_owner(school, old_owner[:id], args[:keep_old_owner_as_teacher])
31+
assign_roles_to_new_owner(school, new_owner[:id])
32+
33+
school.update!(creator_id: new_owner[:id], creator_agree_to_ux_contact: false)
34+
end
35+
36+
Rails.logger.info "Ownership transfered to #{new_owner[:email]} successfully."
37+
Rails.logger.warn '⚠️ You must now manually remove the owner safeguarding flag from the old owner.'
38+
Rails.logger.warn 'Open a bash console on the rpf-profile app: `heroku run bash -a rpf-profile`'
39+
Rails.logger.warn "Remove the owner safeguarding flag from the old owner: `node profile-cli remove-safeguarding-flag #{args[:old_owner_email]} school:owner`"
40+
end
41+
42+
def remove_old_owner(school, user_id, keep_old_owner_as_teacher)
43+
school.roles.owner.find_by(user_id: user_id).destroy!
44+
school.roles.teacher.find_by(user_id: user_id)&.destroy! unless keep_old_owner_as_teacher
45+
end
46+
47+
def assign_roles_to_new_owner(school, user_id)
48+
school.roles.create!(user_id: user_id, role: 'owner')
49+
school.roles.find_or_create_by!(user_id: user_id, role: 'teacher')
50+
end
51+
end
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# frozen_string_literal: true
2+
3+
require 'rails_helper'
4+
require 'rake'
5+
6+
RSpec.describe 'school_management', type: :task do
7+
describe ':transfer_ownership' do
8+
let(:task) { Rake::Task['school_management:transfer_ownership'] }
9+
let(:old_user_id) { SecureRandom.uuid }
10+
let(:new_user_id) { SecureRandom.uuid }
11+
let(:school) { create(:school, creator_id: old_user_id) }
12+
13+
before do
14+
stub_user_info_api_find_by_email(
15+
email: 'old_owner@example.com',
16+
user: { id: old_user_id, email: 'old_owner@example.com' }
17+
)
18+
19+
stub_user_info_api_find_by_email(
20+
email: 'new_owner@example.com',
21+
user: { id: new_user_id, email: 'new_owner@example.com' }
22+
)
23+
24+
create(:owner_role, school:, user_id: old_user_id)
25+
create(:teacher_role, school:, user_id: old_user_id)
26+
end
27+
28+
it "exits early if new owner doesn't exist" do
29+
allow(UserInfoApiClient).to receive(:find_user_by_email)
30+
.with('not_real_owner@example.com')
31+
.and_return(nil)
32+
33+
task.invoke('old_owner@example.com', 'not_real_owner@example.com')
34+
35+
expect(school.creator_id).to eq(old_user_id)
36+
end
37+
38+
it "exits early if old owner doesn't exist" do
39+
allow(UserInfoApiClient).to receive(:find_user_by_email)
40+
.with('not_real_owner@example.com')
41+
.and_return(nil)
42+
43+
task.invoke('old_owner@example.com', 'new_owner@example.com')
44+
45+
expect(school.creator_id).to eq(old_user_id)
46+
end
47+
48+
it 'exits early if new owner is already owner of a school' do
49+
create(:owner_role, school:, user_id: new_user_id)
50+
51+
task.invoke('old_owner@example.com', 'new_owner@example.com')
52+
53+
expect(school.creator_id).to eq(old_user_id)
54+
end
55+
56+
it 'exits early if new owner is already creator of a school' do
57+
create(:school, creator_id: new_user_id)
58+
59+
task.invoke('old_owner@example.com', 'new_owner@example.com')
60+
61+
expect(school.creator_id).to eq(old_user_id)
62+
end
63+
64+
it 'creates owner and teacher roles for the new owner' do
65+
task.invoke('old_owner@example.com', 'new_owner@example.com')
66+
67+
owners = school.roles.owner
68+
owner_user_ids = owners.map(&:user_id)
69+
teachers = school.roles.teacher
70+
teacher_user_ids = teachers.map(&:user_id)
71+
72+
expect(owner_user_ids).to eq([new_user_id])
73+
expect(teacher_user_ids).to include(new_user_id)
74+
end
75+
76+
it 'does not error if new owner already has teacher role' do
77+
create(:teacher_role, school:, user_id: new_user_id)
78+
task.invoke('old_owner@example.com', 'new_owner@example.com')
79+
80+
owners = school.roles.owner
81+
owner_user_ids = owners.map(&:user_id)
82+
teachers = school.roles.teacher
83+
teacher_user_ids = teachers.map(&:user_id)
84+
85+
expect(owner_user_ids).to eq([new_user_id])
86+
expect(teacher_user_ids).to include(new_user_id)
87+
end
88+
89+
it 'keeps the old owner as a teacher if keep parameter is true' do
90+
task.invoke('old_owner@example.com', 'new_owner@example.com', 'true')
91+
teachers = school.roles.teacher
92+
teacher_user_ids = teachers.map(&:user_id)
93+
expect(teacher_user_ids).to include(old_user_id)
94+
end
95+
96+
it 'removes the old owner as a teacher by default' do
97+
task.invoke('old_owner@example.com', 'new_owner@example.com')
98+
teachers = school.roles.teacher
99+
teacher_user_ids = teachers.map(&:user_id)
100+
expect(teacher_user_ids).not_to include(old_user_id)
101+
end
102+
103+
it 'switches creator to the new owner' do
104+
task.invoke('old_owner@example.com', 'new_owner@example.com')
105+
school.reload
106+
expect(school.creator_id).to eq(new_user_id)
107+
end
108+
109+
it 'sets the school UX contact flag to false' do
110+
school.update!(creator_agree_to_ux_contact: true)
111+
112+
task.invoke('old_owner@example.com', 'new_owner@example.com')
113+
school.reload
114+
115+
expect(school.creator_agree_to_ux_contact).to eq(false)
116+
end
117+
end
118+
end

0 commit comments

Comments
 (0)