Passed
Push — 2.x ( 285083...cd4fe9 )
by Jordi
06:30
created

UserDataPanel.label()   A

Complexity

Conditions 2

Size

Total Lines 8
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 2
nop 1
1
# -*- coding: utf-8 -*-
2
3
from bika.lims import api
4
from bika.lims import senaiteMessageFactory as _
5
from bika.lims.interfaces import IContact
6
from bika.lims.interfaces import ILabContact
7
from plone.app.users.browser.account import getSchema
8
from plone.app.users.browser.userdatapanel import UserDataPanel as Base
9
from plone.app.users.browser.userdatapanel import UserDataPanelAdapter
10
from plone.app.users.schema import ProtectedEmail
11
from plone.app.users.schema import ProtectedTextLine
12
from plone.app.users.schema import checkEmailAddress
13
from plone.autoform import directives
14
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
15
from senaite.core.catalog import CONTACT_CATALOG
16
from senaite.core.z3cform.widgets.uidreference.widget import \
17
    UIDReferenceWidgetFactory
18
from z3c.form.interfaces import DISPLAY_MODE
19
from zope.interface import Interface
20
from zope.schema import TextLine
21
22
23
class IUserDataSchema(Interface):
24
    """Custom User Data Schema
25
    """
26
27
    fullname = ProtectedTextLine(
28
        title=_(u"label_user_full_name", default=u"Full Name"),
29
        description=_(u"help_full_name_creation",
30
                      default=u"Enter full name, e.g. John Smith."),
31
        required=False)
32
33
    email = ProtectedEmail(
34
        title=_(u"label_user_email", default=u"Email"),
35
        description=u"We will use this address if you need to recover your "
36
                    u"password",
37
        required=True,
38
        constraint=checkEmailAddress,
39
    )
40
41
    # Field behaves like a readonly field
42
    directives.mode(contact=DISPLAY_MODE)
43
    directives.widget("contact", UIDReferenceWidgetFactory)
44
    contact = TextLine(
45
        title=_(u"label_user_contact", default=u"Contact"),
46
        description=_(u"description_user_contact",
47
                      default=u"User is linked to a contact. "
48
                      u"Please change your settings in the contact profile."),
49
        required=False,
50
    )
51
52
53
def getUserDataSchema():
54
    form_name = u"In User Profile"
55
    # This is needed on Plone 6, but has a bad side effect on Plone 5:
56
    # as Manager you go to a member and then to your own personal-information
57
    # form and you see the data of the member you just visited.
58
    # I keep the code here commented out as warning in case someone compares
59
    # the code.
60
    # if getSecurityManager().checkPermission('Manage portal', portal):
61
    #     form_name = None
62
    schema = getSchema(
63
        IUserDataSchema, UserDataPanelAdapter, form_name=form_name)
64
    return schema
65
66
67
class UserDataPanel(Base):
68
    """Provides user properties in the profile
69
    """
70
    template = ViewPageTemplateFile("templates/account-panel.pt")
71
72
    def __init__(self, context, request):
73
        super(UserDataPanel, self).__init__(context, request)
74
75
    def __call__(self):
76
        submitted = self.request.form.get("Save", False)
77
        if not submitted:
78
            self.notify_linked_user()
79
        return super(UserDataPanel, self).__call__()
80
81
    def _on_save(self, data=None):
82
        contact = api.get_user_contact(self.member)
83
        if not contact:
84
            return
85
        # update the fullname
86
        fullname = data.get("fullname")
87
        if fullname:
88
            contact.setFullname(fullname)
89
        # update the email
90
        email = data.get("email")
91
        if email:
92
            contact.setEmailAddress(email)
93
94
    @property
95
    def label(self):
96
        fullname = self.member.getProperty("fullname")
97
        username = self.member.getUserName()
98
        if fullname:
99
            # username/fullname are already encoded in UTF8
100
            return "%s (%s)" % (fullname, username)
101
        return username
102
103
    @property
104
    def schema(self):
105
        schema = getUserDataSchema()
106
        return schema
107
108
    def updateWidgets(self, prefix=None):
109
        super(UserDataPanel, self).updateWidgets(prefix=prefix)
110
        # check if we are linked to a contact
111
        contact = self.get_linked_contact()
112
        if not contact:
113
            # remove the widget and return
114
            return self.remove_widgets("contact")
115
        # update the contact widget and remove the email/fullname widgets
116
        widget = self.widgets.get("contact")
117
        if widget:
118
            widget.value = api.safe_unicode(api.get_uid(contact))
119
            # remove the email/fullname widgets
120
            self.remove_widgets("email", "fullname")
121
122
    def remove_widgets(self, *names):
123
        """Removes the widgets from the form
124
        """
125
        for name in names:
126
            widget = self.widgets.get(name)
127
            if not widget:
128
                continue
129
            del self.widgets[name]
130
131
    def get_linked_contact(self):
132
        """Returns the linked contact object
133
        """
134
        query = {"getUsername": self.member.getId()}
135
        brains = api.search(query, CONTACT_CATALOG)
136
        if len(brains) == 0:
137
            return None
138
        return api.get_object(brains[0])
139
140
    def notify_linked_user(self):
141
        """Add notification message if user is linked to a contact
142
        """
143
        contact = self.get_linked_contact()
144
        if ILabContact.providedBy(contact):
145
            self.add_status_message(
146
                _("User is linked to lab contact '%s'" %
147
                  contact.getFullname()))
148
        elif IContact.providedBy(contact):
149
            self.add_status_message(
150
                _("User is linked to the client contact '%s' (%s)" %
151
                  (contact.getFullname(), contact.aq_parent.getName())))
152
153
    def add_status_message(self, message, level="info"):
154
        """Add a portal status message
155
        """
156
        plone_utils = api.get_tool("plone_utils")
157
        return plone_utils.addPortalMessage(message, level)
158
159
160
class UserDataConfiglet(UserDataPanel):
161
    """Control panel version of the userdata panel
162
    """
163
    template = ViewPageTemplateFile("templates/account-configlet.pt")
164