Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
## 1.4.3 (unreleased)


- Nothing changed yet.
- DEVOPS-339 : Fix ConflictError when multiple Zope instances start simultaneously and commit OIDC settings
[remdub]


## 1.4.2 (2025-12-10)
Expand Down
12 changes: 10 additions & 2 deletions src/pas/plugins/kimug/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from plone import api
from Products.PluggableAuthService.interfaces.plugins import IAuthenticationPlugin
from urllib.parse import urlparse
from ZODB.POSException import ConflictError
from zope.annotation.interfaces import IAnnotations
from zope.component.hooks import setSite

Expand Down Expand Up @@ -74,8 +75,15 @@ def set_oidc_settings(context):

_set_allowed_groups(oidc)

transaction.commit()
logger.info("OIDC settings set with set_oidc_settings()")
try:
transaction.commit()
logger.info("OIDC settings set with set_oidc_settings()")
except ConflictError:
transaction.abort()
logger.warning(
"ConflictError committing OIDC settings: another instance already "
"committed the same values. Settings are correct; skipping."
)
else:
logger.warning("Could not find OIDC plugin, not setting OIDC settings")

Expand Down
19 changes: 19 additions & 0 deletions tests/utils/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from pas.plugins.kimug import utils
from plone import api
from unittest.mock import patch
from ZODB.POSException import ConflictError
from zope.annotation.interfaces import IAnnotations

import os
Expand Down Expand Up @@ -122,3 +124,20 @@ def test_set_allowed_groups(self, portal):
utils._set_allowed_groups(oidc)

assert oidc.allowed_groups == ("group.1 is - the first!",)


class TestSetOidcSettings:
def test_conflict_error_is_handled(self, portal):
"""ConflictError on commit must be caught and transaction aborted — no exception raised."""
with patch("pas.plugins.kimug.utils.transaction") as mock_txn:
mock_txn.commit.side_effect = ConflictError()
utils.set_oidc_settings(None)
mock_txn.abort.assert_called_once()

def test_settings_are_applied(self, portal):
"""set_oidc_settings should apply environment values to the OIDC plugin."""
with patch.dict(os.environ, {"keycloak_client_id": "my-client"}):
with patch("pas.plugins.kimug.utils.transaction"):
utils.set_oidc_settings(None)
oidc = utils.get_plugin()
assert oidc.client_id == "my-client"
Loading