Disallow updating proficiency attributes
closes OUT-4125 flag=account_level_mastery_scales At the API level, disallow updating an outcome's proficiency attributes, since these will be managed at the context level. Additionally, when editing an outcome in the UI, exclude these attributes from the Backbone model so they are not included when persisting changes to the API. test plan: - enable the feature flag - create account mastery scale - create an account outcome - reload the page - confirm that editing the outcome does not error when saving - disable the feature flag - confirm that editing the outcome does not error when saving Change-Id: I647049372ae46d31a07f9fa34056cc9d4315047f Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/254896 Reviewed-by: Pat Renner <prenner@instructure.com> Reviewed-by: Michael Brewer-Davis <mbd@instructure.com> Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> QA-Review: Chrystal Langston <chrystal.langston@instructure.com> Product-Review: Jody Sailor
This commit is contained in:
parent
b1bd9d1955
commit
63f3256897
|
@ -104,3 +104,12 @@ export default class Outcome extends Backbone.Model
|
|||
when 'add' then @outcomeGroup.outcomes_url
|
||||
when 'edit' then @get 'url'
|
||||
when 'delete' then @outcomeLink.url
|
||||
|
||||
save: (data, saveOpts) ->
|
||||
if ENV.ACCOUNT_LEVEL_MASTERY_SCALES
|
||||
@unset 'mastery_points'
|
||||
@unset 'points_possible'
|
||||
@unset 'ratings'
|
||||
@unset 'calculation_method'
|
||||
@unset 'calculation_int'
|
||||
super
|
||||
|
|
|
@ -266,6 +266,21 @@ class OutcomesApiController < ApplicationController
|
|||
def update
|
||||
return unless authorized_action(@outcome, @current_user, :update)
|
||||
|
||||
if @domain_root_account.feature_enabled?(:account_level_mastery_scales)
|
||||
error_msg = nil
|
||||
if params[:mastery_points]
|
||||
error_msg = t('Individual outcome mastery points cannot be modified.')
|
||||
elsif params[:ratings]
|
||||
error_msg = t('Individual outcome ratings cannot be modified.')
|
||||
elsif params[:calculation_method] || params[:calculation_int]
|
||||
error_msg = t('Individual outcome calculation values cannot be modified.')
|
||||
end
|
||||
if error_msg
|
||||
render json: { error: error_msg }, status: :forbidden
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
update_outcome_criterion(@outcome) if params[:mastery_points] || params[:ratings]
|
||||
if @outcome.update(params.permit(*DIRECT_PARAMS))
|
||||
render :json => outcome_json(@outcome, @current_user, session, {context: @context})
|
||||
|
|
|
@ -727,6 +727,50 @@ describe "Outcomes API", type: :request do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with account_level_mastery_scales enabled" do
|
||||
before do
|
||||
@outcome.context.root_account.set_feature_flag!(:account_level_mastery_scales, 'on')
|
||||
end
|
||||
|
||||
it "should fail when updating mastery points" do
|
||||
api_call(:put, "/api/v1/outcomes/#{@outcome.id}",
|
||||
{ :controller => 'outcomes_api',
|
||||
:action => 'update',
|
||||
:id => @outcome.id.to_s,
|
||||
:format => 'json' },
|
||||
{ :mastery_points => 5 })
|
||||
assert_forbidden
|
||||
expect(JSON.parse(response.body)['error']).to eq 'Individual outcome mastery points cannot be modified.'
|
||||
end
|
||||
|
||||
it "should fail when updating ratings" do
|
||||
api_call(:put, "/api/v1/outcomes/#{@outcome.id}",
|
||||
{ :controller => 'outcomes_api',
|
||||
:action => 'update',
|
||||
:id => @outcome.id.to_s,
|
||||
:format => 'json' },
|
||||
{ :ratings => [
|
||||
{ :points => 10, :description => "Exceeds Expectations" },
|
||||
{ :points => 5, :description => "Meets Expectations" },
|
||||
{ :points => 0, :description => "Does Not Meet Expectations" }
|
||||
]})
|
||||
assert_forbidden
|
||||
expect(JSON.parse(response.body)['error']).to eq 'Individual outcome ratings cannot be modified.'
|
||||
end
|
||||
|
||||
it "should fail when updating calculation values" do
|
||||
api_call(:put, "/api/v1/outcomes/#{@outcome.id}",
|
||||
{ :controller => 'outcomes_api',
|
||||
:action => 'update',
|
||||
:id => @outcome.id.to_s,
|
||||
:format => 'json' },
|
||||
{ :calculation_method => 'decaying_average',
|
||||
:calculation_int => 65 })
|
||||
assert_forbidden
|
||||
expect(JSON.parse(response.body)['error']).to eq 'Individual outcome calculation values cannot be modified.'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -67,13 +67,13 @@ test('CanManage returns true for an account outcome on the course level', functi
|
|||
|
||||
test('default calculation method settings not set if calculation_method exists', function() {
|
||||
const spy = sandbox.spy(Outcome.prototype, 'setDefaultCalcSettings')
|
||||
const outcome = new Outcome(this.importedOutcome, {parse: true})
|
||||
new Outcome(this.importedOutcome, {parse: true})
|
||||
ok(!spy.called)
|
||||
})
|
||||
|
||||
test('default calculation method settings set if calculation_method is null', function() {
|
||||
const spy = sandbox.spy(Outcome.prototype, 'setDefaultCalcSettings')
|
||||
const outcome = new Outcome(this.courseOutcome, {parse: true})
|
||||
new Outcome(this.courseOutcome, {parse: true})
|
||||
ok(spy.calledOnce)
|
||||
})
|
||||
|
||||
|
@ -166,3 +166,14 @@ test('it uses the ENV.MASTERY_SCALES ratings', function() {
|
|||
equal(outcome.get('mastery_points'), 3)
|
||||
equal(outcome.get('points_possible'), 4)
|
||||
})
|
||||
|
||||
test('ignores proficiency attributes during saving', function() {
|
||||
const outcome = new Outcome(this.importedOutcome, {parse: true})
|
||||
sinon.stub(outcome, 'url').returns('fake-url')
|
||||
outcome.save({}, {})
|
||||
equal(outcome.get('mastery_points'), null)
|
||||
equal(outcome.get('points_possible'), null)
|
||||
equal(outcome.get('ratings'), null)
|
||||
equal(outcome.get('calculation_method'), null)
|
||||
equal(outcome.get('calculation_int'), null)
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue