From 9140e33af968574042f2b7e4fa93c47d6850dbe8 Mon Sep 17 00:00:00 2001 From: Espurna Date: Tue, 12 Dec 2017 17:52:50 +0100 Subject: [PATCH 01/11] registry --- bika/lims/profiles/default/registry.xml | 20 ++++++++++++++++++++ bika/lims/upgrade/v01_01_008.py | 2 ++ 2 files changed, 22 insertions(+) diff --git a/bika/lims/profiles/default/registry.xml b/bika/lims/profiles/default/registry.xml index 4d6aa12c14..c4acc6ae3b 100644 --- a/bika/lims/profiles/default/registry.xml +++ b/bika/lims/profiles/default/registry.xml @@ -26,6 +26,26 @@ + + + + Dashboard panels visibility + + It is a dictionary with dashboard panel names as keys and + strings as values. Values are strings containing the role and + view permission for each role following this format: + "role1,yes,role2,no,rol3,no" + + + + + + null + null + null + + + diff --git a/bika/lims/upgrade/v01_01_008.py b/bika/lims/upgrade/v01_01_008.py index 6c92c2bbbe..1c7f162fc3 100644 --- a/bika/lims/upgrade/v01_01_008.py +++ b/bika/lims/upgrade/v01_01_008.py @@ -30,6 +30,8 @@ def upgrade(tool): logger.info("Upgrading {0}: {1} -> {2}".format(product, ver_from, version)) # -------- ADD YOUR STUFF HERE -------- + setup = portal.portal_setup + setup.runImportStepFromProfile('profile-bika.lims:default', 'plone.app.registry') upgrade_indexes() logger.info("{0} upgraded to version {1}".format(product, version)) From 89120ce17d737a4cb423600bb71df5bfae9d91a4 Mon Sep 17 00:00:00 2001 From: Espurna Date: Wed, 13 Dec 2017 18:08:04 +0100 Subject: [PATCH 02/11] python logic for new registry element --- bika/lims/browser/dashboard/dashboard.py | 79 +++++++++++++++++++ .../browser/dashboard/templates/dashboard.pt | 23 +++++- bika/lims/profiles/default/registry.xml | 2 +- bika/lims/utils/__init__.py | 24 ++++++ 4 files changed, 124 insertions(+), 4 deletions(-) diff --git a/bika/lims/browser/dashboard/dashboard.py b/bika/lims/browser/dashboard/dashboard.py index 7f24baeb93..c2780c2156 100644 --- a/bika/lims/browser/dashboard/dashboard.py +++ b/bika/lims/browser/dashboard/dashboard.py @@ -11,6 +11,7 @@ from Products.Archetypes.public import DisplayList from Products.CMFCore.utils import getToolByName from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile +from plone import api from bika.lims import bikaMessageFactory as _ from bika.lims import logger @@ -19,6 +20,7 @@ from bika.lims.catalog import CATALOG_ANALYSIS_REQUEST_LISTING from bika.lims.catalog import CATALOG_WORKSHEET_LISTING from bika.lims.utils import get_strings +from bika.lims.utils import get_unicode DASHBOARD_FILTER_COOKIE = 'dashboard_filter_cookie' @@ -93,6 +95,15 @@ def is_filter_selected(self, selection_id, value): selected = self.dashboard_cookie.get(selection_id) return selected == value + def is_admin_user(self): + """ + Checks if the user is the admin user. + :return: Boolean + """ + user = api.user.get_current() + username = user and user.getUserName() or None + return username == 'admin' + def _create_raw_data(self): """ Gathers the different sections ids and creates a string as first @@ -636,3 +647,71 @@ def _update_criteria_with_filters(self, query, section_name): query['Creator'] = self.member.getId() return query return query + + def get_dashboard_panels_visibility(self, section_name): + """ + Return a list of pairs as values that represents the role-permission + view relation for the panel section. + :param section_name: the panels section id. + :return: a list of tuples. + """ + result = [] + registry_info = self._get_dashboard_registry_record() + if registry_info is None: + return result + pairs = registry_info.get(section_name) + pairs = get_strings(pairs) + if pairs is None: + return result + if pairs == 'null': + # Registry hasn't been set yet + self._setup_dashboard_panels_visibility_registry( + section_name) + return self.get_dashboard_panels_visibility(section_name) + pairs = pairs.split(',') + result = [ + (pairs[i], pairs[i+1]) for i in range(len(pairs)) if i % 2 == 0] + return result + + def _setup_dashboard_panels_visibility_registry(self, section_name): + """ + It gives 'yes' values to all roles inside 'section_name' key values in + 'bika.lims.dashboard_panels_visibility' registry. + :param section_name: + :return: An string like: "role1,yes,role2,no,rol3,no" + """ + registry_info = self._get_dashboard_registry_record() + if registry_info is None: + return None + role_permissions_list = [] + # Getting roles defined in the system + roles = [] + roles_tree = self.portal.acl_users.portal_role_manager.listRoleIds() + for role in roles_tree: + roles.append(role) + # Set view permissions to each role as 'yes': + # "role1,yes,role2,no,rol3,no" + for role in roles: + role_permissions_list.append(role) + role_permissions_list.append('yes') + role_permissions = ','.join(role_permissions_list) + + # Set permissions string into dict + registry_info[section_name] = get_unicode(role_permissions) + # Set new values to registry record + api.portal.set_registry_record( + 'bika.lims.dashboard_panels_visibility', registry_info) + return registry_info + + def _get_dashboard_registry_record(self): + """ + Return the 'bika.lims.dashboard_panels_visibility' values. + :return: A dictionary or None + """ + registry = api.portal.get_registry_record( + 'bika.lims.dashboard_panels_visibility') + if registry is None: + logger.warn('Registry bika.lims.dashboard_panels_visibility not ' + 'found.') + return None + return registry diff --git a/bika/lims/browser/dashboard/templates/dashboard.pt b/bika/lims/browser/dashboard/templates/dashboard.pt index 6351a6a993..470f12338b 100644 --- a/bika/lims/browser/dashboard/templates/dashboard.pt +++ b/bika/lims/browser/dashboard/templates/dashboard.pt @@ -431,13 +431,12 @@ -
+

+
+ +
diff --git a/bika/lims/profiles/default/registry.xml b/bika/lims/profiles/default/registry.xml index c4acc6ae3b..5e018d749a 100644 --- a/bika/lims/profiles/default/registry.xml +++ b/bika/lims/profiles/default/registry.xml @@ -41,7 +41,7 @@
null - null + null null
diff --git a/bika/lims/utils/__init__.py b/bika/lims/utils/__init__.py index fd4c1a6f1c..73823ffea8 100644 --- a/bika/lims/utils/__init__.py +++ b/bika/lims/utils/__init__.py @@ -800,6 +800,30 @@ def get_strings(data): return data +def get_unicode(data): + """ + Convert string values to unicode even if they belong to lists or dicts. + :param data: an object. + :return: The object with all string values converted to unicode. + """ + # if this is a common string, return its unicode representation + if isinstance(data, str): + return safe_unicode(data) + + # if this is a list of values, return list of unicode values + if isinstance(data, list): + return [get_unicode(item) for item in data] + + # if this is a dictionary, return dictionary of unicode keys and values + if isinstance(data, dict): + return { + get_unicode(key): get_unicode(value) + for key, value in data.iteritems() + } + # if it's anything else, return it in its original form + return data + + def is_bika_installed(): """Check if Bika LIMS is installed in the Portal """ From 353e25407a390c54a084487194f628ebea992bfb Mon Sep 17 00:00:00 2001 From: Espurna Date: Thu, 14 Dec 2017 11:27:10 +0100 Subject: [PATCH 03/11] ajax post to modify registry --- bika/lims/browser/dashboard/configure.zcml | 8 + bika/lims/browser/dashboard/dashboard.py | 139 ++++++++++++------ .../browser/dashboard/templates/dashboard.pt | 32 +++- 3 files changed, 137 insertions(+), 42 deletions(-) diff --git a/bika/lims/browser/dashboard/configure.zcml b/bika/lims/browser/dashboard/configure.zcml index a22add64b1..f979c67c3f 100644 --- a/bika/lims/browser/dashboard/configure.zcml +++ b/bika/lims/browser/dashboard/configure.zcml @@ -11,4 +11,12 @@ layer="bika.lims.interfaces.IBikaLIMS" /> + + diff --git a/bika/lims/browser/dashboard/dashboard.py b/bika/lims/browser/dashboard/dashboard.py index c2780c2156..7ddb406c3d 100644 --- a/bika/lims/browser/dashboard/dashboard.py +++ b/bika/lims/browser/dashboard/dashboard.py @@ -12,6 +12,7 @@ from Products.CMFCore.utils import getToolByName from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile from plone import api +from plone import protect from bika.lims import bikaMessageFactory as _ from bika.lims import logger @@ -25,6 +26,63 @@ DASHBOARD_FILTER_COOKIE = 'dashboard_filter_cookie' +def get_dashboard_registry_record(): + """ + Return the 'bika.lims.dashboard_panels_visibility' values. + :return: A dictionary or None + """ + registry = api.portal.get_registry_record( + 'bika.lims.dashboard_panels_visibility') + if registry is None: + logger.warn('Registry bika.lims.dashboard_panels_visibility not ' + 'found.') + return None + return registry + + +def set_dashboard_registry_record(registry_info): + """ + Sets the 'bika.lims.dashboard_panels_visibility' values. + + :param registry_info: A dictionary type object with all its values as + *unicode* objects. + :return: A dictionary or None + """ + api.portal.set_registry_record( + 'bika.lims.dashboard_panels_visibility', registry_info) + + +def setup_dashboard_panels_visibility_registry(section_name): + """ + It gives 'yes' values to all roles inside 'section_name' key values in + 'bika.lims.dashboard_panels_visibility' registry. + :param section_name: + :return: An string like: "role1,yes,role2,no,rol3,no" + """ + registry_info = get_dashboard_registry_record() + if registry_info is None: + return None + role_permissions_list = [] + # Getting roles defined in the system + roles = [] + acl_users = api.get_tool("acl_users") + roles_tree = acl_users.portal_role_manager.listRoleIds() + for role in roles_tree: + roles.append(role) + # Set view permissions to each role as 'yes': + # "role1,yes,role2,no,rol3,no" + for role in roles: + role_permissions_list.append(role) + role_permissions_list.append('yes') + role_permissions = ','.join(role_permissions_list) + + # Set permissions string into dict + registry_info[section_name] = get_unicode(role_permissions) + # Set new values to registry record + set_dashboard_registry_record(registry_info) + return registry_info + + class DashboardView(BrowserView): template = ViewPageTemplateFile("templates/dashboard.pt") @@ -656,7 +714,7 @@ def get_dashboard_panels_visibility(self, section_name): :return: a list of tuples. """ result = [] - registry_info = self._get_dashboard_registry_record() + registry_info = get_dashboard_registry_record() if registry_info is None: return result pairs = registry_info.get(section_name) @@ -665,53 +723,52 @@ def get_dashboard_panels_visibility(self, section_name): return result if pairs == 'null': # Registry hasn't been set yet - self._setup_dashboard_panels_visibility_registry( - section_name) + setup_dashboard_panels_visibility_registry(section_name) return self.get_dashboard_panels_visibility(section_name) pairs = pairs.split(',') result = [ (pairs[i], pairs[i+1]) for i in range(len(pairs)) if i % 2 == 0] return result - def _setup_dashboard_panels_visibility_registry(self, section_name): - """ - It gives 'yes' values to all roles inside 'section_name' key values in - 'bika.lims.dashboard_panels_visibility' registry. - :param section_name: - :return: An string like: "role1,yes,role2,no,rol3,no" - """ - registry_info = self._get_dashboard_registry_record() - if registry_info is None: + +class DashboardViewPermissionUpdate(BrowserView): + """ + Updates the values in 'bika.lims.dashboard_panels_visibility' registry. + """ + + def __call__(self): + protect.CheckAuthenticator(self.request) + # Getting values from post + section_name = self.request.get('section_name', None) + if section_name is None: + return None + role_id = self.request.get('role_id', None) + if role_id is None: return None - role_permissions_list = [] - # Getting roles defined in the system - roles = [] - roles_tree = self.portal.acl_users.portal_role_manager.listRoleIds() - for role in roles_tree: - roles.append(role) - # Set view permissions to each role as 'yes': - # "role1,yes,role2,no,rol3,no" - for role in roles: - role_permissions_list.append(role) - role_permissions_list.append('yes') - role_permissions = ','.join(role_permissions_list) + check_state = self.request.get('check_state', None) + if check_state is None: + return None + elif check_state == 'false': + check_state = 'no' + else: + check_state = 'yes' + # Update registry + registry_info = get_dashboard_registry_record() + pairs = registry_info.get(section_name) + pairs = get_strings(pairs) + if pairs is None: + return None + if pairs == 'null': + # Registry hasn't been set yet + return None + pairs = pairs.split(',') + for i in range(len(pairs)): + if i % 2 == 0 and pairs[i] == role_id: + # update record + pairs[i + 1] = check_state + role_permissions = ','.join(pairs) # Set permissions string into dict registry_info[section_name] = get_unicode(role_permissions) - # Set new values to registry record - api.portal.set_registry_record( - 'bika.lims.dashboard_panels_visibility', registry_info) - return registry_info - - def _get_dashboard_registry_record(self): - """ - Return the 'bika.lims.dashboard_panels_visibility' values. - :return: A dictionary or None - """ - registry = api.portal.get_registry_record( - 'bika.lims.dashboard_panels_visibility') - if registry is None: - logger.warn('Registry bika.lims.dashboard_panels_visibility not ' - 'found.') - return None - return registry + set_dashboard_registry_record(registry_info) + return True diff --git a/bika/lims/browser/dashboard/templates/dashboard.pt b/bika/lims/browser/dashboard/templates/dashboard.pt index 470f12338b..c98d77ab65 100644 --- a/bika/lims/browser/dashboard/templates/dashboard.pt +++ b/bika/lims/browser/dashboard/templates/dashboard.pt @@ -195,6 +195,7 @@ loadPieCharts(); loadBarCharts(); dashboard_cookie_controller(); + role_permission_input_controller(); }); function loadBarCharts() { @@ -427,6 +428,32 @@ function build_cookie_data(data){ return JSON.stringify(data); }; + function role_permission_input_controller() { + /* Ajax post to update registry values */ + var section_id, role, chk_val; + var role_checks = $('input.role-permission-bloc-value'); + for(counter = 0; counter < role_checks.length; counter++){ + selector = role_checks[counter]; + $(selector).live('change', function(){ + section_id = $(this).attr('section_id'); + role = $(this).attr('role_id'); + chk_val = $(this).is(':checked'); + // AJAX post + $.ajax({ + dataType: 'json', + async: false, + type: 'POST', + url: 'dashboard_view_permissions_update', + data: { + 'section_name': section_id, + 'role_id': role, + 'check_state': chk_val, + '_authenticator': $('input[name=\'_authenticator\']').val() + } + }); + }); + } + } }(jQuery)); @@ -525,7 +552,10 @@ tal:content="python: role_value_pair[0]"> + tal:attributes=" + checked python: role_value_pair[1] == 'yes'; + role_id python: role_value_pair[0]; + section_id section_id;"> From 51557eb10093b9a8b025e3ec9e6e39e9e59e454d Mon Sep 17 00:00:00 2001 From: Espurna Date: Thu, 14 Dec 2017 16:06:51 +0100 Subject: [PATCH 04/11] checking user --- bika/lims/browser/dashboard/dashboard.py | 49 ++++++++++++++----- .../browser/dashboard/templates/dashboard.pt | 2 +- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/bika/lims/browser/dashboard/dashboard.py b/bika/lims/browser/dashboard/dashboard.py index 7ddb406c3d..357411dd8d 100644 --- a/bika/lims/browser/dashboard/dashboard.py +++ b/bika/lims/browser/dashboard/dashboard.py @@ -83,6 +83,23 @@ def setup_dashboard_panels_visibility_registry(section_name): return registry_info +def is_panel_visible_for_user(panel, user): + """ + Checks if the user is allowed to see the panel + :param panel: panel ID as tring + :param user: a MemberData object + :return: Boolean + """ + roles = user.getRoles() + panels_visibility = get_strings(get_dashboard_registry_record()) + pairs = panels_visibility.get(panel).split(',') + for i in range(len(pairs)): + if i % 2 == 0 and pairs[i] in roles: + if pairs[i+1] == 'yes': + return True + return False + + class DashboardView(BrowserView): template = ViewPageTemplateFile("templates/dashboard.pt") @@ -92,15 +109,11 @@ def __init__(self, context, request): self.member = None def __call__(self): - tofrontpage = True + tofrontpage = False mtool=getToolByName(self.context, 'portal_membership') - if not mtool.isAnonymousUser() and self.context.bika_setup.getDashboardByDefault(): - # If authenticated user with labman role, - # display the Main Dashboard view - pm = getToolByName(self.context, "portal_membership") - self.member = pm.getAuthenticatedMember() - roles = self.member.getRoles() - tofrontpage = 'Manager' not in roles and 'LabManager' not in roles + if mtool.isAnonymousUser() or \ + not self.context.bika_setup.getDashboardByDefault(): + tofrontpage = True if tofrontpage: self.request.response.redirect(self.portal_url + "/bika-frontpage") @@ -155,12 +168,17 @@ def is_filter_selected(self, selection_id, value): def is_admin_user(self): """ - Checks if the user is the admin user. + Checks if the user is the admin or a SiteAdmin user. :return: Boolean """ user = api.user.get_current() username = user and user.getUserName() or None - return username == 'admin' + if username == 'admin': + return True + roles = user.getRoles() + if 'Site Administrator' in roles: + return True + return False def _create_raw_data(self): """ @@ -262,9 +280,14 @@ def get_sections(self): 'title': , 'panels': } """ - sections = [self.get_analyses_section(), - self.get_analysisrequests_section(), - self.get_worksheets_section()] + sections = [] + user = api.user.get_current() + if is_panel_visible_for_user('analyses', user): + sections.append(self.get_analyses_section()) + if is_panel_visible_for_user('analysisrequests', user): + sections.append(self.get_analysisrequests_section()) + if is_panel_visible_for_user('worksheets', user): + sections.append(self.get_worksheets_section()) return sections def is_filter_enable(self): diff --git a/bika/lims/browser/dashboard/templates/dashboard.pt b/bika/lims/browser/dashboard/templates/dashboard.pt index c98d77ab65..1032ea9729 100644 --- a/bika/lims/browser/dashboard/templates/dashboard.pt +++ b/bika/lims/browser/dashboard/templates/dashboard.pt @@ -541,7 +541,7 @@
+ tal:condition="python: view.is_filter_enable() and view.is_admin_user()">

