Skip to content

Commit

Permalink
Revert "Revert "Plip10359 - move security controlpanel from plone.app…
Browse files Browse the repository at this point in the history
….controlpanel""

This reverts commit f6f4456.
  • Loading branch information
jcerjak committed Nov 16, 2014
1 parent 858a53a commit 7b6f30f
Show file tree
Hide file tree
Showing 18 changed files with 1,115 additions and 0 deletions.
1 change: 1 addition & 0 deletions Products/CMFPlone/controlpanel/bbb/configure.zcml
Expand Up @@ -7,6 +7,7 @@
<adapter factory=".maintenance.MaintenanceControlPanelAdapter" />
<adapter factory=".navigation.NavigationControlPanelAdapter" />
<adapter factory=".search.SearchControlPanelAdapter" />
<adapter factory=".security.SecurityControlPanelAdapter" />
<adapter factory=".site.SiteControlPanelAdapter" />
<adapter factory=".markup.MarkupControlPanelAdapter" />

Expand Down
78 changes: 78 additions & 0 deletions Products/CMFPlone/controlpanel/bbb/security.py
@@ -0,0 +1,78 @@
# -*- coding: utf-8 -*-
from Products.CMFCore.utils import getToolByName
from Products.CMFPlone.interfaces.siteroot import IPloneSiteRoot
from Products.CMFPlone.interfaces import ISecuritySchema
from plone.registry.interfaces import IRegistry
from zope.component import adapts
from zope.component import getUtility
from zope.interface import implements
from zope.site.hooks import getSite


class SecurityControlPanelAdapter(object):

adapts(IPloneSiteRoot)
implements(ISecuritySchema)

def __init__(self, context):
self.portal = getSite()
self.pmembership = getToolByName(context, 'portal_membership')
registry = getUtility(IRegistry)
self.settings = registry.forInterface(
ISecuritySchema, prefix="plone")

def get_enable_self_reg(self):
return self.settings.enable_self_reg

def set_enable_self_reg(self, value):
# additional processing in the event handler
self.settings.enable_self_reg = value

enable_self_reg = property(get_enable_self_reg, set_enable_self_reg)

def get_enable_user_pwd_choice(self):
return self.settings.enable_user_pwd_choice

def set_enable_user_pwd_choice(self, value):
self.settings.enable_user_pwd_choice = value

enable_user_pwd_choice = property(get_enable_user_pwd_choice,
set_enable_user_pwd_choice)

def get_enable_user_folders(self):
return self.settings.enable_user_folders

def set_enable_user_folders(self, value):
# additional processing in the event handler
self.settings.enable_user_folders = value

enable_user_folders = property(get_enable_user_folders,
set_enable_user_folders)

def get_allow_anon_views_about(self):
return self.settings.allow_anon_views_about

def set_allow_anon_views_about(self, value):
self.settings.allow_anon_views_about = value

allow_anon_views_about = property(get_allow_anon_views_about,
set_allow_anon_views_about)

def get_use_email_as_login(self):
return self.settings.use_email_as_login

def set_use_email_as_login(self, value):
# additional processing in the event handler
self.settings.use_email_as_login = value

use_email_as_login = property(get_use_email_as_login,
set_use_email_as_login)

def get_use_uuid_as_userid(self):
return self.settings.use_uuid_as_userid

def set_use_uuid_as_userid(self, value):
self.settings.use_uuid_as_userid = value

use_uuid_as_userid = property(get_use_uuid_as_userid,
set_use_uuid_as_userid)
17 changes: 17 additions & 0 deletions Products/CMFPlone/controlpanel/browser/configure.zcml
Expand Up @@ -57,6 +57,23 @@
permission="plone.app.controlpanel.Search"
/>

<!-- Security Control Panel -->
<browser:page
name="security-controlpanel"
for="Products.CMFPlone.interfaces.IPloneSiteRoot"
class=".security.SecurityControlPanel"
permission="plone.app.controlpanel.Security"
/>

<!-- Security Control Panel - EMail Login -->
<browser:page
for="Products.CMFPlone.interfaces.IPloneSiteRoot"
name="migrate-to-emaillogin"
class=".security.EmailLogin"
template="emaillogin.pt"
permission="cmf.ManagePortal"
/>

<!-- Site Control Panel -->
<browser:page
name="site-controlpanel"
Expand Down
67 changes: 67 additions & 0 deletions Products/CMFPlone/controlpanel/browser/emaillogin.pt
@@ -0,0 +1,67 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
metal:use-macro="context/prefs_main_template/macros/master"
i18n:domain="plone">

<body>

<metal:main metal:fill-slot="prefs_configlet_content">
<h1 class="documentFirstHeading"
i18n:translate="heading_find_duplicate_login_names">
Find duplicate login names
</h1>

<p i18n:translate="help_duplicate_login_names">
Switching the email login setting in the
<a i18n:name="link"
tal:attributes="href string:${context/portal_url}/@@security-controlpanel"
i18n:translate="">Security settings</a>
on or off automatically changes the login name for existing users.
This may fail when there are duplicates.
On this page you can search for duplicates.
</p>

