mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-14 00:16:20 +00:00
Connections own their credentials
Migration 0038 moves every stored secret (OAuth tokens, MCP OAuth tokens and client registrations, API keys) into the connection's encrypted envelope, links API-key tools to one connection per distinct credential, allows several accounts per provider, and adds credential_mode to sources and tools. OAuth MCP tools keep resolving each member's own token, as they did before. docsgpt.connectors.service is now the only reader of OAuth tokens: get_valid_token_info refreshes under a row lock and persists rotated refresh tokens, and a revoked grant flags the connection, pauses its sources and notifies the owner. Loaders build from a connection (BaseConnectorLoader.from_connection), so scheduled sync covers Drive, SharePoint and Confluence sources with no browser. S3 and Reddit keys stay on the connection instead of in remote_data. New endpoints: POST /api/connections, /setup, /reconnect, /picker-token, /claim, DELETE /api/connections/<id>, per-action permissions and MCP refresh-tools. Upload, file listing, sync and validate-session take a connection_id; session tokens keep working for this release. The tool executor reads credentials from the resolved connection (owner or member mode) and pauses on a Connect card when a connection needs signing in. docsgpt connectors reencrypt rewrites stored credentials after a key rotation.
This commit is contained in:
1 parent
667d4bbab0
commit
3511004f50
54 files changed
+4007
-754
No files matched your search
@@ -285,6 +285,28 @@ def _add_deploy_commands(commands) -> None:
|
||||
dev.set_defaults(func=_deploy("dev"), deploy=True)
|
||||
|
||||
|
||||
def _connectors(args: argparse.Namespace) -> int:
|
||||
"""``docsgpt connectors reencrypt``: move every credential onto the current key."""
|
||||
if getattr(args, "connectors_action", None) != "reencrypt":
|
||||
print("usage: docsgpt connectors reencrypt", file=sys.stderr)
|
||||
return 2
|
||||
from docsgpt.connectors.service import reencrypt_all
|
||||
|
||||
counts = reencrypt_all()
|
||||
print(
|
||||
f"docsgpt: re-encrypted {counts['rewritten']} connection(s), "
|
||||
f"{counts['current']} already current, {counts['failed']} unreadable",
|
||||
file=sys.stderr,
|
||||
)
|
||||
if counts["failed"]:
|
||||
print(
|
||||
"docsgpt: unreadable connections were marked 'Reconnect needed'; "
|
||||
"their owners must reconnect them.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 1 if counts["failed"] else 0
|
||||
|
||||
|
||||
def build_parser() -> argparse.ArgumentParser:
|
||||
parser = argparse.ArgumentParser(prog="docsgpt", description="DocsGPT: private AI for agents, assistants and search.")
|
||||
parser.add_argument("--version", action="version", version=f"docsgpt {__version__}")
|
||||
@@ -315,6 +337,14 @@ def build_parser() -> argparse.ArgumentParser:
|
||||
migrate.add_argument("--no-create", dest="create_db", action="store_false", help="fail instead of creating a missing database")
|
||||
migrate.set_defaults(func=_migrate)
|
||||
|
||||
connectors = commands.add_parser("connectors", help="manage stored connector credentials")
|
||||
connector_actions = connectors.add_subparsers(dest="connectors_action", metavar="<action>")
|
||||
connector_actions.add_parser(
|
||||
"reencrypt",
|
||||
help="rewrite every stored credential with ENCRYPTION_SECRET_KEY (after a key rotation)",
|
||||
)
|
||||
connectors.set_defaults(func=_connectors)
|
||||
|
||||
for name, (module, help_text) in SCRIPTS.items():
|
||||
commands.add_parser(name, help=f"{help_text} (docsgpt.scripts.{module})", add_help=False)
|
||||
|
||||
|
||||
Reference in new issue
Block a user