Skip to content

Fix labels applied to a wrong issue in boards

euko requested to merge 334465-label-problem-fix into master

What does this MR do?

Resolves #334465 (comment 665652425) AND #340068 (closed).

What was the cause of the bug?

the labels select (labels_select_root.vue) will be replaced with a new implementation soon.

The labels select has its own vuex store which has the following states:

  • state.labels
  • state.labelsFetched

Then the labels select itself accepts the prop selectedLabels.

On mounting, the labels select initially displays the labels stored in selectedLabels. Then when a user opens a dropdown (and only then) calls the backend to fetch labels and updates state.labels and state.labelsFetched to true (see !65530 (merged)).

Now this design is very problematic when the labels select is used in the boards sidebar. Because an actual update request happens in board_sidebar_labels_select.vue through apollo then the updated labels information is passed via selectedLabels, the labels select must be told to update state.labels whenever selectedLabels changes.

The mechanism for this is a watcher on selectedLabels placed in the labels select component. Unfortunately, when the board sidebar is hidden, the labels select component is destroyed temporarily and the watcher does not become activated on a re-mount. This has a particularly pernicious effect when the vuex store for the labels select is already initialized (state.labelsFetched is true) because the vuex action fetchLabels() will immediately return and state.labels will become stale without the watcher.

Walkthrough

  1. User clicks on an issue card (for the first time)
  • labels are fetched from the backend
  • board_sidebar_labels_select.vue passes the labels info to labels_select_root.vue via selectedLabels
  1. User updates the labels on the issue
  • opening the dropdown triggers fetchLabels() eventually updating state.labels and setting state.labelsFetched to true. (it's important to note that these are vuex states for the labels component, NOT the board).
  1. User closes the sidebar
  • The sidebar is closed unmounting the labels select.
  1. User clicks on another issue card and re-opens the sidebar.
  • When the sidebar is re-opened for the newly selected issue, the labels info for the issue is fetched then passed via selectedLabels but the watcher in labels_select_root.vue doesn't immediately trigger.
  1. User opens the labels dropdown
  • Because state.labelsFetched is already true, fetchLabels() returns and state.labels has stale values that are then used in an update request.

Does this MR meet the acceptance criteria?

Conformity

Availability and Testing

Security

Does this MR contain changes to processing or storing of credentials or tokens, authorization and authentication methods or other items described in the security review guidelines? If not, then delete this Security section.

  • Label as security and @ mention @gitlab-com/gl-security/appsec
  • The MR includes necessary changes to maintain consistency between UI, API, email, or other methods
  • Security reports checked/validated by a reviewer from the AppSec team
Edited by euko

Merge request reports