Source code for ploneintranet.userprofile.content.userprofile
# coding=utf-8
from collective import dexteritytextindexer
from plone import api as plone_api
from plone.autoform import directives
from plone.autoform.interfaces import IFormFieldProvider
from plone.dexterity.content import Container
from plone.namedfile.field import NamedBlobImage
from plone.supermodel import model
from ploneintranet.core import ploneintranetCoreMessageFactory as _
from Products.CMFPlone.utils import safe_unicode
from z3c.form import validator
from zope import schema
from zope.interface import implementer
from zope.interface import Invalid
from zope.interface import provider
[docs]class Email(schema.TextLine):
""" An email field
"""
[docs]class Phone(schema.TextLine):
""" A phone field
"""
[docs]class GooglePlace(schema.Choice):
""" A field that is linked in the display view to a google place search
"""
[docs]class IUserProfile(model.Schema):
"""The core user profile schema.
Most of the plone intranet UI relies on these fields.
"""
# username == context.getId() == userid
# username should never be changed because it's used as an alias for userid
# if you need different login names, switch on use_email_as_username
# see changeset and docs in quaive/ploneintranet#1043
dexteritytextindexer.searchable("username")
username = schema.TextLine(title=_(u"Username"), required=True, default=u"")
dexteritytextindexer.searchable("person_title")
person_title = schema.TextLine(
title=_(u"Person title"), required=False, default=u""
)
dexteritytextindexer.searchable("first_name")
first_name = schema.TextLine(title=_(u"First name"), required=True, default=u"")
dexteritytextindexer.searchable("last_name")
last_name = schema.TextLine(title=_(u"Last name"), required=True, default=u"")
dexteritytextindexer.searchable("email")
email = Email(title=_(u"Email"), required=True, default=u"")
portrait = NamedBlobImage(title=_(u"Photo"), required=False, default=None)
directives.omitted("recent_contacts")
recent_contacts = schema.List(title=_("Last Contacts"), required=False, default=[])
[docs]@provider(IFormFieldProvider)
class IUserProfileAdditional(model.Schema):
"""Default additional fields for UserProfile."""
dexteritytextindexer.searchable("job_title")
job_title = schema.TextLine(title=_(u"Job title"), required=False, default=u"")
dexteritytextindexer.searchable("department")
department = schema.TextLine(title=_(u"Department"), required=False, default=u"")
dexteritytextindexer.searchable("telephone")
telephone = Phone(title=_(u"Telephone Number"), required=False, default=u"")
dexteritytextindexer.searchable("mobile")
mobile = Phone(title=_(u"Mobile Number"), required=False, default=u"")
dexteritytextindexer.searchable("address")
address = schema.Text(title=_(u"Address"), required=False, default=u"")
time_zone = schema.Choice(
title=_(u"Time Zone"),
source=u"plone.app.vocabularies.CommonTimezones",
required=False,
)
primary_location = GooglePlace(
title=_(u"Primary location"),
source=u"ploneintranet.userprofile.locations_vocabulary",
required=False,
)
dexteritytextindexer.searchable("biography")
biography = schema.Text(title=_(u"Biography"), required=False, default=u"")
[docs]@implementer(IUserProfile)
class UserProfile(Container):
"""UserProfile content type."""
[docs] def Title(self):
return self.fullname
[docs] def Description(self):
return getattr(self, "job_title", None)
@property
def fullname(self):
names = [self.person_title, self.first_name, self.last_name]
return u" ".join([name for name in names if name])
@property
def initials(self):
first_name = self.first_name or ""
last_name = self.last_name or ""
return first_name[:1].upper() + last_name[:2].capitalize()
@property
def display_name_email(self):
if not self.email:
return ""
return u"{} <{}>".format(
safe_unicode(self.fullname or self.email), safe_unicode(self.email)
)
[docs]class UsernameValidator(validator.SimpleFieldValidator):
"""Two users can't have the same username.
Because of #1043 it's possible that .username != .getUserName()
so instead we rely on .username == .getUserId() which holds true
since we don't do use_uuid_as_userid.
"""
[docs] def validate(self, value, force=False):
membrane_tool = plone_api.portal.get_tool("membrane_tool")
usernames = membrane_tool._catalog.uniqueValuesFor("exact_getUserId")
if value in usernames:
brains = membrane_tool.searchResults(exact_getUserId=value)
if brains and self.context != brains[0].getObject():
raise Invalid(_("A user with this username already exists"))
return super(UsernameValidator, self).validate(value)
validator.WidgetValidatorDiscriminators(
UsernameValidator, field=IUserProfile["username"]
)