Both LDAP and OAuth registration checked user count before insert to determine whether to assign admin role. With multiple workers, concurrent first-user registrations could each see zero users and both create admin accounts.
Applies the insert-first-check-after pattern already used by signup_handler: insert with DEFAULT_USER_ROLE, then atomically check get_num_users()==1 and promote only the sole user to admin.
- URL-encodes the OAuth error message when constructing the redirect URL in the OIDC callback handler
- Without encoding, error messages containing spaces, ampersands, or other special characters produce malformed URLs that the frontend cannot parse correctly
- The custom OAuth client callback handler already correctly uses urllib.parse.quote_plus() for the same purpose; this fix brings the OIDC handler in line with that pattern
Co-authored-by: gambletan <tan@gambletan.com>
* fix: replace bare except with except Exception in main.py
* fix: replace bare except with Exception in oauth.py
In Python 3, bare 'except:' is discouraged as it catches all
SystemExit and KeyboardInterrupt exceptions. Changed to 'except Exception:'
to only catch actual exceptions.
* sequential
* zero default
* fix
* fix: preserve absolute paths in sqlite+sqlcipher URLs
Previously, the connection logic incorrectly stripped the leading slash
from `sqlite+sqlcipher` paths, forcibly converting absolute paths
(e.g., `sqlite+sqlcipher:////app/data.db`) into relative paths
(which became `app/data.db`). This caused database initialization failures
when using absolute paths, such as with Docker volume mounts.
This change removes the slash-stripping logic, ensuring that absolute
path conventions (starting with `/`) are respected while maintaining
support for relative paths (which do not start with `/`).
* fix: MCP OAuth 2.1 token exchange and multi-node propagation
Fix two MCP OAuth 2.1 bugs affecting tool server authentication:
1. Token exchange failing with duplicate credentials (#19823)
- Removed explicit client_id/client_secret passing in handle_callback()
- Authlib already has credentials configured during add_client(),
passing them again caused concatenation (e.g., "ID1,ID1") and 401 errors
- Added token validation to detect missing access_token and provide
clear error messages instead of cryptic database constraint errors
2. OAuth clients not propagating across multi-node setups (#19901)
- Updated get_client() and get_client_info() to auto-lazy-load
OAuth clients from the Redis-synced TOOL_SERVER_CONNECTIONS config
- Clients are now instantiated on-demand on any node that needs them
Fixes#19823, #19901
* Update db.py
* Update wrappers.py