Skip to content

Block supporting org editors from locking themselves out [WHIT - 3458]#11455

Open
GDSNewt wants to merge 1 commit into
mainfrom
dont-allow-supporting-org-editors-to-lock-themselves-out-access-limiting
Open

Block supporting org editors from locking themselves out [WHIT - 3458]#11455
GDSNewt wants to merge 1 commit into
mainfrom
dont-allow-supporting-org-editors-to-lock-themselves-out-access-limiting

Conversation

@GDSNewt
Copy link
Copy Markdown
Contributor

@GDSNewt GDSNewt commented May 15, 2026

Fixes a bug where users could unintentionally remove their own organisation’s access to a draft without receiving a warning, due to how empty multi-select fields are handled in HTML forms.


Problem

While working on support, I encountered the following scenario:

  1. An Org B user creates a draft publication with:

    • Org A as the lead organisation
    • Org B as a supporting organisation
  2. The user later edits the draft and:

    • Enables "Limit access"
    • Changes the lead organisation to Org A only
    • Removes Org B from supporting organisations
  3. Due to HTML behavior:

    • <select multiple> fields submit nothing when empty
    • supporting_organisation_ids is missing from the payload entirely

Root Cause

  • In the controller:

    • delete_absent_edition_organisations detects the missing key
    • It skips processing
    • Org B remains in the in-memory edition_organisations
  • In DraftEditionUpdater:

    • The "will this user retain access?" check runs against this in-memory state
    • Org B is still present, so access is assumed to be retained
  • The save is allowed:

    • access_limited = true
    • Only Org A is persisted as the lead organisation

Result

  • The Org B user loses access
  • No warning is shown during the edit process

Fix

  1. Handle missing multi-select params explicitly

    • Treat absence of supporting_organisation_ids as "clear all values", not "no change"
  2. Wrap update flow in a transaction

    • Encloses assign_attributes and save
    • Ensures that if can_perform? returns false, all changes are rolled back, including side effects from attribute assignment

JIRA

@GDSNewt GDSNewt changed the title Block supporting org editors from locking themselves out Block supporting org editors from locking themselves out [WHIT - 3458] May 15, 2026
end
if edition_params[:supporting_organisation_ids]
edition_params[:supporting_organisation_ids] = edition_params[:supporting_organisation_ids].reject(&:blank?)
elsif edition_params.key?(:lead_organisation_ids)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear reading the code why we are doing this. We could create a separate method to describe it e.g.

  if editions_form_cleared_supporting_orgs?
    edition_params[:supporting_organisation_ids] = []
  elsif edition_params[:supporting_organisation_ids]
    edition_params[:supporting_organisation_ids] = edition_params[:supporting_organisation_ids].reject(&:blank?)
  end

  def editions_form_cleared_supporting_orgs?
    edition_params.key?(:lead_organisation_ids) &&
      !edition_params.key?(:supporting_organisation_ids)
  end

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also add a corresponding test?


def update
@edition.assign_attributes(edition_params)
saved = ApplicationRecord.transaction do
Copy link
Copy Markdown
Contributor

@TonyGDS TonyGDS May 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DraftEditionUpdater has a method access_limit_excludes_current_user? could we not do something similar here with the input params rather than wrapping the action in a transaction? Reading the code it's unclear why we need to do it. If we call access_limit_excludes_current_user? before @edition.assign_attributes(edition_params) we wouldn't have to roll anything back.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants