feat: Add option to delete or keep API keys when uninstalling plugin#28201
Conversation
Summary of ChangesHello @UMDKyle, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the plugin uninstallation experience by providing users with explicit control over the lifecycle of their API keys and credentials. Previously, these sensitive details would remain in the database even after a plugin was removed, leading to potential security concerns and user confusion upon reinstallation. The new implementation introduces a clear, user-friendly mechanism to either securely delete these credentials or intentionally retain them, directly resolving a critical user feedback and improving data hygiene. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a valuable feature for managing plugin credentials during uninstallation. The backend and frontend changes are comprehensive and well-structured. However, I've identified several critical issues in the backend tests that need immediate attention, as they are not correctly testing the implementation and could lead to a false sense of security. There are also significant performance inefficiencies in the database operations for deleting credentials, which should be refactored to use bulk operations for better performance. On the frontend, there's an opportunity to improve maintainability by reducing code duplication with a custom hook, and there are some UI and internationalization inconsistencies that should be addressed.
api/tests/unit_tests/services/plugin/test_plugin_credential_service.py
Outdated
Show resolved
Hide resolved
api/tests/unit_tests/services/plugin/test_plugin_credential_service.py
Outdated
Show resolved
Hide resolved
api/tests/unit_tests/services/plugin/test_plugin_service_uninstall.py
Outdated
Show resolved
Hide resolved
api/tests/unit_tests/services/plugin/test_plugin_service_uninstall.py
Outdated
Show resolved
Hide resolved
web/app/components/plugins/plugin-detail-panel/detail-header.tsx
Outdated
Show resolved
Hide resolved
c734463 to
78a5274
Compare
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces a valuable feature that allows users to decide whether to delete or retain API keys upon uninstalling a plugin. The implementation is solid, with both backend and frontend changes to support this new functionality. I've identified a couple of areas for improvement: one related to database performance and another concerning internationalization of new UI strings. Overall, this is a well-executed feature addition.
There was a problem hiding this comment.
Pull Request Overview
This PR adds functionality allowing users to choose whether to delete or keep API keys/credentials when uninstalling plugins, directly addressing issue #27531 where credentials persisted after plugin deletion without user awareness.
Key Changes:
- Added backend service (
PluginCredentialService) to query and delete plugin credentials - Enhanced uninstall API endpoint with credential management parameters
- Implemented frontend UI showing credentials and providing delete/keep options before uninstallation
Reviewed Changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
api/services/plugin/plugin_credential_service.py |
New service to retrieve and delete plugin credentials from database |
api/services/plugin/plugin_service.py |
Enhanced uninstall method with credential deletion logic |
api/controllers/console/workspace/plugin.py |
Added credential check endpoint and updated uninstall endpoint with new parameters |
web/service/plugins.ts |
Added credential check function and updated uninstall function signature |
web/app/components/plugins/plugin-item/action.tsx |
Implemented credential check and deletion UI with radio buttons |
web/app/components/plugins/plugin-detail-panel/detail-header.tsx |
Implemented credential check and deletion UI with checkbox |
web/i18n/en-US/plugin.ts |
Added English translations for credential management UI |
Comments suppressed due to low confidence (3)
web/app/components/plugins/plugin-item/action.tsx:12
- Unused import CredentialCheckbox.
import CredentialCheckbox from './credential-checkbox'
web/i18n/en-US/plugin.ts:196
- This property is overwritten by another property in the same object literal.
action: {
checkForUpdates: 'Check for updates',
pluginInfo: 'Plugin info',
delete: 'Remove plugin',
deleteContentLeft: 'Would you like to remove ',
deleteContentRight: ' plugin?',
usedInApps: 'This plugin is being used in {{num}} apps.',
},
api/services/plugin/plugin_service.py:551
- This import of module logging is redundant, as it was previously imported on line 1.
import logging
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
web/app/components/plugins/plugin-detail-panel/detail-header.tsx
Outdated
Show resolved
Hide resolved
web/app/components/plugins/plugin-detail-panel/detail-header.tsx
Outdated
Show resolved
Hide resolved
web/app/components/plugins/plugin-detail-panel/detail-header.tsx
Outdated
Show resolved
Hide resolved
|
Thanks for the PR, please resolve the CI errors :) And you should use existing checkbox component in the project instead. |
|
IMO, whether to delete credentials should not be an option to users, I prefer deleting them forcefully. How do you think about it? @laipz8200 |
Automatically remove plugin provider credentials on uninstall to prevent orphaned keys from being restored when plugin is reinstalled. Fixes langgenius#27531
a8bd363 to
c1b914e
Compare
Hi, I updated the pull request and now api keys will be deleted forcefully. I think this is better and sovles the problem with smaller change. |
- Move sqlalchemy, db, and ProviderCredential imports to file top - Remove local imports from uninstall() method - Addresses reviewer feedback
826976d to
e64caca
Compare
|
@crazywoola Thank you for merging the latest main branch! The requested changes have been implemented. Ready for review. |
|
Yes, it's better to delete them forcefully. |
Description
Summary
This PR automatically deletes plugin credentials when uninstalling a plugin, preventing orphaned API keys from persisting in the database.
Updated Implementation (Nov 29, 2025): Following review feedback from @Yeuoly, this PR has been completely refactored to use automatic forced deletion instead of user selection.
Problem (Issue #27531)
When users deleted a plugin, associated API keys remained in the database:
User complaint:
Solution
Simple automatic deletion:
Changes
Backend (
api/services/plugin/plugin_service.py)Modified the
uninstall()method to:ProviderCredentialentries (matchingplugin_id/%pattern)@staticmethod
def uninstall(tenant_id: str, plugin_installation_id: str) -> bool:
# Get plugin info before uninstalling
plugins = manager.list_plugins(tenant_id)
plugin = next((p for p in plugins if p.installation_id == plugin_installation_id), None)
%logging format (Python best practice)Code Comparison
Previous approach: +435 −23 lines (user selection UI, multiple components)
Current approach: +57 −0 lines (automatic deletion, backend only)
Simplification:
Testing
Manual Testing:
Tested with Docker deployment:
Database Impact
Affected Tables:
provider_credential- Provider-level credentials deleted via pattern matchplugin_id/%Query Pattern:
DELETE FROM provider_credential
WHERE tenant_id = ?
AND provider_name LIKE 'plugin_id/%'---
How This Solves Issue #27531
Before:
After:
Related Issue
Fixes #27531
Checklist