From 67537341bc6745a887d7b679c33db49b5eb4adaf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Tue, 3 Sep 2019 10:55:53 +0200
Subject: [PATCH 1/2] misc: add get_roles() accessor to user class (#7865)

---
 wcs/api.py                        |  8 ++++----
 wcs/backoffice/data_management.py |  4 ++--
 wcs/backoffice/management.py      | 14 +++++++-------
 wcs/backoffice/root.py            |  4 ++--
 wcs/backoffice/submission.py      |  4 ++--
 wcs/formdef.py                    | 15 ++++++---------
 wcs/forms/backoffice.py           |  4 ++--
 wcs/forms/root.py                 |  6 +++---
 wcs/forms/workflows.py            |  2 +-
 wcs/users.py                      |  3 +++
 wcs/workflows.py                  | 10 +++++-----
 11 files changed, 37 insertions(+), 37 deletions(-)

diff --git a/wcs/api.py b/wcs/api.py
index fb2487618..20869f18e 100644
--- a/wcs/api.py
+++ b/wcs/api.py
@@ -360,7 +360,7 @@ class ApiFormdefDirectory(Directory):
                 raise AccessForbiddenError('no user set for backoffice submission')
             if not self.formdef.backoffice_submission_roles:
                 raise AccessForbiddenError('no backoffice submission roles')
-            if not set(user.roles or []).intersection(self.formdef.backoffice_submission_roles):
+            if not set(user.get_roles()).intersection(self.formdef.backoffice_submission_roles):
                 raise AccessForbiddenError('not cleared for backoffice submit')
             formdata.backoffice_submission = True
         elif 'user' in json_input:
@@ -454,7 +454,7 @@ class ApiFormdefsDirectory(Directory):
                         continue
                     authentication_required = True
                 elif logged_users_role().id not in formdef.roles:
-                    for q in user.roles or []:
+                    for q in user.get_roles():
                         if q in formdef.roles:
                             break
                     else:
@@ -465,7 +465,7 @@ class ApiFormdefsDirectory(Directory):
                 if not formdef.backoffice_submission_roles:
                     continue
                 if not list_all_forms:
-                    for role in user.roles or []:
+                    for role in user.get_roles():
                         if role in formdef.backoffice_submission_roles:
                             break
                     else:
@@ -675,7 +675,7 @@ class ApiUserDirectory(Directory):
                 if not query_user.can_go_in_backoffice():
                     raise AccessForbiddenError('user not allowed to query data from others')
                 # mark forms that are readable by querying user
-                user_roles = set(query_user.roles or [])
+                user_roles = set(query_user.get_roles())
                 if get_publisher().is_using_postgresql():
                     # use concerned_roles_array attribute that was saved in the
                     # table.
diff --git a/wcs/backoffice/data_management.py b/wcs/backoffice/data_management.py
index 476a3573c..17ebbb548 100644
--- a/wcs/backoffice/data_management.py
+++ b/wcs/backoffice/data_management.py
@@ -37,7 +37,7 @@ class DataManagementDirectory(ManagementDirectory):
             return False
         # only include data management if there are accessible cards
         for carddef in CardDef.select(ignore_errors=True, lightweight=True, iterator=True):
-            for role_id in (user.roles or []):
+            for role_id in user.get_roles():
                 if role_id in (carddef.backoffice_submission_roles or []):
                     return True
                 if role_id in (carddef.workflow_roles or {}).values():
@@ -86,7 +86,7 @@ class CardPage(FormPage):
     def listing_top_actions(self):
         if not self.formdef.backoffice_submission_roles:
             return ''
-        for role in get_request().user.roles or []:
+        for role in get_request().user.get_roles():
             if role in self.formdef.backoffice_submission_roles:
                 break
         else:
diff --git a/wcs/backoffice/management.py b/wcs/backoffice/management.py
index b47b02c36..8fe6a18a5 100644
--- a/wcs/backoffice/management.py
+++ b/wcs/backoffice/management.py
@@ -216,7 +216,7 @@ class UserViewDirectory(Directory):
         html_top('management', _('Management'))
         # display list of open formdata for the user
         formdefs = [x for x in FormDef.select(lightweight=True) if not x.skip_from_360_view]
-        user_roles = set([logged_users_role().id] + (get_request().user.roles or []))
+        user_roles = set([logged_users_role().id] + get_request().user.get_roles())
         criterias = [Equal('is_at_endpoint', False),
                      Equal('user_id', str(self.user.id)),
                      Contains('formdef_id', [x.id for x in formdefs]),
@@ -468,7 +468,7 @@ class ManagementDirectory(Directory):
         r += get_session().display_message()
 
         user = get_request().user
-        user_roles = [logged_users_role().id] + (user.roles or [])
+        user_roles = [logged_users_role().id] + user.get_roles()
 
         forms_without_pending_stuff = []
         forms_with_pending_stuff = []
@@ -771,8 +771,8 @@ class ManagementDirectory(Directory):
     def get_global_listing_criterias(self, ignore_user_roles=False):
         parsed_values = {}
         user_roles = [logged_users_role().id]
-        if get_request().user and get_request().user.roles:
-            user_roles.extend(get_request().user.roles)
+        if get_request().user:
+            user_roles.extend(get_request().user.get_roles())
         criterias = get_global_criteria(get_request(), parsed_values)
         query_parameters = (get_request().form or {}).copy()
         query_parameters.pop('callback', None) # when using jsonp
@@ -2020,7 +2020,7 @@ class FormBackOfficeStatusPage(FormStatusPage):
     def _q_index(self):
         if self.filled.status == 'draft':
             if self.filled.backoffice_submission:
-                for role in get_request().user.roles or []:
+                for role in get_request().user.get_roles():
                     if role in self.formdef.backoffice_submission_roles:
                         return redirect('../../../submission/%s/%s' % (
                             self.formdef.url_name, self.filled.id))
@@ -2061,7 +2061,7 @@ class FormBackOfficeStatusPage(FormStatusPage):
 
         if not visitors or me_in_visitors:
             related_user_forms = getattr(self.filled, 'related_user_forms', None) or []
-            user_roles = set(get_request().user.roles or [])
+            user_roles = set(get_request().user.get_roles())
             for user_formdata in related_user_forms:
                 if user_roles.intersection(user_formdata.actions_roles):
                     user_formdata.mark_as_being_visited()
@@ -2201,7 +2201,7 @@ class FormBackOfficeStatusPage(FormStatusPage):
         from wcs import sql
         formdata = self.filled
         r = TemplateIO(html=True)
-        user_roles = [logged_users_role().id] + (get_request().user.roles or [])
+        user_roles = [logged_users_role().id] + get_request().user.get_roles()
         criterias = [Equal('is_at_endpoint', False),
                      Equal('user_id', str(formdata.user_id)),
                      Intersects('concerned_roles_array', user_roles),
diff --git a/wcs/backoffice/root.py b/wcs/backoffice/root.py
index 0f730a371..d598c1264 100644
--- a/wcs/backoffice/root.py
+++ b/wcs/backoffice/root.py
@@ -105,7 +105,7 @@ class RootDirectory(BackofficeRootDirectory):
                 return subdirectory in ('settings', 'users')
             return False
 
-        user_roles = set(get_request().user.roles or [])
+        user_roles = set(get_request().user.get_roles())
         authorised_roles = set(get_cfg('admin-permissions', {}).get(subdirectory) or [])
         if authorised_roles:
             # access is governed by roles set in the settings panel
@@ -247,7 +247,7 @@ class RootDirectory(BackofficeRootDirectory):
             # user connecting.
             user_roles = set()
         else:
-            user_roles = set(get_request().user.roles or [])
+            user_roles = set(get_request().user.get_roles())
         menu_items = []
         backoffice_url = get_publisher().get_backoffice_url()
         if not backoffice_url.endswith('/'):
diff --git a/wcs/backoffice/submission.py b/wcs/backoffice/submission.py
index 187975f55..3ca6bc292 100644
--- a/wcs/backoffice/submission.py
+++ b/wcs/backoffice/submission.py
@@ -124,7 +124,7 @@ class FormFillPage(PublicFormFillPage):
             return True
         if not self.formdef.backoffice_submission_roles:
             raise errors.AccessUnauthorizedError()
-        for role in get_request().user.roles or []:
+        for role in get_request().user.get_roles():
             if role in self.formdef.backoffice_submission_roles:
                 break
         else:
@@ -276,7 +276,7 @@ class SubmissionDirectory(Directory):
                 continue
             if not formdef.backoffice_submission_roles:
                 continue
-            for role in user.roles or []:
+            for role in user.get_roles():
                 if role in formdef.backoffice_submission_roles:
                     break
             else:
diff --git a/wcs/formdef.py b/wcs/formdef.py
index 26f9aa485..014e62853 100644
--- a/wcs/formdef.py
+++ b/wcs/formdef.py
@@ -1292,21 +1292,21 @@ class FormDef(StorableObject):
         # if the formdef itself has some function attributed to the user, grant
         # access.
         for role_id in self.workflow_roles.values():
-            if role_id in (user.roles or []):
+            if role_id in user.get_roles():
                 return True
 
         # if there was some redispatching of function, values will be different
         # in formdata, check them.
         if formdata and formdata.workflow_roles:
             for role_id in formdata.workflow_roles.values():
-                if role_id in (user.roles or []):
+                if role_id in user.get_roles():
                     return True
 
         # if no formdata was given, lookup if there are some existing formdata
         # where the user has access.
         if not formdata:
             data_class = self.data_class()
-            for role_id in user.roles or []:
+            for role_id in user.get_roles():
                 if data_class.get_ids_with_indexed_value('workflow_roles', role_id):
                     return True
 
@@ -1321,10 +1321,7 @@ class FormDef(StorableObject):
         if user.is_admin:
             return True
 
-        if user.roles:  # set(None) raise an exception for python>2.6
-            user_roles = set(user.roles)
-        else:
-            user_roles = set([])
+        user_roles = set(user.get_roles())
         user_roles.add(logged_users_role().id)
 
         def ensure_role_are_strings(roles):
@@ -1354,8 +1351,8 @@ class FormDef(StorableObject):
         if user and user.is_admin:
             return True
 
-        if user and user.roles:
-            user_roles = set(user.roles)
+        if user:
+            user_roles = set(user.get_roles())
         else:
             user_roles = set([])
 
diff --git a/wcs/forms/backoffice.py b/wcs/forms/backoffice.py
index 317ddc42f..32922dcf6 100644
--- a/wcs/forms/backoffice.py
+++ b/wcs/forms/backoffice.py
@@ -124,7 +124,7 @@ class FormDefUI(object):
             drafts = {x: True for x in formdata_class.get_ids_with_indexed_value('status', 'draft')}
             item_ids = [x for x in item_ids if x not in drafts]
         elif selected_filter == 'waiting':
-            user_roles = [logged_users_role().id] + (user.roles or [])
+            user_roles = [logged_users_role().id] + user.get_roles()
             item_ids = formdata_class.get_actionable_ids(user_roles)
         else:
             applied_filters = []
@@ -154,7 +154,7 @@ class FormDefUI(object):
             # situation where the user is the submitter, and we limit ourselves
             # to consider treating roles.
             if not user.is_admin:
-                user_roles = set(user.roles or [])
+                user_roles = set(user.get_roles())
                 concerned_ids = set()
                 for role in user_roles:
                     concerned_ids |= set(formdata_class.get_ids_with_indexed_value(
diff --git a/wcs/forms/root.py b/wcs/forms/root.py
index 90319ecba..ed628cb32 100644
--- a/wcs/forms/root.py
+++ b/wcs/forms/root.py
@@ -233,8 +233,8 @@ class FormPage(Directory, FormTemplateMixin):
                 raise errors.AccessUnauthorizedError()
             if logged_users_role().id not in self.formdef.roles and not (
                     self.user and self.user.is_admin):
-                if self.user and self.user.roles:
-                    user_roles = set(self.user.roles)
+                if self.user:
+                    user_roles = set(self.user.get_roles())
                 else:
                     user_roles = set([])
                 other_roles = (self.formdef.roles or [])
@@ -1373,7 +1373,7 @@ class RootDirectory(AccessControlled, Directory):
                         advertised_forms.append(formdef)
                     continue
                 if logged_users_role().id not in formdef.roles:
-                    for q in user.roles or []:
+                    for q in user.get_roles():
                         if q in formdef.roles:
                             break
                     else:
diff --git a/wcs/forms/workflows.py b/wcs/forms/workflows.py
index 86029984d..342cc764f 100644
--- a/wcs/forms/workflows.py
+++ b/wcs/forms/workflows.py
@@ -52,7 +52,7 @@ class HookDirectory(Directory):
                     break
                 if not user:
                     continue
-                if get_role_translation(self.formdata, role) in (user.roles or []):
+                if get_role_translation(self.formdata, role) in user.get_roles():
                     break
             else:
                 raise errors.AccessForbiddenError('insufficient roles')
diff --git a/wcs/users.py b/wcs/users.py
index 320cc2512..0eb59822c 100644
--- a/wcs/users.py
+++ b/wcs/users.py
@@ -87,6 +87,9 @@ class User(StorableObject):
         return _('Unknown User')
     display_name = property(get_display_name)
 
+    def get_roles(self):
+        return (self.roles or [])
+
     def set_attributes_from_formdata(self, formdata):
         users_cfg = get_cfg('users', {})
 
diff --git a/wcs/workflows.py b/wcs/workflows.py
index 0c94748a5..dd9de272a 100644
--- a/wcs/workflows.py
+++ b/wcs/workflows.py
@@ -425,7 +425,7 @@ class Workflow(StorableObject):
                         break
                     roles = [get_role_translation(formdata, x)
                              for x in (trigger.roles or []) if x != '_submitter']
-                    if set(roles).intersection(user.roles or []):
+                    if set(roles).intersection(user.get_roles()):
                         actions.append(action)
                         break
         return actions
@@ -1439,7 +1439,7 @@ class WorkflowStatus(object):
                     if user is None:
                         continue
                     role = get_role_translation(filled, role)
-                    if role in (user.roles or []):
+                    if role in user.get_roles():
                         break
                 else:
                     continue
@@ -1514,7 +1514,7 @@ class WorkflowStatus(object):
             return True
 
         if user:
-            user_roles = set(user.roles or [])
+            user_roles = set(user.get_roles())
             user_roles.add(logged_users_role().id)
         else:
             user_roles = set([])
@@ -1699,7 +1699,7 @@ class WorkflowStatusItem(XmlSerialisable):
             if not user:
                 continue
             role = get_role_translation(formdata, role)
-            if role in (user.roles or []):
+            if role in user.get_roles():
                 return True
 
         return False
@@ -2696,7 +2696,7 @@ class DisplayMessageWorkflowStatusItem(WorkflowStatusItem):
                     return True
             elif user:
                 role = get_role_translation(filled, role)
-                if role in (user.roles or []):
+                if role in user.get_roles():
                     return True
         return False
 
-- 
2.23.0

