-
-
Notifications
You must be signed in to change notification settings - Fork 195
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #329 from plone/jcerjak-plip10359-security-control…
…panel Jcerjak plip10359 security controlpanel
- Loading branch information
Showing
20 changed files
with
1,192 additions
and
57 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,4 +7,6 @@ | |
<include package=".bbb" /> | ||
<include package=".browser" /> | ||
|
||
<include file="events.zcml" /> | ||
|
||
</configure> |
Oops, something went wrong.