-
Notifications
You must be signed in to change notification settings - Fork 273
Add admin namespace deletion feature via API (fixes #1519) #1547
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Implements admin namespace deletion through the API instead of requiring manual SQL statements. Backend: Add deleteNamespace method with cascade deletion, two DELETE endpoints, storage cleanup, cache invalidation, and audit logging. Frontend: Add Delete Namespace button in admin dashboard with confirmation dialog and error handling. Testing: Add 12 comprehensive test cases covering all scenarios including edge cases.
|
@netomi Please review this and let me know if any changes are needed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds admin namespace deletion functionality via API, eliminating the need for manual SQL operations. It implements a complete deletion flow that handles all related data (extensions, versions, files, reviews, memberships) with proper cascade, cache clearing, and search index updates.
Changes:
- Added backend
deleteNamespace()method inAdminServicewith transactional support and proper cleanup - Added two DELETE endpoints in
AdminAPIfor session-based and token-based authentication - Added frontend
deleteNamespace()method and UI button with confirmation dialog in namespace detail view
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| server/src/main/java/org/eclipse/openvsx/admin/AdminService.java | Core namespace deletion logic with cascade deletion and cleanup |
| server/src/main/java/org/eclipse/openvsx/admin/AdminAPI.java | REST API endpoints for namespace deletion with authentication |
| server/src/test/java/org/eclipse/openvsx/admin/AdminAPITest.java | Comprehensive test coverage for namespace deletion scenarios |
| webui/src/extension-registry-service.ts | Frontend service method for namespace deletion API calls |
| webui/src/pages/user/user-settings-namespace-detail.tsx | UI integration with delete button and confirmation dialog |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <ButtonWithProgress | ||
| variant='outlined' | ||
| color='error' | ||
| working={deleting} | ||
| onClick={handleDelete}> | ||
| Delete Namespace | ||
| </ButtonWithProgress> |
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ButtonWithProgress component does not accept a 'variant' prop. The component hardcodes variant='contained' on line 17 of button-with-progress.tsx. Remove the variant='outlined' prop.
| entityManager.remove(namespace); | ||
|
|
||
| // Update search index | ||
| search.updateSearchEntries(extensions.toList()); |
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After deleting extensions, updateSearchEntries should not be called with the deleted extensions. This will attempt to re-index extensions that have just been removed. Use removeSearchEntries with extension IDs instead, or call search.removeSearchEntry() for each extension before removal.
| // Remove file resources | ||
| var resources = repositories.findFiles(version); | ||
| for (var resource : resources) { | ||
| storageUtil.removeFile(resource); |
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
File removal should be done asynchronously via job scheduler, similar to removeExtensionVersion() on line 243 which uses scheduler.enqueue(new RemoveFileJobRequest(resource)). This prevents blocking the transaction on potentially slow external storage operations.
| storageUtil.removeFile(resource); | |
| scheduler.enqueue(new RemoveFileJobRequest(resource)); |
| for (var extension : extensions) { | ||
| // Remove reviews (associated with extension, not version) | ||
| var reviews = repositories.findAllReviews(extension); | ||
| for (var review : reviews) { | ||
| entityManager.remove(review); | ||
| } | ||
|
|
||
| // Remove all versions and their resources | ||
| var versions = repositories.findVersions(extension); | ||
| for (var version : versions) { | ||
| // Remove file resources | ||
| var resources = repositories.findFiles(version); | ||
| for (var resource : resources) { | ||
| storageUtil.removeFile(resource); | ||
| entityManager.remove(resource); | ||
| } | ||
|
|
||
| // Remove the version | ||
| entityManager.remove(version); | ||
| } | ||
|
|
||
| // Clear cache for the extension | ||
| cache.evictExtensionJsons(extension); | ||
| cache.evictLatestExtensionVersion(extension); | ||
|
|
||
| // Remove the extension | ||
| entityManager.remove(extension); | ||
| } |
Copilot
AI
Jan 14, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The namespace deletion logic does not handle deprecated extension references. When an extension is deleted, other extensions that reference it as a replacement should have their replacement field cleared. See deleteExtension() on lines 217-221 which handles this with findDeprecatedExtensions().
Adds API-based admin namespace deletion, removing the need for manual SQL. Fixes issue #1519.
Changes
Backend
Added
deleteNamespace()inAdminServiceAdded DELETE endpoints in
AdminAPIDELETE /admin/namespace/{namespaceName}(session-based auth)DELETE /admin/api/namespace/{namespaceName}?token={token}(token-based auth)Frontend
Added
deleteNamespace()to AdminServiceAdded “Delete Namespace” button in admin namespace detail view
Testing
Added 12 test cases covering:
Benefits
Breaking Changes
None
Related Issue
Fixes #1519
If you want it even shorter (GitHub PR–style) or more technical, tell me and I’ll trim it further.