From c178b782028ec7a2c427bb963fc2c9c25967ff12 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9rome=20Perrin?= <jerome@nexedi.com>
Date: Fri, 12 May 2017 03:08:18 +0000
Subject: [PATCH] PreferenceTool: introduce a new getActiveUserPreference
 method

This method creates a user preference if no preference exists.
---
 product/ERP5/tests/testERP5Base.py            | 16 +++++++++---
 product/ERP5/tests/testPerson.py              | 13 ----------
 product/ERP5Form/PreferenceTool.py            | 21 ++++++++++++++++
 product/ERP5Form/tests/testPreferences.py     |  6 +++++
 .../ERP5Security/tests/testERP5Security.py    | 25 +++++++++++++++++++
 5 files changed, 64 insertions(+), 17 deletions(-)

diff --git a/product/ERP5/tests/testERP5Base.py b/product/ERP5/tests/testERP5Base.py
index ce5b57c9dd..8e6a6516f6 100644
--- a/product/ERP5/tests/testERP5Base.py
+++ b/product/ERP5/tests/testERP5Base.py
@@ -1157,7 +1157,7 @@ class TestERP5Base(ERP5TypeTestCase):
   def test_user_creation(self):
     person = self.portal.person_module.newContent(portal_type='Person')
     assignment = person.newContent(portal_type='Assignment',
-                                   group='nexedi')
+                                   group='nexedi/storever')
     self.assertNotEquals(None, assignment.getGroupValue())
     assignment.open()
     self.portal.portal_workflow.doActionFor(person, 'create_user_action',
@@ -1170,13 +1170,21 @@ class TestERP5Base(ERP5TypeTestCase):
     user = self.portal.acl_users.getUser('user_login')
     self.assertNotEquals(None, user)
 
-    # and this user has a preference created
+    # This user does not have a preference created automatically ...
     newSecurityManager(None, user.__of__(self.portal.acl_users))
+    self.assertEquals(None,
+        self.portal.portal_catalog.getResultValue(portal_type='Preference',
+                                                  owner=user.getId()))
+    # ... but only when `getActiveUserPreference`
+    preference = self.portal.portal_preferences.getActiveUserPreference()
+    self.assertNotEquals(None, preference)
+    self.tic()
     self.assertNotEquals(None,
         self.portal.portal_catalog.getResultValue(portal_type='Preference',
                                                   owner=user.getId()))
-    # for his assignent group
-    self.assertEqual('group/nexedi',
+
+    # for his assignment group
+    self.assertEqual('group/nexedi/storever',
         self.portal.portal_preferences.getPreferredSectionCategory())
 
   def test_default_address_acquisition(self):
diff --git a/product/ERP5/tests/testPerson.py b/product/ERP5/tests/testPerson.py
index e3b665edc1..576fb1f277 100644
--- a/product/ERP5/tests/testPerson.py
+++ b/product/ERP5/tests/testPerson.py
@@ -241,19 +241,6 @@ class TestPerson(ERP5TypeTestCase):
     self.assertEqual(None, p.getPassword())
     self.assertEqual('default', p.getPassword('default'))
 
-  def testPreferenceInteractionWorkflow(self):
-    """ when setting reference, a script create preference is
-        called by activities, check this behavior. """
-    person_module = self.getPersonModule()
-    title = "Séb"
-    person = person_module.newContent(portal_type='Person', title=title)
-    person.setReference('test_seb')
-    self.tic()
-    portal = self.getPortal()
-    last_id = portal.portal_preferences.getLastId()
-    last_preference = portal.portal_preferences[last_id]
-    self.assertTrue("Séb" in last_preference.getTitle())
-
 
 def test_suite():
   suite = unittest.TestSuite()
diff --git a/product/ERP5Form/PreferenceTool.py b/product/ERP5Form/PreferenceTool.py
index c6db69a197..b2ae035fa5 100644
--- a/product/ERP5Form/PreferenceTool.py
+++ b/product/ERP5Form/PreferenceTool.py
@@ -197,6 +197,27 @@ class PreferenceTool(BaseTool):
        Note that this preference may be read only. """
     return self._getActivePreferenceByPortalType('Preference')
 
+  security.declareProtected(Permissions.View, 'getActiveUserPreference')
+  def getActiveUserPreference(self) :
+    """ returns the current user preference for the user.
+    If no preference exists, then try to create one with `createUserPreference`
+    type based method.
+
+    This method returns a preference that the user will be able to edit or
+    None, if `createUserPreference` refused to create a preference.
+
+    It is intendended for "click here to edit your preferences" actions.
+    """
+    active_preference = self.getActivePreference()
+    if active_preference is None or active_preference.getPriority() != Priority.USER:
+      # If user does not have a preference, let's try to create one
+      user = self.getPortalObject().portal_membership.getAuthenticatedMember().getUserValue()
+      if user is not None:
+        createUserPreference = user.getTypeBasedMethod('createUserPreference')
+        if createUserPreference is not None:
+          active_preference = createUserPreference()
+    return active_preference
+
   security.declareProtected(Permissions.View, 'getActiveSystemPreference')
   def getActiveSystemPreference(self) :
     """ returns the current system preference for the user.
diff --git a/product/ERP5Form/tests/testPreferences.py b/product/ERP5Form/tests/testPreferences.py
index 26f6260017..901549a8dd 100644
--- a/product/ERP5Form/tests/testPreferences.py
+++ b/product/ERP5Form/tests/testPreferences.py
@@ -115,6 +115,7 @@ class TestPreferences(PropertySheetTestCase):
     site = self.getPreferenceTool()['site']
 
     self.assertEqual(None, self.getPreferenceTool().getActivePreference())
+    self.assertEqual(None, self.getPreferenceTool().getActiveUserPreference())
     self.assertEqual(None,
         self.getPreferenceTool().getActiveSystemPreference())
 
@@ -124,6 +125,7 @@ class TestPreferences(PropertySheetTestCase):
     self.assertEqual(person1.getPreferenceState(), 'enabled')
 
     self.assertEqual( person1, self.getPreferenceTool().getActivePreference())
+    self.assertEqual( person1, self.getPreferenceTool().getActiveUserPreference())
     self.assertEqual(None,
         self.getPreferenceTool().getActiveSystemPreference())
 
@@ -133,6 +135,7 @@ class TestPreferences(PropertySheetTestCase):
     self.assertEqual(site.getPreferenceState(),    'global')
 
     self.assertEqual(person1, self.getPreferenceTool().getActivePreference())
+    self.assertEqual(person1, self.getPreferenceTool().getActiveUserPreference())
     self.assertEqual(None,
         self.getPreferenceTool().getActiveSystemPreference())
 
@@ -143,6 +146,7 @@ class TestPreferences(PropertySheetTestCase):
     self.assertEqual(site.getPreferenceState(),    'global')
 
     self.assertEqual(person1, self.getPreferenceTool().getActivePreference())
+    self.assertEqual(person1, self.getPreferenceTool().getActiveUserPreference())
     self.assertEqual(None,
         self.getPreferenceTool().getActiveSystemPreference())
 
@@ -150,6 +154,7 @@ class TestPreferences(PropertySheetTestCase):
        person2, 'enable_action', wf_id='preference_workflow')
     self.commit()
     self.assertEqual(person2, self.getPreferenceTool().getActivePreference())
+    self.assertEqual(person2, self.getPreferenceTool().getActiveUserPreference())
     self.assertEqual(None,
         self.getPreferenceTool().getActiveSystemPreference())
     self.assertEqual(person2.getPreferenceState(), 'enabled')
@@ -553,6 +558,7 @@ class TestPreferences(PropertySheetTestCase):
     # even if there is System Preference enabled getActivePreference shall return
     # user preference
     self.assertEqual(user_pref, preference_tool.getActivePreference())
+    self.assertEqual(user_pref, preference_tool.getActiveUserPreference())
     self.assertEqual(system_pref, preference_tool.getActiveSystemPreference())
 
   def test_boolean_accessor(self):
diff --git a/product/ERP5Security/tests/testERP5Security.py b/product/ERP5Security/tests/testERP5Security.py
index 7cfc0ba003..f008013002 100644
--- a/product/ERP5Security/tests/testERP5Security.py
+++ b/product/ERP5Security/tests/testERP5Security.py
@@ -379,6 +379,31 @@ class TestUserManagement(ERP5TypeTestCase):
       user_id,
     )
 
+  def test_Preference_created_for_new_user_on_getActiveUserPreference(self):
+    # Creating a user will create a preference on the first time `getActiveUserPreference`
+    # is called
+    preference_tool = self.portal.portal_preferences
+    preference_count = len(preference_tool.contentValues())
+
+    user_id, login, password = self._makePerson()
+    # creating a person does not create a preference
+    self.assertEqual(preference_count, len(preference_tool.contentValues()))
+
+    self.loginAsUser(user_id)
+
+    # getActiveUserPreference will create a user preference
+    new_preference = preference_tool.getActiveUserPreference()
+    self.assertNotEqual(None, new_preference)
+    self.assertEqual(preference_count+1, len(preference_tool.contentValues()))
+    self.assertEqual('enabled', new_preference.getPreferenceState())
+
+    self.tic()
+
+    # subsequent calls to getActiveUserPreference returns the same preference
+    active_preference = preference_tool.getActiveUserPreference()
+    self.assertEqual(active_preference, new_preference)
+    self.assertEqual(preference_count+1, len(preference_tool.contentValues()))
+
   def test_PreferenceTool_setNewPassword(self):
     # Preference Tool has an action to change password
     user_id, login, password = self._makePerson()
-- 
2.30.9