From d8ebb7dd2e7b22904c9bf3e9d99f3094564090e8 Mon Sep 17 00:00:00 2001
From: Ivan Tyagov <ivan@nexedi.com>
Date: Wed, 7 Sep 2011 16:17:11 +0300
Subject: [PATCH] Add new alarm to 'expire' already passed (in time)
 Authentication Failures. Add a new report (part of worklist) to show blocked
 user account list.

---
 .../expire_authentication_events.xml          |  91 ++++++++
 .../Person_getListboxUrl.xml                  |  70 ++++++
 .../Person_isLoginBlocked.xml                 |   3 +-
 .../Person_unblockLogin.xml                   |   7 +-
 ...ntModule_expireAuthenticationEventList.xml |  85 +++++++
 ...temEventModule_getBlockedUserLoginList.xml | 110 +++++++++
 ...ystemEventModule_viewBlockUseLoginList.xml | 154 +++++++++++++
 .../listbox.xml                               | 209 ++++++++++++++++++
 .../listbox_unblockHTML.xml                   | 137 ++++++++++++
 bt5/erp5_authentication_policy/bt/revision    |   2 +-
 .../bt/template_path_list                     |   1 +
 11 files changed, 865 insertions(+), 4 deletions(-)
 create mode 100644 bt5/erp5_authentication_policy/PathTemplateItem/portal_alarms/expire_authentication_events.xml
 create mode 100644 bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Person_getListboxUrl.xml
 create mode 100644 bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/SystemEventModule_expireAuthenticationEventList.xml
 create mode 100644 bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/SystemEventModule_getBlockedUserLoginList.xml
 create mode 100644 bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/SystemEventModule_viewBlockUseLoginList.xml
 create mode 100644 bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/SystemEventModule_viewBlockUseLoginList/listbox.xml
 create mode 100644 bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/SystemEventModule_viewBlockUseLoginList/listbox_unblockHTML.xml
 create mode 100644 bt5/erp5_authentication_policy/bt/template_path_list

