Add REST API endpoint to restore an organization
What does this MR do and why?
Closes #599346
Administrators can now restore a soft-deleted organization with the REST API, using POST /api/v4/organizations/:id/restore. Until now, only the GraphQL organizationRestore mutation could do this. The endpoint follows the same rules as the mutation:
201with the restored organization when it works.400withOrganization is not soft-deletedwhen the organization is active.403for users who aren't administrators, and for administrators without admin mode.404when the organization doesn't exist.
Some decisions, and I'm happy to change any of them:
- When someone creates a fine-grained access token, only administrators are offered the restore permission. The mutation does the same, and the permissions check requires both to match.
- It returns
201 Created, likePOST /api/v4/groups/:id/restore. - No feature flag. The endpoint is marked as an experiment, like
DELETE /api/v4/organizations/:id, which has no flag either. - The endpoint description says GitLab 19.6, because I don't expect this to merge before the 19.5 release.
Three files are normally generated: the OpenAPI v3 docs, the fine-grained token permissions page, and the Cells route list. I wrote the entries by hand, and the jobs that check them passed (static-analysis, permissions-verify, cells-routes:up-to-date).
I added request tests for the restore itself, for each error response above, for 401 without a user, and for fine-grained tokens. They ran in pipeline 2933495983: rspec integration predictive passed with 46 examples, 0 failures and 6 pending. rubocop passed too. Locally I ran ruby -c on the changed Ruby files, and parsed the OpenAPI file as YAML. The rest runs in the pipeline.
The issue asks for docs on the organizations API page. I left them out, like for the delete endpoint, because !257880 (merged) removed the soft-delete docs while organizations are in beta. We agreed on this in the review.
I have one question:
- Danger says the HTTP Router route snapshot doesn't have the new route yet, and
cells-routes:router-in-syncfailed (it's allowed to fail). The same warning lists 11 other routes that aren't from this MR. Do I need to open the paired snapshot MR in the HTTP Router project, or does the Cells team refresh the snapshot?
References
- Issue: #599346
- Epic: &22387
- GraphQL mutation: #599344 (closed)
- REST soft-delete endpoint: #599345 (closed)
- Soft-delete docs removed for the beta: !257880 (merged)
Screenshots or screen recordings
Not applicable. This is a new API endpoint, with no UI change.
How to set up and validate locally
- Create a personal access token for an administrator with the
apiscope (andadmin_modeif admin mode is enabled). - In the Rails console, soft-delete an organization:
organization = Organizations::Organization.find_by_path('my-org') organization.soft_delete(transition_user: User.find_by_username('root')) organization.reload.state # => "soft_deleted" - Restore it with the API:
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \ "http://gdk.test:3000/api/v4/organizations/<organization_id>/restore" - The response should be
201with the organization, andorganization.reload.stateshould be"active". - Run the same
curlagain. It should return400with{"message":"Organization is not soft-deleted"}.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
Implemented with AI assistance; I reviewed and tested the changes.