Fix owner deletion by qualifying ambiguous tenant_id column

The CountActiveOwnerByOrganizationID query joins iam_membership_profiles with
iam_memberships, but used an unqualified tenant_id = @tenant_id in the WHERE
clause. Since both tables have a tenant_id column, PostgreSQL raised an
"ambiguous column" error when deleting an owner. Fixed by prefixing with the
table alias (p.tenant_id) to match the pattern used in CountByOrganizationID.

Added TestUser_RemoveOwner e2e test to verify one owner can remove another.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
Bryan Frimin
2026-03-19 11:53:07 +01:00
parent 922c0c2db8
commit d6b9280038
2 changed files with 89 additions and 1 deletions

View File

@@ -196,6 +196,94 @@ func TestUser_RemoveUser(t *testing.T) {
assert.Equal(t, userID, mutationResult.RemoveUser.DeletedProfileID)
}
func TestUser_RemoveOwner(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
// Create another owner to remove
_ = testutil.NewClientInOrg(t, testutil.RoleOwner, owner)
// Get the profiles
query := `
query($id: ID!) {
node(id: $id) {
... on Organization {
profiles(first: 50) {
edges {
node {
id
identity {
id
}
membership {
role
}
}
}
}
}
}
}
`
var result struct {
Node struct {
Profiles struct {
Edges []struct {
Node struct {
ID string `json:"id"`
Identity struct {
ID string `json:"id"`
} `json:"identity"`
Membership struct {
Role string `json:"role"`
} `json:"membership"`
} `json:"node"`
} `json:"edges"`
} `json:"profiles"`
} `json:"node"`
}
err := owner.ExecuteConnect(query, map[string]any{
"id": owner.GetOrganizationID().String(),
}, &result)
require.NoError(t, err)
// Find the other owner (not the calling owner)
var targetProfileID string
for _, edge := range result.Node.Profiles.Edges {
if edge.Node.Membership.Role == "OWNER" && edge.Node.Identity.ID != owner.GetUserID().String() {
targetProfileID = edge.Node.ID
break
}
}
require.NotEmpty(t, targetProfileID, "Should find another owner to remove")
mutation := `
mutation($input: RemoveUserInput!) {
removeUser(input: $input) {
deletedProfileId
}
}
`
var mutationResult struct {
RemoveUser struct {
DeletedProfileID string `json:"deletedProfileId"`
} `json:"removeUser"`
}
err = owner.ExecuteConnect(mutation, map[string]any{
"input": map[string]any{
"organizationId": owner.GetOrganizationID().String(),
"profileId": targetProfileID,
},
}, &mutationResult)
require.NoError(t, err)
assert.Equal(t, targetProfileID, mutationResult.RemoveUser.DeletedProfileID)
}
func TestUser_List(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)

View File

@@ -1121,7 +1121,7 @@ FROM
iam_membership_profiles p
INNER JOIN iam_memberships m ON m.identity_id = p.identity_id AND m.organization_id = p.organization_id
WHERE
%s
p.%s
AND p.organization_id = @organization_id
AND p.state = @state
AND m.role = @role