diff --git a/bt5/erp5_authentication_policy/PathTemplateItem/portal_alarms/expire_authentication_events.xml b/bt5/erp5_authentication_policy/PathTemplateItem/portal_alarms/expire_authentication_events.xml
new file mode 100644
index 0000000000..7d4c84cbed
--- /dev/null
+++ b/bt5/erp5_authentication_policy/PathTemplateItem/portal_alarms/expire_authentication_events.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Alarm" module="erp5.portal_type"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>active_sense_method_id</string> </key>
+            <value> <string>SystemEventModule_expireAuthenticationEventList</string> </value>
+        </item>
+        <item>
+            <key> <string>description</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>enabled</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>expire_authentication_events</string> </value>
+        </item>
+        <item>
+            <key> <string>periodicity_hour</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>periodicity_minute</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>periodicity_minute_frequency</string> </key>
+            <value> <int>5</int> </value>
+        </item>
+        <item>
+            <key> <string>periodicity_month</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>periodicity_month_day</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>periodicity_start_date</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="DateTime" module="DateTime.DateTime"/>
+                </klass>
+                <tuple>
+                  <none/>
+                </tuple>
+                <state>
+                  <tuple>
+                    <float>1309996800.0</float>
+                    <string>GMT</string>
+                  </tuple>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>periodicity_week</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>portal_type</string> </key>
+            <value> <string>Alarm</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string>Expire old Authentication Events</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Person_getListboxUrl.xml b/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Person_getListboxUrl.xml
new file mode 100644
index 0000000000..2a7afd0149
--- /dev/null
+++ b/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Person_getListboxUrl.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>Script_magic</string> </key>
+            <value> <int>3</int> </value>
+        </item>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>name_container</string> </key>
+                                <value> <string>container</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_context</string> </key>
+                                <value> <string>context</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_m_self</string> </key>
+                                <value> <string>script</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_subpath</string> </key>
+                                <value> <string>traverse_subpath</string> </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_body</string> </key>
+            <value> <string>"""\n
+  Used to generate an URL to person object in a listbox.\n
+"""\n
+return brain.url\n
+</string> </value>
+        </item>
+        <item>
+            <key> <string>_params</string> </key>
+            <value> <string>brain, **kw</string> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>Person_getListboxUrl</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Person_isLoginBlocked.xml b/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Person_isLoginBlocked.xml
index e04aa6a9f9..9eecb65f7c 100644
--- a/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Person_isLoginBlocked.xml
+++ b/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Person_isLoginBlocked.xml
@@ -94,11 +94,12 @@ kw = {\'portal_type\': \'Authentication Event\',\n
 indexed_failure_list = portal.portal_catalog(**kw)\n
 indexed_failures = len(indexed_failure_list)\n
 \n
+#context.log(\'== %s %s %s\' %(unindexed_failures, indexed_failures, max_authentication_failures))\n
 if (indexed_failures + unindexed_failures) >= max_authentication_failures:\n
   last_authentication_failure = indexed_failure_list[-1].getObject()\n
   block_timeout = last_authentication_failure.getCreationDate() + block_duration*one_second\n
   if block_timeout >= now:\n
-    context.log(\'block %s\' %context.getReference())\n
+    #context.log(\'block %s\' %context.getReference())\n
     request.set(\'is_user_account_blocked\', True)\n
     return 1\n
 \n
diff --git a/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Person_unblockLogin.xml b/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Person_unblockLogin.xml
index c40fed5e00..bab6153538 100644
--- a/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Person_unblockLogin.xml
+++ b/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/Person_unblockLogin.xml
@@ -82,14 +82,17 @@ for authentication_event in authentication_event_list:\n
 \n
 if not batch_mode:\n
   message = context.Base_translateString(\'User Login unblocked.\')\n
-  context.Base_redirect(form_id=form_id, keep_items={\'portal_status_message\': message})\n
+  if cancel_url is None:\n
+    context.Base_redirect(form_id=form_id, keep_items={\'portal_status_message\': message})\n
+  else:\n
+    context.REQUEST.RESPONSE.redirect(\'%s?portal_status_message=%s\' %(cancel_url, message))\n
 \n
 return\n
 </string> </value>
         </item>
         <item>
             <key> <string>_params</string> </key>
-            <value> <string>form_id="view", batch_mode=False</string> </value>
+            <value> <string>form_id="view", cancel_url=None, batch_mode=False</string> </value>
         </item>
         <item>
             <key> <string>id</string> </key>
diff --git a/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/SystemEventModule_expireAuthenticationEventList.xml b/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/SystemEventModule_expireAuthenticationEventList.xml
new file mode 100644
index 0000000000..7d5ec0dea8
--- /dev/null
+++ b/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/SystemEventModule_expireAuthenticationEventList.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>Script_magic</string> </key>
+            <value> <int>3</int> </value>
+        </item>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>name_container</string> </key>
+                                <value> <string>container</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_context</string> </key>
+                                <value> <string>context</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_m_self</string> </key>
+                                <value> <string>script</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_subpath</string> </key>
+                                <value> <string>traverse_subpath</string> </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_body</string> </key>
+            <value> <string>"""\n
+  Expire old Authentication Events.\n
+"""\n
+from DateTime import DateTime\n
+from Products.ZSQLCatalog.SQLCatalog import Query\n
+from Products.ERP5Type.Document import newTempBase\n
+\n
+portal = context.getPortalObject()\n
+portal_preferences = portal.portal_preferences\n
+\n
+now = DateTime()\n
+one_second = 1/24.0/60.0/60.0\n
+check_duration = portal_preferences.getPreferredAuthenticationFailureCheckDuration()\n
+check_time = now - check_duration*one_second\n
+\n
+kw = {\'portal_type\': \'Authentication Event\',\n
+      \'creation_date\': Query(creation_date = check_time,\n
+                             range=\'max\'),\n
+      \'validation_state\' : \'confirmed\'}\n
+failure_list = portal.portal_catalog(**kw)\n
+\n
+for failure in failure_list:\n
+  failure.activate().expire(comment=\'System expire.\')\n
+</string> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>SystemEventModule_expireAuthenticationEventList</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/SystemEventModule_getBlockedUserLoginList.xml b/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/SystemEventModule_getBlockedUserLoginList.xml
new file mode 100644
index 0000000000..b1e344c54e
--- /dev/null
+++ b/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/SystemEventModule_getBlockedUserLoginList.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>Script_magic</string> </key>
+            <value> <int>3</int> </value>
+        </item>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>name_container</string> </key>
+                                <value> <string>container</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_context</string> </key>
+                                <value> <string>context</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_m_self</string> </key>
+                                <value> <string>script</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_subpath</string> </key>
+                                <value> <string>traverse_subpath</string> </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_body</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+"""\n
+  Return list of blocked user logins in a \'listbox\' format\n
+"""\n
+from DateTime import DateTime\n
+from Products.ZSQLCatalog.SQLCatalog import Query\n
+from Products.ERP5Type.Document import newTempBase\n
+\n
+portal = context.getPortalObject()\n
+portal_preferences = portal.portal_preferences\n
+\n
+blocked_user_login_list = []\n
+all_blocked_user_login_dict = {}\n
+\n
+now = DateTime()\n
+one_second = 1/24.0/60.0/60.0\n
+check_duration = portal_preferences.getPreferredAuthenticationFailureCheckDuration()\n
+max_authentication_failures = portal_preferences.getPreferredMaxAuthenticationFailure()\n
+check_time = now - check_duration*one_second\n
+\n
+kw = {\'portal_type\': \'Authentication Event\',\n
+      \'creation_date\': Query(creation_date = check_time,\n
+                             range=\'min\'),\n
+      \'validation_state\' : \'confirmed\'}\n
+failure_list = portal.portal_catalog(**kw)\n
+for failure in failure_list:\n
+  person = failure.getDestinationValue()\n
+  if person not in all_blocked_user_login_dict.keys():\n
+    all_blocked_user_login_dict[person] = []\n
+  all_blocked_user_login_dict[person].append(failure)\n
+\n
+# leave only ones that are blocked:\n
+for person, failure_list in all_blocked_user_login_dict.items():\n
+  if len(failure_list) >= max_authentication_failures:\n
+    blocked_user_login_list.append(newTempBase(portal, \n
+                                               person.getTitle(), \n
+                                               **{\'title\': person.getTitle(),\n
+                                                  \'count\':len(failure_list),\n
+                                                  \'reference\': person.getReference(),\n
+                                                  \'url\': person.absolute_url()}))\n
+return blocked_user_login_list\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>_params</string> </key>
+            <value> <string>**kw</string> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>SystemEventModule_getBlockedUserLoginList</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/SystemEventModule_viewBlockUseLoginList.xml b/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/SystemEventModule_viewBlockUseLoginList.xml
new file mode 100644
index 0000000000..273d2d307b
--- /dev/null
+++ b/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/SystemEventModule_viewBlockUseLoginList.xml
@@ -0,0 +1,154 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ERP5Form" module="Products.ERP5Form.Form"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary/>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>action</string> </key>
+            <value> <string>Base_doSelect</string> </value>
+        </item>
+        <item>
+            <key> <string>description</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>edit_order</string> </key>
+            <value>
+              <list/>
+            </value>
+        </item>
+        <item>
+            <key> <string>encoding</string> </key>
+            <value> <string>UTF-8</string> </value>
+        </item>
+        <item>
+            <key> <string>enctype</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>group_list</string> </key>
+            <value>
+              <list>
+                <string>left</string>
+                <string>right</string>
+                <string>center</string>
+                <string>bottom</string>
+                <string>hidden</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>groups</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>bottom</string> </key>
+                    <value>
+                      <list>
+                        <string>listbox</string>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>center</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>hidden</string> </key>
+                    <value>
+                      <list>
+                        <string>listbox_unblockHTML</string>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>left</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>right</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>SystemEventModule_viewBlockUseLoginList</string> </value>
+        </item>
+        <item>
+            <key> <string>method</string> </key>
+            <value> <string>POST</string> </value>
+        </item>
+        <item>
+            <key> <string>name</string> </key>
+            <value> <string>SystemEventModule_viewAuthenticationEventList</string> </value>
+        </item>
+        <item>
+            <key> <string>pt</string> </key>
+            <value> <string>form_list</string> </value>
+        </item>
+        <item>
+            <key> <string>row_length</string> </key>
+            <value> <int>4</int> </value>
+        </item>
+        <item>
+            <key> <string>stored_encoding</string> </key>
+            <value> <string>UTF-8</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string>Blocked User Login</string> </value>
+        </item>
+        <item>
+            <key> <string>unicode_mode</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>update_action</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>update_action_title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/SystemEventModule_viewBlockUseLoginList/listbox.xml b/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/SystemEventModule_viewBlockUseLoginList/listbox.xml
new file mode 100644
index 0000000000..fb9c7e6515
--- /dev/null
+++ b/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/SystemEventModule_viewBlockUseLoginList/listbox.xml
@@ -0,0 +1,209 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list>
+                <string>all_columns</string>
+                <string>columns</string>
+                <string>hide_rows_on_no_search_criterion</string>
+                <string>list_method</string>
+                <string>search_columns</string>
+                <string>selection_name</string>
+                <string>sort_columns</string>
+                <string>style_columns</string>
+                <string>title</string>
+                <string>url_columns</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>listbox</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>all_columns</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>columns</string> </key>
+                    <value>
+                      <list>
+                        <tuple>
+                          <string>title</string>
+                          <string>Title</string>
+                        </tuple>
+                        <tuple>
+                          <string>reference</string>
+                          <string>Login</string>
+                        </tuple>
+                        <tuple>
+                          <string>count</string>
+                          <string>Number of Failures</string>
+                        </tuple>
+                        <tuple>
+                          <string>unblockHTML</string>
+                          <string>Unblock</string>
+                        </tuple>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_list_mode_listbox</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>hide_rows_on_no_search_criterion</string> </key>
+                    <value> <int>0</int> </value>
+                </item>
+                <item>
+                    <key> <string>list_method</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>portal_type</string> </key>
+                    <value>
+                      <list>
+                        <tuple>
+                          <string>Authentication Event</string>
+                          <string>Authentication Event</string>
+                        </tuple>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>search_columns</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>selection_name</string> </key>
+                    <value> <string>unblock_user_login_search_selection</string> </value>
+                </item>
+                <item>
+                    <key> <string>sort_columns</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>style_columns</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string>Blocked User Login List</string> </value>
+                </item>
+                <item>
+                    <key> <string>url_columns</string> </key>
+                    <value>
+                      <list>
+                        <tuple>
+                          <string>title</string>
+                          <string>Person_getListboxUrl</string>
+                        </tuple>
+                        <tuple>
+                          <string>reference</string>
+                          <string>Person_getListboxUrl</string>
+                        </tuple>
+                        <tuple>
+                          <string>count</string>
+                          <string>Person_getListboxUrl</string>
+                        </tuple>
+                      </list>
+                    </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="Method" module="Products.Formulator.MethodField"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>method_name</string> </key>
+            <value> <string>SystemEventModule_getBlockedUserLoginList</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/SystemEventModule_viewBlockUseLoginList/listbox_unblockHTML.xml b/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/SystemEventModule_viewBlockUseLoginList/listbox_unblockHTML.xml
new file mode 100644
index 0000000000..aa03194fa3
--- /dev/null
+++ b/bt5/erp5_authentication_policy/SkinTemplateItem/portal_skins/erp5_authentication_policy/SystemEventModule_viewBlockUseLoginList/listbox_unblockHTML.xml
@@ -0,0 +1,137 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list>
+                <string>default</string>
+                <string>editable</string>
+                <string>title</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>listbox_unblockHTML</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>default</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>editable</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>default</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>editable</string> </key>
+                    <value> <int>0</int> </value>
+                </item>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_editor_field</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string>Unblock</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="TALESMethod" module="Products.Formulator.TALESField"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+python: \'<a title="Click to unblock login" href="%s/Person_unblockLogin?cancel_url=%s"> Unblock </a>\' %(cell.url, here.absolute_url())
+
+]]></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_authentication_policy/bt/revision b/bt5/erp5_authentication_policy/bt/revision
index 25bf17fc5a..dec2bf5d61 100644
--- a/bt5/erp5_authentication_policy/bt/revision
+++ b/bt5/erp5_authentication_policy/bt/revision
@@ -1 +1 @@
-18
\ No newline at end of file
+19
\ No newline at end of file
diff --git a/bt5/erp5_authentication_policy/bt/template_path_list b/bt5/erp5_authentication_policy/bt/template_path_list
new file mode 100644
index 0000000000..55ec26adac
--- /dev/null
+++ b/bt5/erp5_authentication_policy/bt/template_path_list
@@ -0,0 +1 @@
+portal_alarms/expire_authentication_events
\ No newline at end of file
-- 
2.30.9