graphql: Add mutation to delete custom attributes from users
What does this MR do and why?
Implements a GraphQL mutation deleteUserCustomAttribute to delete custom attributes from users, providing feature parity with the existing REST API DELETE /users/:id/custom_attributes/:key endpoint.
This MR follows the patterns and learnings established in !217084 (merged) (project custom attributes delete mutation), incorporating feedback from the GitLab team review.
Key implementation details (aligned with project mutation):
- Uses verb-noun naming pattern:
DeleteUserCustomAttribute(consistent withDeleteProjectCustomAttribute) - Uses shared
CustomAttributes::DestroyServicefor business logic - Uses shared
Types::CustomAttributeType(not a project-specific type) - Uses
:delete_custom_attributepermission (specific to delete action) - Uses
GlobalIDType[::User]for user lookup - Request specs only (no unit specs, following established patterns)
Changes:
- Add
Mutations::Users::CustomAttributes::Deletemutation class - Add
:delete_custom_attributepermission toUserPolicyfor admins - Mount mutation in
MutationTypewith milestone 18.9 - Add policy spec for
:delete_custom_attributepermission - Add request specs covering authorization, success, and error scenarios
Example mutation:
mutation {
deleteUserCustomAttribute(input: {
userId: "gid://gitlab/User/1"
key: "department"
}) {
customAttribute {
key
value
}
errors
}
}
References
- Part of #349396
- Follows patterns from: !217084 (merged) (project custom attributes delete mutation)
- REST API implementation:
lib/api/custom_attributes_endpoints.rb:86-93 - Shared service:
app/services/custom_attributes/destroy_service.rb - Shared type:
app/graphql/types/custom_attribute_type.rb
Screenshots or screen recordings
Not applicable - backend API changes only, no UI modifications.
How to set up and validate locally
- Ensure you have an admin user (or create one in Rails console with
User.first.update!(admin: true)) - Create a custom attribute on a user via Rails console:
user = User.first user.custom_attributes.create!(key: 'department', value: 'engineering') - Navigate to GraphiQL explorer at
/-/graphql-explorer - Run the following mutation (replace with your user ID):
mutation { deleteUserCustomAttribute(input: { userId: "gid://gitlab/User/1" key: "department" }) { customAttribute { key value } errors } } - Verify the deleted attribute is returned and the attribute is removed from the user
- Try deleting a non-existent key and verify error is returned in the
errorsarray
MR acceptance checklist
Please evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
MR Checklist (@gerardo-navarro)
- Changelog entry added, if necessary
- Documentation created/updated via this MR
- Documentation reviewed by technical writer or follow-up review issue created
- Tests added for this feature/bug
- Tested in all supported browsers - N/A (backend only)
- Conforms to the code review guidelines
- Conforms to the style guides
- Conforms to the javascript style guides - N/A (no JS changes)
- Conforms to the database guides - N/A (no DB changes)
- Conforms to the merge request performance guidelines
-
Admin-only authorization enforced via
:delete_custom_attributeability -
Uses shared
CustomAttributes::DestroyService(consistent with project mutation) -
Uses shared
Types::CustomAttributeType(not duplicate type) - Follows naming convention from !217084 (merged)
Edited by Gerardo Navarro