Skip to content

Make RolesService.updateRole atomic across the name update and permission reassignment #1050

Description

@RUKAYAT-CODER

Overview

RolesService.updateRole() performs three sequential operations with no transaction: roleRepository.update(id, { name, description }), then a relation .set(permissions) through the query builder, then a findOne to return the result. A failure between the first and second leaves the role renamed but still holding its previous permission set — a security-relevant divergence, since the role's name is what administrators reason about when granting it. Because the relation .set() replaces the entire permission collection, a partially-applied update can also leave the role with no permissions at all if the set operation fails after clearing.

Specifications

Features:

  • Role metadata and permission assignment are updated atomically.
  • A concurrent update cannot interleave with the permission replacement.

Tasks:

  • Wrap all three operations in dataSource.transaction, using the transactional manager throughout.
  • Take a row lock on the role at the start of the transaction so concurrent updates serialize.
  • Throw NotFoundException inside the transaction when the role does not exist, rather than after the writes.
  • Invalidate the RBAC permission cache only after the transaction commits.
  • Add a test that forces the permission set to fail and asserts the name change is rolled back.

Impacted Files:

  • src/rbac/roles/roles.service.ts

Acceptance Criteria

  • A failure during permission reassignment rolls back the name and description change.
  • Concurrent updates to one role do not interleave.
  • Cache invalidation happens only after commit.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions