Skip to content

Commit b5f24bd

Browse files
committed
Added external watchers for esign sessions
1 parent 9434308 commit b5f24bd

File tree

4 files changed

+65
-3
lines changed

4 files changed

+65
-3
lines changed

CHANGES.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ Changelog
2525
[gbastien]
2626
- Avoided duplicated filenames and kept files ordering in session.
2727
[sgeulette]
28+
- Added external watchers for esign sessions.
29+
[chris-adam]
2830

2931
1.0a2 (2026-02-06)
3032
------------------

src/imio/esign/browser/settings.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# -*- coding: utf-8 -*-
22

3+
from collective.behavior.talcondition.utils import _evaluateExpression
34
from imio.esign import _
5+
from plone import api
46
from plone.app.registry.browser.controlpanel import ControlPanelFormWrapper
57
from plone.app.registry.browser.controlpanel import RegistryEditForm
68
from plone.app.z3cform.wysiwyg import WysiwygFieldWidget
@@ -10,6 +12,8 @@
1012
from zope.interface import Interface
1113
from zope.interface import Invalid
1214

15+
import re
16+
1317

1418
def validate_vat_number(va_nb):
1519
"""Validate the VAT number format. It should start with BE followed by 10 digits,
@@ -39,6 +43,37 @@ def validate_vat_number(va_nb):
3943
return True
4044

4145

46+
def validate_external_watchers(tal_expression):
47+
"""Validate external watchers is a valid TAL expression with valid email addresses."""
48+
49+
if not tal_expression or not tal_expression.strip():
50+
return True
51+
52+
try:
53+
portal = api.portal.get()
54+
except Exception:
55+
return True
56+
57+
if portal is None:
58+
return True
59+
60+
try:
61+
result = _evaluateExpression(portal, expression=tal_expression, raise_on_error=True)
62+
except Exception as e:
63+
raise Invalid(_("Invalid TAL expression: %s") % str(e))
64+
65+
if not result:
66+
return True
67+
68+
email_re = re.compile(r'^[^@\s]+@[^@\s]+\.[^@\s]+$')
69+
for email in result.split(","):
70+
email = email.strip()
71+
if email and not email_re.match(email):
72+
raise Invalid(_("Invalid email address: %s") % email)
73+
74+
return True
75+
76+
4277
class IImioEsignSettings(Interface):
4378

4479
enabled = schema.Bool(
@@ -103,6 +138,14 @@ class IImioEsignSettings(Interface):
103138
required=True,
104139
)
105140

141+
external_watchers = schema.TextLine(
142+
title=_("External watchers"),
143+
description=_("TAL expression returning a list of comma-separated email addresses."),
144+
constraint=validate_external_watchers,
145+
required=False,
146+
default=u"string:",
147+
)
148+
106149

107150
class ImioEsignSettings(RegistryEditForm):
108151
schema = IImioEsignSettings

src/imio/esign/config.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# -*- coding: utf-8 -*-
22

3+
from collective.behavior.talcondition.utils import _evaluateExpression
34
from plone import api
45

56

@@ -39,6 +40,14 @@ def get_registry_max_session_size(default=100):
3940
return api.portal.get_registry_record("imio.esign.max_session_size", default=default)
4041

4142

43+
def get_registry_external_watchers():
44+
value = api.portal.get_registry_record("imio.esign.external_watchers", default="")
45+
value = _evaluateExpression(api.portal.get(), value)
46+
if not value:
47+
return []
48+
return [ew.strip() for ew in value.split(",") if ew.strip()]
49+
50+
4251
def set_registry_enabled(value):
4352
api.portal.set_registry_record("imio.esign.enabled", value)
4453

@@ -75,6 +84,10 @@ def set_registry_max_session_size(value):
7584
api.portal.set_registry_record("imio.esign.max_session_size", value)
7685

7786

87+
def set_registry_external_watchers(value):
88+
api.portal.set_registry_record("imio.esign.external_watchers", value)
89+
90+
7891
SIGNERS_EMAIL_CONTENT = u"""
7992
<meta charset="UTF-8"><tal:global>
8093
<p style="font-weight: bold;" tal:condition="nothing">!! Attention: ne pas modifier ceci directement mais passer

src/imio/esign/utils.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from imio.esign import _tr as _
55
from imio.esign import API_ROOT_URL
66
from imio.esign import logger
7+
from imio.esign.config import get_registry_external_watchers
78
from imio.esign.config import get_registry_file_url
89
from imio.esign.config import get_registry_max_session_size
910
from imio.esign.config import get_registry_seal_code
@@ -151,6 +152,9 @@ def create_external_session(session_id, esign_root_url=None):
151152
vat_number = get_registry_vat_number(default="BE0000000097")
152153
data_payload["commonData"]["vatNumber"] = vat_number
153154

155+
watchers = list(session.get("watchers", []))
156+
external_watchers = get_registry_external_watchers()
157+
watchers.extend([ew for ew in external_watchers if ew not in watchers])
154158
signers = [fdic["email"] for fdic in session["signers"]]
155159
if signers:
156160
data_payload["signData"] = {
@@ -160,8 +164,8 @@ def create_external_session(session_id, esign_root_url=None):
160164
sign_code = get_registry_sign_code()
161165
if sign_code:
162166
data_payload["signData"]["signCode"] = sign_code
163-
if session.get("watchers", ()):
164-
data_payload["signData"]["watchers"] = list(session["watchers"])
167+
if watchers:
168+
data_payload["signData"]["watchers"] = watchers
165169

166170
if session["seal"]:
167171
seal_email = get_registry_seal_email()
@@ -176,7 +180,7 @@ def create_external_session(session_id, esign_root_url=None):
176180
"users": [seal_email],
177181
# "placeholderName": "SCEAU", # default
178182
"acroform": True,
179-
"watchers": list(session.get("watchers", [])),
183+
"watchers": watchers,
180184
"sealCode": seal_code,
181185
}
182186

0 commit comments

Comments
 (0)