<div tal:condition="request/form/submitted|nothing">
<div tal:condition="view/duplicates">
<p i18n:translate="msg_login_duplicates_found">
The following login names would be used by more than one account:
</p>
<ul>
<ol tal:repeat="dup view/duplicates">
<span tal:content="python:dup[0]" />:
<span tal:repeat="account python:dup[1]" tal:content="account" />
</ol>
</ul>
</div>
<div tal:condition="not:view/duplicates">
<p i18n:translate="msg_no_login_duplicates_found">
No login names found that are used by more than one account.
</p>
</div>
</div>

<form action=""
name="emaillogin-migrate"
method="post"
class="enableUnloadProtection enableAutoFocus">
<div class="formControls">
<input type="hidden" name="submitted" value="submitted" id="submitted" />
<input class="context"
type="submit"
name="check_email"
value="Check for duplicate emails"
i18n:attributes="value label_check_duplicate_emails" />
<br />
<input class="context"
type="submit"
name="check_userid"
value="Check for duplicate lower case user ids"
i18n:attributes="value label_check_duplicate_user_ids" />
</div>
</form>

</metal:main>
</body>
</html>
127 changes: 127 additions & 0 deletions Products/CMFPlone/controlpanel/browser/security.py
@@ -0,0 +1,127 @@
from Acquisition import aq_inner
from Products.CMFCore.utils import getToolByName
from Products.CMFPlone import PloneMessageFactory as _
from Products.CMFPlone.controlpanel.utils import migrate_to_email_login
from Products.CMFPlone.controlpanel.utils import migrate_from_email_login
from Products.CMFPlone.interfaces import ISecuritySchema
from Products.Five.browser import BrowserView
from collections import defaultdict
from plone.app.registry.browser import controlpanel

import logging

logger = logging.getLogger('Products.CMFPlone')


class SecurityControlPanelForm(controlpanel.RegistryEditForm):

id = "SecurityControlPanel"
label = _(u"Security settings")
schema = ISecuritySchema
schema_prefix = "plone"


class SecurityControlPanel(controlpanel.ControlPanelFormWrapper):
form = SecurityControlPanelForm


class EmailLogin(BrowserView):
"""View to help in migrating to or from using email as login.
We used to change the login name of existing users here, but that
is now done by checking or unchecking the option in the security
control panel. Here you can only search for duplicates.
"""

duplicates = []

def __call__(self):
if self.request.form.get('check_email'):
self.duplicates = self.check_email()
elif self.request.form.get('check_userid'):
self.duplicates = self.check_userid()
return self.index()

@property
def _email_list(self):
context = aq_inner(self.context)
pas = getToolByName(context, 'acl_users')
emails = defaultdict(list)
orig_transform = pas.login_transform
try:
if not orig_transform:
# Temporarily set this to lower, as that will happen
# when turning emaillogin on.
pas.login_transform = 'lower'
for user in pas.getUsers():
if user is None:
# Created in the ZMI?
continue
email = user.getProperty('email', '')
if email:
email = pas.applyTransform(email)
else:
logger.warn("User %s has no email address.",
user.getUserId())
# Add the normal login name anyway.
email = pas.applyTransform(user.getUserName())
emails[email].append(user.getUserId())
finally:
pas.login_transform = orig_transform
return emails

def check_email(self):
duplicates = []
for email, userids in self._email_list.items():
if len(userids) > 1:
logger.warn("Duplicate accounts for email address %s: %r",
email, userids)
duplicates.append((email, userids))

return duplicates

@property
def _userid_list(self):
# user ids are unique, but their lowercase version might not
# be unique.
context = aq_inner(self.context)
pas = getToolByName(context, 'acl_users')
userids = defaultdict(list)
orig_transform = pas.login_transform
try:
if not orig_transform:
# Temporarily set this to lower, as that will happen
# when turning emaillogin on.
pas.login_transform = 'lower'
for user in pas.getUsers():
if user is None:
continue
login_name = pas.applyTransform(user.getUserName())
userids[login_name].append(user.getUserId())
finally:
pas.login_transform = orig_transform
return userids

def check_userid(self):
duplicates = []
for login_name, userids in self._userid_list.items():
if len(userids) > 1:
logger.warn("Duplicate accounts for lower case user id "
"%s: %r", login_name, userids)
duplicates.append((login_name, userids))

return duplicates

def switch_to_email(self):
# This is not used and is only here for backwards
# compatibility. It avoids a test failure in
# Products.CMFPlone.
# XXX: check if this can be removed
migrate_to_email_login(self.context)

def switch_to_userid(self):
# This is not used and is only here for backwards
# compatibility. It avoids a test failure in
# Products.CMFPlone.
# XXX: check if this can be removed
migrate_from_email_login(self.context)
2 changes: 2 additions & 0 deletions Products/CMFPlone/controlpanel/configure.zcml
Expand Up @@ -7,4 +7,6 @@
<include package=".bbb" />
<include package=".browser" />

<include file="events.zcml" />

</configure>

0 comments on commit 7b6f30f

Please sign in to comment.