Skip to content

fix: reject affiliations for organizations that block them - #4461

Merged
skwowet merged 2 commits into
mainfrom
fix/reject-affiliations-for-blocked-orgs
Aug 11, 2026
Merged

fix: reject affiliations for organizations that block them#4461
skwowet merged 2 commits into
mainfrom
fix/reject-affiliations-for-blocked-orgs

Conversation

@skwowet

@skwowet skwowet commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

Rejects creating member segment affiliations that target an organization with isAffiliationBlocked, closing the gap where the public API and CDP UI could reintroduce blocked-org activity affiliations after an org was already blocked.

Changes

  • Public API PATCH /members/:id/project-affiliations/:projectId returns 400 when any affiliation org has affiliations blocked
  • CDP PUT /member/:id/affiliation applies the same check before upserting MSAs

Signed-off-by: Yeganathan S <63534555+skwowet@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings August 11, 2026 05:11
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Jira Issue Key Missing

Your PR title doesn't contain a Jira issue key. Consider adding it for better traceability.

Example:

  • feat: add user authentication (CM-123)
  • feat: add user authentication (IN-123)

Projects:

  • CM: Community Data Platform
  • IN: Insights

Please add a Jira issue key to your PR title.

Copilot AI left a comment

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.

Pull request overview

Rejects affiliations targeting organizations that have blocked them.

Changes:

  • Adds blocked-organization validation to public API updates.
  • Applies equivalent validation to CDP affiliation upserts.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
memberAffiliationsService.ts Validates organization affiliation policies.
patchProjectAffiliation.ts Returns 400 for blocked organizations.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread backend/src/services/member/memberAffiliationsService.ts
Copilot AI review requested due to automatic review settings August 11, 2026 05:14

Copilot AI left a comment

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.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (3)

backend/src/services/member/memberAffiliationsService.ts:76

  • The policy read happens before MemberAffiliationsRepository.upsertMultiple opens its write transaction. If this request reads false, then another transaction blocks the organization and deletes its affiliations before this upsert commits, this request recreates an affiliation for the now-blocked organization. Keep the policy read and insert in one transaction and lock the organization rows with a mode that conflicts with policy updates (for example FOR SHARE), or enforce this invariant in the database.
      const qx = SequelizeRepository.getQueryExecutor(this.options)
      const organizationIds = data
        .map((a) => a.organizationId)
        .filter((id): id is string => Boolean(id))
      const policies = await fetchManyOrganizationAffiliationPolicies(qx, organizationIds)

backend/src/api/public/v1/members/project-affiliations/patchProjectAffiliation.ts:70

  • This check is outside the transaction that replaces the affiliations. A concurrent organization-block operation can update the policy and finish deleting affiliations after this read but before this transaction inserts, leaving a new affiliation on a blocked organization. Perform the policy read inside the write transaction while locking the organization rows with a mode that conflicts with policy updates (for example FOR SHARE), or enforce the invariant in the database.
    const policies = await fetchManyOrganizationAffiliationPolicies(
      qx,
      affiliations.map((a) => a.organizationId),
    )

backend/src/services/member/memberAffiliationsService.ts:79

  • Error400 treats its second argument as an i18n key; in production, an unregistered literal falls back to the generic validation message, so CDP users will not receive the newly intended explanation. Use BadRequestError('This organization does not allow affiliations') (and import it) or add and pass a real translation key.
        throw new Error400(this.options.language, 'This organization does not allow affiliations')

@skwowet
skwowet merged commit d9d2a15 into main Aug 11, 2026
14 checks passed
@skwowet
skwowet deleted the fix/reject-affiliations-for-blocked-orgs branch August 11, 2026 05:23
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.

2 participants