{"record":{"id":"59f702d1dc0218fc","repo":"instructure/canvas-lms","slug":"insufficient-permission-delete-outcome-calculation-method","errorCode":null,"errorMessage":"insufficient permission","messagePattern":"insufficient permission","errorType":"exception","errorClass":"GraphQL::ExecutionError","httpStatus":null,"severity":"warning","filePath":"app/graphql/mutations/delete_outcome_calculation_method.rb","lineNumber":38,"sourceCode":"\nclass Mutations::DeleteOutcomeCalculationMethod < Mutations::BaseMutation\n  graphql_name \"DeleteOutcomeCalculationMethod\"\n\n  # input arguments\n  argument :id, ID, required: true\n\n  # the return data if the delete is successful\n  field :outcome_calculation_method_id, ID, null: false\n\n  def self.outcome_calculation_method_id_log_entry(_entry, context)\n    context[:deleted_models][:outcome_calculation_method].context\n  end\n\n  def resolve(input:)\n    record_id = GraphQLHelpers.parse_relay_or_legacy_id(input[:id], \"OutcomeCalculationMethod\")\n    record = OutcomeCalculationMethod.active.find_by(id: record_id)\n    raise GraphQL::ExecutionError, \"Unable to find OutcomeCalculationMethod\" if record.nil?\n    raise GraphQL::ExecutionError, \"insufficient permission\" unless record.context.grants_right? current_user, :manage_proficiency_calculations\n\n    context[:deleted_models][:outcome_calculation_method] = record\n    record.destroy\n    { outcome_calculation_method_id: record.id }\n  end\nend\n","sourceCodeStart":20,"sourceCodeEnd":45,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/graphql/mutations/delete_outcome_calculation_method.rb#L20-L45","documentation":"The deleteOutcomeCalculationMethod mutation raises \"insufficient permission\" when the record's context (account or course) does not grant the current user :manage_proficiency_calculations. The record exists but the user may not manage its calculation methods.","triggerScenarios":"Calling deleteOutcomeCalculationMethod with a valid active id while current_user lacks manage_proficiency_calculations on record.context — e.g. a student or plain teacher on an account-level calculation method.","commonSituations":"API tokens for non-admin users, admins of a different root account than the record's context, or course-level users attempting account-level proficiency changes.","solutions":["Grant the user :manage_proficiency_calculations in the record's context (account/course permissions)","Use a token for a user with account-level outcome management rights","Verify record.context matches the account you administer","Check role overrides in the account's permission matrix"],"exampleFix":"// before\nrecord.destroy\n// after\nunless record.context.grants_right?(current_user, :manage_proficiency_calculations)\n  raise GraphQL::ExecutionError, \"insufficient permission\"\nend\nrecord.destroy","handlingStrategy":"validation","validationCode":"const perms = await query(contextPermissions, { contextId: record.contextId });\nif (!perms?.manageProficiencyCalculations) throw new Forbidden();","typeGuard":"function canManageCalculations(perms) {\n  return perms?.manageProficiencyCalculations === true;\n}","tryCatchPattern":"try {\n  await client.mutate(DELETE_OUTCOME_CALCULATION_METHOD, { id });\n} catch (e) {\n  if (e.message === \"insufficient permission\") {\n    showPermissionHelp(\"manage_proficiency_calculations\");\n  } else throw e;\n}","preventionTips":["Gate UI on permissions fields from the GraphQL type","Confirm the admin account matches the record's context","Verify role overrides include manage_proficiency_calculations","Use admin tokens for outcome management automation"],"tags":["graphql","authorization","permissions","outcomes"],"backgroundTag":"insufficient-permissions","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}