Skip to content

Establish billable member membership type with a Group

Vijay Hawoldar requested to merge vij-billable-member-source into master

What does this MR do?

Adds an additional attribute to the BillableMember entity for the GET /api/v4/groups/:id/billable_members REST endpoint.

Why?

We recently added the ability to remove billable members from a root group within the seat usage page.

This uncovered an edge case problem when removing a billable member that could belong to a group outside of the root group hierarchy:

graph TB
    
    subgraph Invited/Shared Group associations
    E(Outside Group)-->|Member|F(User C)
    E-->|Member| G(User D)
    end
    
    D-->|GroupGroupLink|E
    
    subgraph Root Group Associations
    A[Root Group] -->|Member| B(User A)
    A-->|Member| C(User B)
    A-->D[Sub-Group]
    end

In this example, User C and User D are not direct members of Root Group but are considered billable within Root Group.

We cannot individually remove either of those members from Root Group because of the relationships and implications on having partial-group access - groups are invited as a whole and should continue to have access as a whole.

What is the solution?

The currently agreed solution is to identify which members are from a group invite and expose that to the frontend, which can then remove the ability to try and delete them.

This is more complicated than it appears on the surface, because Group -> User associations are represented by a Member record in the database, but this is not the case with members of invited/shared groups. These are associated via the GroupGroupLink join table (demonstrated in the diagram above).

These associations are handled already when calculating billable members, and a somewhat expensive set of queries are already performed to generate a Set of user IDs that are billable, throughout a root Group's hierarchy.

This MR attempts to leverage that work by making the various sets of IDs accessible as a hash to compare against to establish how they're associated, rather than re-performing the expensive queries for each user in the entity (or some other location).

Testing

curl --request GET \
  --url http://127.0.0.1:3000/api/v4/groups/:group_id/billable_members \
  --header 'PRIVATE-TOKEN: <your private token>'

Refs #324658 (closed)

Does this MR meet the acceptance criteria?

Conformity

Availability and Testing

Security

If this MR contains changes to processing or storing of credentials or tokens, authorization and authentication methods and other items described in the security review guidelines:

  • 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 Vijay Hawoldar

Merge request reports