Skip to content

feat: Add option to delete or keep API keys when uninstalling plugin#28201

Merged
crazywoola merged 6 commits intolanggenius:mainfrom
UMDKyle:feature/plugin-credential-deletion-option
Jan 14, 2026
Merged

feat: Add option to delete or keep API keys when uninstalling plugin#28201
crazywoola merged 6 commits intolanggenius:mainfrom
UMDKyle:feature/plugin-credential-deletion-option

Conversation

@UMDKyle
Copy link
Contributor

@UMDKyle UMDKyle commented Nov 13, 2025

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.

"IMO, whether to delete credentials should not be an option to users, I prefer deleting them forcefully." - @Yeuoly


Problem (Issue #27531)

When users deleted a plugin, associated API keys remained in the database:

  • ❌ Credentials silently retained after plugin deletion
  • ❌ No cleanup of unused credentials
  • ❌ API keys automatically restored on plugin reinstall
  • ❌ Users confused about credential persistence

User complaint:

"I deleted the OpenAI plugin, and after reinstalling it, the original API key was automatically restored. I want to clear it."


Solution

Simple automatic deletion:

  • ✅ When plugin is uninstalled, all associated credentials are automatically deleted
  • ✅ No user interaction required
  • ✅ Clean database state after uninstall
  • ✅ Plugin reinstall requires fresh API key configuration

Changes

Backend (api/services/plugin/plugin_service.py)

Modified the uninstall() method to:

  1. Get plugin information before uninstalling
  2. Query all associated ProviderCredential entries (matching plugin_id/% pattern)
  3. Delete all found credentials
  4. Proceed with plugin uninstall

@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)

if plugin:
    # Delete all credentials matching plugin_id/%
    credentials = db.session.scalars(
        select(ProviderCredential).where(
            ProviderCredential.tenant_id == tenant_id,
            ProviderCredential.provider_name.like(f"{plugin_id}/%"),
        )
    ).all()
    
    for cred in credentials:
        db.session.delete(cred)
    db.session.commit()

return manager.uninstall(tenant_id, plugin_installation_id)**Key Features:**
  • Uses lazy % logging format (Python best practice)
  • Graceful error handling - continues uninstall even if credential deletion fails
  • Logs credential deletion operations for debugging

Code Comparison

Previous approach: +435 −23 lines (user selection UI, multiple components)
Current approach: +57 −0 lines (automatic deletion, backend only)

Simplification:

  • ✅ 87% less code
  • ✅ No frontend changes needed
  • ✅ Simpler to maintain
  • ✅ Follows reviewer recommendation

Testing

Manual Testing:

  1. ✅ Install plugin with API key configuration
  2. ✅ Uninstall plugin → credentials automatically deleted
  3. ✅ Reinstall plugin → requires new API key (old one gone)
  4. ✅ Database queries confirm no orphaned credentials

Tested with Docker deployment:

  • All services running correctly
  • Plugin uninstall flow working as expected
  • No database orphaned records

Database Impact

Affected Tables:

  • provider_credential - Provider-level credentials deleted via pattern match plugin_id/%

Query Pattern:
DELETE FROM provider_credential
WHERE tenant_id = ?
AND provider_name LIKE 'plugin_id/%'---

How This Solves Issue #27531

Before:

  • User deletes OpenAI plugin
  • API key remains in database
  • Plugin reinstall → old API key restored
  • ❌ User frustrated, wants to clear it

After:

  • User deletes OpenAI plugin
  • API key automatically deleted from database
  • Plugin reinstall → requires new API key
  • ✅ Clean state, issue resolved

Related Issue

Fixes #27531


Checklist

  • Code follows project coding standards
  • Self-reviewed the code
  • Added necessary comments
  • Changes generate no new warnings
  • Tested locally with Docker
  • CI checks passing
  • Addressed all review feedback

@dosubot dosubot bot added size:XXL This PR changes 1000+ lines, ignoring generated files. 💪 enhancement New feature or request labels Nov 13, 2025
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @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

  • User Control over API Keys: Introduces a user-facing option to either delete or retain associated API keys and credentials when uninstalling a plugin, addressing a long-standing issue where credentials would persist silently.
  • Two-Step Deletion Process: Implements a new workflow where, upon initiating plugin uninstallation, the system first checks for associated credentials and then presents the user with clear choices: delete all credentials (default) or keep them for future reinstallation.
  • New Backend Service for Credential Management: A dedicated PluginCredentialService has been added to handle the retrieval, specific deletion, and bulk deletion of plugin-related credentials from the database.
  • Updated API Endpoints and Frontend UI: New API endpoints facilitate credential checking, and existing uninstall endpoints now accept parameters for credential deletion. The frontend UI has been updated with radio buttons and a list display of credentials to enable user choice.
  • Comprehensive Test Coverage: The feature is backed by 41 new tests, covering both backend logic (26 tests for services and API controllers) and frontend components (15 tests for service functions, state management, and integration flows).
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@alterxyz alterxyz requested review from Yeuoly and crazywoola and removed request for Yeuoly and crazywoola November 14, 2025 04:07
@alterxyz alterxyz marked this pull request as draft November 14, 2025 04:09
@UMDKyle UMDKyle force-pushed the feature/plugin-credential-deletion-option branch from c734463 to 78a5274 Compare November 15, 2025 12:20
@asukaminato0721
Copy link
Contributor

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@alterxyz alterxyz marked this pull request as ready for review November 15, 2025 19:33
Copilot AI review requested due to automatic review settings November 15, 2025 19:33
@dosubot dosubot bot added size:L This PR changes 100-499 lines, ignoring generated files. and removed size:XXL This PR changes 1000+ lines, ignoring generated files. labels Nov 15, 2025
Copy link
Contributor

Copilot AI left a 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 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

  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.

@crazywoola
Copy link
Member

Thanks for the PR, please resolve the CI errors :) And you should use existing checkbox component in the project instead.

@crazywoola crazywoola self-assigned this Nov 26, 2025
@Yeuoly
Copy link
Contributor

Yeuoly commented Nov 26, 2025

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
@UMDKyle UMDKyle force-pushed the feature/plugin-credential-deletion-option branch from a8bd363 to c1b914e Compare November 29, 2025 23:16
@dosubot dosubot bot added size:M This PR changes 30-99 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Nov 29, 2025
@UMDKyle
Copy link
Contributor Author

UMDKyle commented Nov 30, 2025

IMO, whether to delete credentials should not be an option to users, I prefer deleting them forcefully.

How do you think about it? @laipz8200

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
@UMDKyle UMDKyle force-pushed the feature/plugin-credential-deletion-option branch from 826976d to e64caca Compare November 30, 2025 23:47
@UMDKyle
Copy link
Contributor Author

UMDKyle commented Dec 28, 2025

@crazywoola Thank you for merging the latest main branch! The requested changes have been implemented. Ready for review.

@laipz8200
Copy link
Member

Yes, it's better to delete them forcefully.

@dosubot dosubot bot added the lgtm This PR has been approved by a maintainer label Jan 14, 2026
@crazywoola crazywoola merged commit 7f9884e into langgenius:main Jan 14, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💪 enhancement New feature or request lgtm This PR has been approved by a maintainer size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

I deleted the OpenAI plugin, and after reinstalling it, the original API key was automatically restored. I want to clear it.

7 participants