enable prounoun changes via api v1 users

fixes VICE-963

setting a user's pronouns via the api
will now work if the root account
has can_change_pronouns enabled

when a request passes "he/him",
it gets stored as he_him: "He/Him" (official)

if a request passes an unapproved pronoun,
it will not get used

if a request passes an empty string,
users pronouns will get cleared out

flag=none

TEST PLAN:
- shortcut: look at the new specs, make sure
they cover cases you care about

long version:
- make sure can_add_pronouns and can_change pronouns
are enabled in account settings
- as an admin, make a PUT request to one of your users
i.e. PUT /api/v1/users/:user_id_of_someone_in_your_account
body: {users: {pronouns: 'anypronounyouwant'}}
- verify that you were able to change the pronoun
- repeat for a regular user but this time, for your own
id
- verify you were able to change your pronoun

Change-Id: I9e72efe68833a5c77e6baec47e4918df5541f179
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/251478
Reviewed-by: Rob Orton <rob@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
QA-Review: Rob Orton <rob@instructure.com>
Product-Review: Rob Orton <rob@instructure.com>
This commit is contained in:
Caleb Guanzon 2020-10-29 12:29:43 -06:00
parent 4aa5d67d3a
commit e36709adb1
3 changed files with 131 additions and 0 deletions

View File

@ -1776,6 +1776,8 @@ class UsersController < ApplicationController
end
end
include Pronouns
# @API Edit a user
# Modify an existing user. To modify a user's login, see the documentation for logins.
#
@ -1822,6 +1824,12 @@ class UsersController < ApplicationController
# Sets a bio on the user profile. (See {api:ProfileController#settings Get user profile}.)
# Profiles must be enabled on the root account.
#
# @argument user[pronouns] [String]
# Sets pronouns on the user profile.
# Passing an empty string will empty the user's pronouns
# Only Available Pronouns set on the root account are allowed
# Adding and changing pronouns must be enabled on the root account.
#
# @example_request
#
# curl 'https://<canvas>/api/v1/users/133.json' \
@ -1854,6 +1862,10 @@ class UsersController < ApplicationController
managed_attributes << :title if @user.grants_right?(@current_user, :rename)
end
if @domain_root_account.can_change_pronouns? && @user.grants_right?(@current_user, :manage_user_details)
managed_attributes << :pronouns
end
if @user.grants_right?(@current_user, :manage_user_details)
managed_attributes.concat([:time_zone, :locale])
end
@ -1895,6 +1907,14 @@ class UsersController < ApplicationController
includes << "bio"
end
if (pronouns = user_params.delete(:pronouns))
updated_pronoun = match_pronoun(pronouns, @domain_root_account.pronouns)
if updated_pronoun || pronouns&.empty?
@user.pronouns = updated_pronoun
end
includes << "pronouns"
end
if admin_avatar_update
old_avatar_state = @user.avatar_state
@user.avatar_state = 'submitted'

View File

@ -45,4 +45,11 @@ module Pronouns
pronouns
end
def match_pronoun(supplied_pronouns_str, account_pronouns_arr)
pronoun = clean_pronouns(supplied_pronouns_str)
account_pronouns_arr.each do |ap|
return ap if ap.casecmp(pronoun) == 0
end
nil
end
end

View File

@ -1657,6 +1657,89 @@ describe "Users API", type: :request do
end
end
context 'pronouns' do
context 'when can_change_pronouns=true' do
before :once do
Account.default.tap do |a|
a.settings[:can_add_pronouns] = true
a.settings[:can_change_pronouns] = true
a.save!
end
end
it "should clear attribute when empty string is passed" do
@student.pronouns = "He/Him"
@student.save!
json = api_call(:put, @path, @path_options, {:user => {:pronouns => ""}})
expect(json['pronouns']).to be_nil
expect(@student.reload.pronouns).to be_nil
end
it "should update with a default pronoun" do
approved_pronoun = "He/Him"
json = api_call(:put, @path, @path_options, {:user => {:pronouns => approved_pronoun}})
expect(json['pronouns']).to eq approved_pronoun
expect(@student.reload.pronouns).to eq approved_pronoun
expect(@student.read_attribute(:pronouns)).to eq "he_him"
end
it "should fix the case when pronoun does not match default pronoun case" do
wrong_case_pronoun = "he/him"
expected_pronoun = "He/Him"
json = api_call(:put, @path, @path_options, {:user => {:pronouns => wrong_case_pronoun}})
expect(json['pronouns']).to eq expected_pronoun
expect(@student.reload.pronouns).to eq expected_pronoun
expect(@student.read_attribute(:pronouns)).to eq "he_him"
end
it "should fix the case when pronoun does not match custom pronoun case" do
Account.default.tap do |a|
a.pronouns = ["Siya/Siya", "Ito/Iyan"]
a.save!
end
wrong_case_pronoun = "ito/iyan"
expected_pronoun = "Ito/Iyan"
json = api_call(:put, @path, @path_options, {:user => {:pronouns => wrong_case_pronoun}})
expect(json['pronouns']).to eq expected_pronoun
expect(@student.reload.pronouns).to eq expected_pronoun
expect(@student.read_attribute(:pronouns)).to eq expected_pronoun
end
it "should not update when pronoun is not approved" do
@student.pronouns = "She/Her"
@student.save!
original_pronoun = @student.pronouns
unapproved_pronoun = "Unapproved/Unapproved"
json = api_call(:put, @path, @path_options, {:user => {:pronouns => unapproved_pronoun}})
expect(json['pronouns']).to eq original_pronoun
expect(@student.reload.pronouns).to eq original_pronoun
end
end
context 'when can_change_pronouns=false' do
before :once do
Account.default.tap do |a|
a.settings[:can_add_pronouns] = true
a.settings[:can_change_pronouns] = false
a.save!
end
end
it "errors" do
@student.pronouns = "She/Her"
@student.save!
original_pronoun = @student.pronouns
test_pronoun = "He/Him"
raw_api_call(:put, @path, @path_options, {:user => {:pronouns => test_pronoun}})
json = JSON.parse(response.body)
expect(response.code).to eq '401'
expect(json['status']).to eq 'unauthorized'
expect(json['errors'][0]['message']).to eq 'user not authorized to perform that action'
expect(@student.reload.pronouns).to eq original_pronoun
end
end
end
it "should be able to update a user's profile" do
Account.default.tap{|a| a.settings[:enable_profiles] = true; a.save!}
new_title = "Burninator"
@ -1781,6 +1864,27 @@ describe "Users API", type: :request do
course_with_teacher user: @user, active_all: true
end
context 'pronouns' do
it "returns an error when user does not have manage rights" do
Account.default.tap do |a|
a.settings[:can_add_pronouns] = true
a.settings[:can_change_pronouns] = true
a.save!
end
@student.pronouns = "She/Her"
@student.save!
original_pronoun = @student.pronouns
test_pronoun = "He/Him"
raw_api_call(:put, @path, @path_options, {:user => {:pronouns => test_pronoun}})
json = JSON.parse(response.body)
expect(response.code).to eq '401'
expect(json['status']).to eq 'unauthorized'
expect(json['errors'][0]['message']).to eq 'user not authorized to perform that action'
expect(@student.reload.pronouns).to eq original_pronoun
end
end
context "with users_can_edit_name enabled" do
before :once do
@course.root_account.settings = { users_can_edit_name: true }