Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ Changelog
- Configured the `@@remove-from-esign-session` the same way as `@@remove-item-from-esign-session`
so relying on an `available` method to show it only if a context is in a session.
[gbastien]
- Fixed faceted viewlet broken because sessions format changed from list to OrderedDict.
[gbastien]

1.0a2 (2026-02-06)
------------------
Expand Down
17 changes: 9 additions & 8 deletions src/imio/esign/browser/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from imio.esign.config import get_registry_signing_users_email_content
from imio.esign.utils import create_external_session
from imio.esign.utils import get_session_annotation
from imio.esign.utils import get_session_info
from imio.esign.utils import get_sessions_for
from imio.esign.utils import get_state_description
from imio.esign.utils import remove_session
Expand Down Expand Up @@ -215,18 +216,18 @@ def render(self):

@property
def sessions(self):
# caching
if hasattr(self, "_cached_session"):
return self._cached_session
session_id = self.request.form.get("esign_session_id[]", None)
try:
session_id = int(session_id)
except (TypeError, ValueError):
return []
sessions = get_session_annotation()["sessions"]
session = sessions.get(session_id)
if not session:
return []
session = deepcopy(session)
session["id"] = session_id
return [session]
return {}
session = {session_id: get_session_info(session_id)}
# caching
self._cached_session = session
return session

def get_table_rows(self, column):
"""Get the table rows following the column"""
Expand Down
9 changes: 7 additions & 2 deletions src/imio/esign/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,15 +331,20 @@ def get_session_annotation(portal=None):
return annotations["imio.esign"]


def get_session_info(session_id, portal=None):
def get_session_info(session_id, portal=None, readonly=True):
"""Return a session info for a given numbering.

:param session_id: the session id to return
:param portal: portal if necessary to get the session annotation
:param readonly: return a copy of stored data to avoid modifying it
"""
annot = get_session_annotation(portal=portal)
session = {}
if session_id in annot['sessions']:
return annot['sessions'][session_id]
session = annot['sessions'][session_id]
if readonly:
session = deepcopy(session)
return session
Comment on lines +334 to +347
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Avoid changing get_session_info semantics in this PR.

This introduces a default deepcopy behavior in a shared utility, which is broader than the PR objective and can break callers expecting a live session mapping.

💡 Suggested adjustment
-def get_session_info(session_id, portal=None, readonly=True):
+def get_session_info(session_id, portal=None):
@@
-    if session_id in annot['sessions']:
-        session = annot['sessions'][session_id]
-        if readonly:
-            session = deepcopy(session)
+    if session_id in annot['sessions']:
+        session = annot['sessions'][session_id]
     return session

If read-only behavior is needed for the viewlet, apply deepcopy in the viewlet only.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def get_session_info(session_id, portal=None, readonly=True):
"""Return a session info for a given numbering.
:param session_id: the session id to return
:param portal: portal if necessary to get the session annotation
:param readonly: return a copy of stored data to avoid modifying it
"""
annot = get_session_annotation(portal=portal)
session = {}
if session_id in annot['sessions']:
return annot['sessions'][session_id]
session = annot['sessions'][session_id]
if readonly:
session = deepcopy(session)
return session
def get_session_info(session_id, portal=None):
"""Return a session info for a given numbering.
:param session_id: the session id to return
:param portal: portal if necessary to get the session annotation
"""
annot = get_session_annotation(portal=portal)
session = {}
if session_id in annot['sessions']:
session = annot['sessions'][session_id]
return session
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/imio/esign/utils.py` around lines 334 - 347, The change made
get_session_info(session_id, portal=None, readonly=True) to deepcopy sessions by
default which alters shared utility semantics; revert the default readonly to
False in get_session_info and ensure deepcopy is only performed when readonly is
explicitly True (keep usage of deepcopy inside get_session_info guarded by the
readonly flag), and move any read-only deepcopy usage from callers (e.g., the
viewlet) into the viewlet code so callers that expect the live session mapping
continue to receive the original mapping returned by get_session_annotation and
the session variable.



def remove_context_from_session(context_uids):
Expand Down
Loading