View permissions configuration

From 666a4d51a88e6d78d9f2c197004cceb4d8e6339f Mon Sep 17 00:00:00 2001 From: Espurna Date: Fri, 15 Dec 2017 11:58:45 +0100 Subject: [PATCH 05/11] fix is_filter_enable --- bika/lims/browser/dashboard/templates/dashboard.pt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bika/lims/browser/dashboard/templates/dashboard.pt b/bika/lims/browser/dashboard/templates/dashboard.pt index a8e4965768..21df91f97f 100644 --- a/bika/lims/browser/dashboard/templates/dashboard.pt +++ b/bika/lims/browser/dashboard/templates/dashboard.pt @@ -538,7 +538,7 @@
+ tal:condition="python: view.is_admin_user()">

View permissions configuration

From 6dc7a1da88242db379a5d4d813967436e2744ee2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Sat, 16 Dec 2017 22:59:03 +0100 Subject: [PATCH 06/11] dashboard view __call__ redux --- bika/lims/browser/dashboard/dashboard.py | 28 +++++++++++++----------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/bika/lims/browser/dashboard/dashboard.py b/bika/lims/browser/dashboard/dashboard.py index e21c1f9a44..d05fe910f2 100644 --- a/bika/lims/browser/dashboard/dashboard.py +++ b/bika/lims/browser/dashboard/dashboard.py @@ -36,7 +36,6 @@ def get_dashboard_registry_record(): if registry is None: logger.warn('Registry bika.lims.dashboard_panels_visibility not ' 'found.') - return None return registry @@ -109,18 +108,21 @@ def __init__(self, context, request): self.member = None def __call__(self): - tofrontpage = False - mtool=getToolByName(self.context, 'portal_membership') - if mtool.isAnonymousUser() or \ - not self.context.bika_setup.getDashboardByDefault(): - tofrontpage = True - - if tofrontpage: - self.request.response.redirect(self.portal_url + "/bika-frontpage") - else: - self._init_date_range() - self.dashboard_cookie = self.check_dashboard_cookie() - return self.template() + frontpage_url = self.portal_url + "/bika-frontpage" + if not self.context.bika_setup.getDashboardByDefault(): + # Do not render dashboard, render frontpage instead + self.request.response.redirect(frontpage_url) + return + + mtool = getToolByName(self.context, 'portal_membership') + if mtool.isAnonymousUser(): + # Anonymous user, redirect to frontpage + self.request.response.redirect(frontpage_url) + return + + self._init_date_range() + self.dashboard_cookie = self.check_dashboard_cookie() + return self.template() def check_dashboard_cookie(self): """ From 13995e95faf63ecff72cbc71ab1e84df2a05469a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Sat, 16 Dec 2017 23:24:49 +0100 Subject: [PATCH 07/11] Preventive checks if dashboard_panels_visibility not in registry_records --- bika/lims/browser/dashboard/dashboard.py | 34 +++++++++++++++--------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/bika/lims/browser/dashboard/dashboard.py b/bika/lims/browser/dashboard/dashboard.py index d05fe910f2..2b5e1bc68b 100644 --- a/bika/lims/browser/dashboard/dashboard.py +++ b/bika/lims/browser/dashboard/dashboard.py @@ -22,6 +22,7 @@ from bika.lims.catalog import CATALOG_WORKSHEET_LISTING from bika.lims.utils import get_strings from bika.lims.utils import get_unicode +from plone.api.exc import InvalidParameterError DASHBOARD_FILTER_COOKIE = 'dashboard_filter_cookie' @@ -31,12 +32,17 @@ def get_dashboard_registry_record(): Return the 'bika.lims.dashboard_panels_visibility' values. :return: A dictionary or None """ - registry = api.portal.get_registry_record( - 'bika.lims.dashboard_panels_visibility') - if registry is None: - logger.warn('Registry bika.lims.dashboard_panels_visibility not ' - 'found.') - return registry + try: + registry = api.portal.get_registry_record( + 'bika.lims.dashboard_panels_visibility') + return registry + except InvalidParameterError: + # No entry in the registry for dashboard panels roles. + # Maybe upgradestep 1.1.8 was not run? + logger.warn("Cannot find a record with name " + "'bika.lims.dashboard_panels_visibility' in " + "registry_record.") + return None def set_dashboard_registry_record(registry_info): @@ -90,7 +96,13 @@ def is_panel_visible_for_user(panel, user): :return: Boolean """ roles = user.getRoles() - panels_visibility = get_strings(get_dashboard_registry_record()) + settings = get_dashboard_registry_record() + if not settings: + # No configuration set in the registry_record. Assume that only Labman + # can see dashboard-panels + return "LabManager" in roles or "Manager" in roles + + panels_visibility = get_strings(settings) pairs = panels_visibility.get(panel).split(',') for i in range(len(pairs)): if i % 2 == 0 and pairs[i] in roles: @@ -120,6 +132,7 @@ def __call__(self): self.request.response.redirect(frontpage_url) return + self.member = mtool.getAuthenticatedMember() self._init_date_range() self.dashboard_cookie = self.check_dashboard_cookie() return self.template() @@ -168,13 +181,8 @@ def is_admin_user(self): :return: Boolean """ user = api.user.get_current() - username = user and user.getUserName() or None - if username == 'admin': - return True roles = user.getRoles() - if 'Site Administrator' in roles: - return True - return False + return "LabManager" or "Manager" in roles def _create_raw_data(self): """ From 64bf5e596b5a70708846160d55d77983312d5bf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Sat, 16 Dec 2017 23:58:59 +0100 Subject: [PATCH 08/11] More fixes just in case no record in registry --- bika/lims/browser/dashboard/dashboard.py | 46 ++++++++++++++++-------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/bika/lims/browser/dashboard/dashboard.py b/bika/lims/browser/dashboard/dashboard.py index 2b5e1bc68b..3157d9f6a7 100644 --- a/bika/lims/browser/dashboard/dashboard.py +++ b/bika/lims/browser/dashboard/dashboard.py @@ -16,6 +16,7 @@ from bika.lims import bikaMessageFactory as _ from bika.lims import logger +from bika.lims.api import get_tool from bika.lims.browser import BrowserView from bika.lims.catalog import CATALOG_ANALYSIS_LISTING from bika.lims.catalog import CATALOG_ANALYSIS_REQUEST_LISTING @@ -53,24 +54,32 @@ def set_dashboard_registry_record(registry_info): *unicode* objects. :return: A dictionary or None """ - api.portal.set_registry_record( - 'bika.lims.dashboard_panels_visibility', registry_info) + try: + api.portal.set_registry_record( + 'bika.lims.dashboard_panels_visibility', registry_info) + except InvalidParameterError: + # No entry in the registry for dashboard panels roles. + # Maybe upgradestep 1.1.8 was not run? + logger.warn("Cannot find a record with name " + "'bika.lims.dashboard_panels_visibility' in " + "registry_record.") def setup_dashboard_panels_visibility_registry(section_name): """ - It gives 'yes' values to all roles inside 'section_name' key values in - 'bika.lims.dashboard_panels_visibility' registry. + Initializes the values for panels visibility in registry_records. By + default, only users with LabManager or Manager roles can see the panels. :param section_name: :return: An string like: "role1,yes,role2,no,rol3,no" """ registry_info = get_dashboard_registry_record() if registry_info is None: - return None + # No record found in the registry + registry_info = {} role_permissions_list = [] # Getting roles defined in the system roles = [] - acl_users = api.get_tool("acl_users") + acl_users = get_tool("acl_users") roles_tree = acl_users.portal_role_manager.listRoleIds() for role in roles_tree: roles.append(role) @@ -78,7 +87,10 @@ def setup_dashboard_panels_visibility_registry(section_name): # "role1,yes,role2,no,rol3,no" for role in roles: role_permissions_list.append(role) - role_permissions_list.append('yes') + visible = 'no' + if role in 'LabManager' or 'Manager': + visible = 'yes' + role_permissions_list.append(visible) role_permissions = ','.join(role_permissions_list) # Set permissions string into dict @@ -97,7 +109,7 @@ def is_panel_visible_for_user(panel, user): """ roles = user.getRoles() settings = get_dashboard_registry_record() - if not settings: + if settings is None: # No configuration set in the registry_record. Assume that only Labman # can see dashboard-panels return "LabManager" in roles or "Manager" in roles @@ -732,21 +744,27 @@ def get_dashboard_panels_visibility(self, section_name): :param section_name: the panels section id. :return: a list of tuples. """ + # By default, only LabManager and Manager can see dashboard panels result = [] registry_info = get_dashboard_registry_record() if registry_info is None: - return result + # Registry hasn't been set, do it at least for this section + registry_info = \ + setup_dashboard_panels_visibility_registry(section_name) + pairs = registry_info.get(section_name) pairs = get_strings(pairs) if pairs is None: + # In the registry, but with None value? return result - if pairs == 'null': - # Registry hasn't been set yet - setup_dashboard_panels_visibility_registry(section_name) - return self.get_dashboard_panels_visibility(section_name) + pairs = pairs.split(',') + if len(pairs) == 0: + # An empty string? + return result + result = [ - (pairs[i], pairs[i+1]) for i in range(len(pairs)) if i % 2 == 0] + (pairs[i], pairs[i + 1]) for i in range(len(pairs)) if i % 2 == 0] return result From 08e13d96d5a7fcc804926ef8e9f64a952ff3a8ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Sun, 17 Dec 2017 00:35:03 +0100 Subject: [PATCH 09/11] More fixes and redux --- bika/lims/browser/dashboard/dashboard.py | 104 +++++++++++------------ 1 file changed, 48 insertions(+), 56 deletions(-) diff --git a/bika/lims/browser/dashboard/dashboard.py b/bika/lims/browser/dashboard/dashboard.py index 3157d9f6a7..87bc098838 100644 --- a/bika/lims/browser/dashboard/dashboard.py +++ b/bika/lims/browser/dashboard/dashboard.py @@ -42,8 +42,8 @@ def get_dashboard_registry_record(): # Maybe upgradestep 1.1.8 was not run? logger.warn("Cannot find a record with name " "'bika.lims.dashboard_panels_visibility' in " - "registry_record.") - return None + "registry_record. Missed upgrade 1.1.8?") + return dict() def set_dashboard_registry_record(registry_info): @@ -62,7 +62,7 @@ def set_dashboard_registry_record(registry_info): # Maybe upgradestep 1.1.8 was not run? logger.warn("Cannot find a record with name " "'bika.lims.dashboard_panels_visibility' in " - "registry_record.") + "registry_record. Missed upgrade 1.1.8?") def setup_dashboard_panels_visibility_registry(section_name): @@ -73,9 +73,6 @@ def setup_dashboard_panels_visibility_registry(section_name): :return: An string like: "role1,yes,role2,no,rol3,no" """ registry_info = get_dashboard_registry_record() - if registry_info is None: - # No record found in the registry - registry_info = {} role_permissions_list = [] # Getting roles defined in the system roles = [] @@ -88,7 +85,7 @@ def setup_dashboard_panels_visibility_registry(section_name): for role in roles: role_permissions_list.append(role) visible = 'no' - if role in 'LabManager' or 'Manager': + if role in ['LabManager', 'Manager']: visible = 'yes' role_permissions_list.append(visible) role_permissions = ','.join(role_permissions_list) @@ -100,26 +97,50 @@ def setup_dashboard_panels_visibility_registry(section_name): return registry_info +def get_dashboard_panels_visibility_by_section(section_name): + """ + Return a list of pairs as values that represents the role-permission + view relation for the panel section passed in. + :param section_name: the panels section id. + :return: a list of tuples. + """ + result = [] + registry_info = get_dashboard_registry_record() + if section_name not in registry_info: + # Registry hasn't been set, do it at least for this section + registry_info = \ + setup_dashboard_panels_visibility_registry(section_name) + + pairs = registry_info.get(section_name) + pairs = get_strings(pairs) + if pairs is None: + # In the registry, but with None value? + setup_dashboard_panels_visibility_registry(section_name) + return get_dashboard_panels_visibility_by_section(section_name) + + pairs = pairs.split(',') + if len(pairs) == 0 or len(pairs) % 2 != 0: + # Non-valid or malformed value + setup_dashboard_panels_visibility_registry(section_name) + return get_dashboard_panels_visibility_by_section(section_name) + + result = [ + (pairs[i], pairs[i + 1]) for i in range(len(pairs)) if i % 2 == 0] + return result + + def is_panel_visible_for_user(panel, user): """ Checks if the user is allowed to see the panel - :param panel: panel ID as tring + :param panel: panel ID as string :param user: a MemberData object :return: Boolean """ roles = user.getRoles() - settings = get_dashboard_registry_record() - if settings is None: - # No configuration set in the registry_record. Assume that only Labman - # can see dashboard-panels - return "LabManager" in roles or "Manager" in roles - - panels_visibility = get_strings(settings) - pairs = panels_visibility.get(panel).split(',') - for i in range(len(pairs)): - if i % 2 == 0 and pairs[i] in roles: - if pairs[i+1] == 'yes': - return True + visibility = get_dashboard_panels_visibility_by_section(panel) + for pair in visibility: + if pair[0] in roles and pair[1] == 'yes': + return True return False @@ -744,28 +765,7 @@ def get_dashboard_panels_visibility(self, section_name): :param section_name: the panels section id. :return: a list of tuples. """ - # By default, only LabManager and Manager can see dashboard panels - result = [] - registry_info = get_dashboard_registry_record() - if registry_info is None: - # Registry hasn't been set, do it at least for this section - registry_info = \ - setup_dashboard_panels_visibility_registry(section_name) - - pairs = registry_info.get(section_name) - pairs = get_strings(pairs) - if pairs is None: - # In the registry, but with None value? - return result - - pairs = pairs.split(',') - if len(pairs) == 0: - # An empty string? - return result - - result = [ - (pairs[i], pairs[i + 1]) for i in range(len(pairs)) if i % 2 == 0] - return result + return get_dashboard_panels_visibility_by_section(section_name) class DashboardViewPermissionUpdate(BrowserView): @@ -791,20 +791,12 @@ def __call__(self): check_state = 'yes' # Update registry registry_info = get_dashboard_registry_record() - pairs = registry_info.get(section_name) - pairs = get_strings(pairs) - if pairs is None: - return None - if pairs == 'null': - # Registry hasn't been set yet - return None - pairs = pairs.split(',') - - for i in range(len(pairs)): - if i % 2 == 0 and pairs[i] == role_id: - # update record - pairs[i + 1] = check_state - role_permissions = ','.join(pairs) + pairs = get_dashboard_panels_visibility_by_section(section_name) + role_permissions = list() + for pair in pairs: + value = '{0},{1}'.format(pair[0], pair[1]) + role_permissions.append(value) + role_permissions = ','.join(role_permissions) # Set permissions string into dict registry_info[section_name] = get_unicode(role_permissions) set_dashboard_registry_record(registry_info) From dc5794902c36942aaa722204ce7e9fd4e4294dbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Sun, 17 Dec 2017 01:52:46 +0100 Subject: [PATCH 10/11] Styling --- .../browser/dashboard/templates/dashboard.pt | 85 +++++++++++++------ 1 file changed, 60 insertions(+), 25 deletions(-) diff --git a/bika/lims/browser/dashboard/templates/dashboard.pt b/bika/lims/browser/dashboard/templates/dashboard.pt index 3131961cd5..95fe34e06c 100644 --- a/bika/lims/browser/dashboard/templates/dashboard.pt +++ b/bika/lims/browser/dashboard/templates/dashboard.pt @@ -26,14 +26,13 @@ padding: 20px 0 0; } .dashboard-section-head { - background-color: #ccc; + background-color: #e3e3e3; border-radius: 5px 5px 0 0; padding: 3px 15px; } .dashboard-section-head div.actions { float:right; text-align:right; - width:30%; } .dashboard-section-head div.actions select { padding: 0 5px; @@ -58,7 +57,7 @@ padding: 0 0 10px 2px; } .dashboard-panels { - border: 1px solid #ccc; + border: 1px solid #dcdcdc; border-radius: 0px 0px 5px 5px; padding: 5px 0; } @@ -201,13 +200,32 @@ float:right; } .toggle-barchart a { - padding: 10px; + padding: 0 10px 0; } .bar-chart-no-data { color: #b22222; font-size: 0.9em; padding: 20px; } + div.roles-visibility { + align-self: right; + background-color: #e3e3e3; + border: 1px solid #cdcdcd; + border-radius: 0 0 5px 5px; + padding: 5px; + position: absolute; + text-align: left; + z-index: 10; + } + div.roles-visibility div.checkbox label { + font-weight:normal; + } + a.dashboard-visibility-link { + margin-right:10px; + } + a.dashboard-visibility-link:after { + content: " ▼"; + }