From 441c009e8428cb7ff0ea1ffaccdafbc6fd9e3281 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Nowak?= <luke@nexedi.com> Date: Fri, 14 Jan 2011 12:06:58 +0000 Subject: [PATCH] - PAS Authentication Plugin to have passwordless logins for machines git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@42333 20353a03-c40f-0410-a6d1-a30d3c3de9de --- .../Vifib/VifibMachineAuthenticationPlugin.py | 153 ++++++++++++++++++ product/Vifib/__init__.py | 16 ++ ...ib_addVifibMachineAuthenticationPlugin.zpt | 46 ++++++ product/Vifib/www/portal.gif | Bin 0 -> 281 bytes 4 files changed, 215 insertions(+) create mode 100644 product/Vifib/VifibMachineAuthenticationPlugin.py create mode 100644 product/Vifib/www/Vifib_addVifibMachineAuthenticationPlugin.zpt create mode 100644 product/Vifib/www/portal.gif diff --git a/product/Vifib/VifibMachineAuthenticationPlugin.py b/product/Vifib/VifibMachineAuthenticationPlugin.py new file mode 100644 index 0000000000..344f7af89d --- /dev/null +++ b/product/Vifib/VifibMachineAuthenticationPlugin.py @@ -0,0 +1,153 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2010 Nexedi SA and Contributors. All Rights Reserved. +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsibility of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# guarantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +############################################################################## + +from zLOG import LOG, PROBLEM +from Products.ERP5Type.Globals import InitializeClass +from AccessControl import ClassSecurityInfo +import sys + +from Products.PageTemplates.PageTemplateFile import PageTemplateFile +from Products.PluggableAuthService.PluggableAuthService import \ + _SWALLOWABLE_PLUGIN_EXCEPTIONS +from Products.PluggableAuthService.interfaces import plugins +from Products.PluggableAuthService.utils import classImplements +from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin +from Products.ERP5Type.Cache import transactional_cached +from Products.ERP5Security.ERP5UserManager import SUPER_USER +from ZODB.POSException import ConflictError + +#Form for new plugin in ZMI +manage_addVifibMachineAuthenticationPluginForm = PageTemplateFile( + 'www/Vifib_addVifibMachineAuthenticationPlugin', globals(), + __name__='manage_addVifibMachineAuthenticationPluginForm') + +def addVifibMachineAuthenticationPlugin(dispatcher, id, title=None, REQUEST=None): + """ Add a VifibMachineAuthenticationPlugin to a Pluggable Auth Service. """ + + plugin = VifibMachineAuthenticationPlugin(id, title) + dispatcher._setObject(plugin.getId(), plugin) + + if REQUEST is not None: + REQUEST['RESPONSE'].redirect( + '%s/manage_workspace' + '?manage_tabs_message=' + 'VifibMachineAuthenticationPlugin+added.' + % dispatcher.absolute_url()) + +@transactional_cached(lambda portal, *args: args) +def getUserByLogin(portal, login): + if isinstance(login, basestring): + login = login, + result = portal.portal_catalog.unrestrictedSearchResults( + select_expression='reference', + portal_type=["Computer", "Software Instance"], + reference=dict(query=login, key='ExactMatch')) + # XXX: Here, we filter catalog result list ALTHOUGH we did pass + # parameters to unrestrictedSearchResults to restrict result set. + # This is done because the following values can match person with + # reference "foo": + # "foo " because of MySQL (feature, PADSPACE collation): + # mysql> SELECT reference as r FROM catalog + # -> WHERE reference="foo "; + # +-----+ + # | r | + # +-----+ + # | foo | + # +-----+ + # 1 row in set (0.01 sec) + # "bar OR foo" because of ZSQLCatalog tokenizing searched strings + # by default (feature). + return [x.getObject() for x in result if x['reference'] in login] + + +class VifibMachineAuthenticationPlugin(BasePlugin): + """ + Plugin to authenicate as machines. + """ + + meta_type = "Vifib Machine Authentication Plugin" + security = ClassSecurityInfo() + + manage_options = (({'label': 'Edit', + 'action': 'manage_editVifibMAchineAuthenticationPluginForm',}, + ) + + BasePlugin.manage_options[:] + ) + + def __init__(self, id, title=None): + #Register value + self._setId(id) + self.title = title + + ################################ + # IAuthenticationPlugin # + ################################ + security.declarePrivate('authenticateCredentials') + def authenticateCredentials(self, credentials): + """Authentificate with credentials""" + login = credentials.get('login', None) + # Forbidden the usage of the super user. + if login == SUPER_USER: + return None + + #Search the user by his login + user_list = self.getUserByLogin(login) + if len(user_list) != 1: + return None + return (login, login) + + def getUserByLogin(self, login): + # Search the Catalog for login and return a list of person objects + # login can be a string or a list of strings + # (no docstring to prevent publishing) + if not login: + return [] + if isinstance(login, list): + login = tuple(login) + elif not isinstance(login, tuple): + login = str(login) + try: + return getUserByLogin(self.getPortalObject(), login) + except ConflictError: + raise + except: + LOG('VifibMachineAuthenticationPlugin', PROBLEM, 'getUserByLogin failed', + error=sys.exc_info()) + # Here we must raise an exception to prevent callers from caching + # a result of a degraded situation. + # The kind of exception does not matter as long as it's catched by + # PAS and causes a lookup using another plugin or user folder. + # As PAS does not define explicitely such exception, we must use + # the _SWALLOWABLE_PLUGIN_EXCEPTIONS list. + raise _SWALLOWABLE_PLUGIN_EXCEPTIONS[0] + +#List implementation of class +classImplements(VifibMachineAuthenticationPlugin, + plugins.IAuthenticationPlugin) + +InitializeClass(VifibMachineAuthenticationPlugin) diff --git a/product/Vifib/__init__.py b/product/Vifib/__init__.py index dfe1f3aec4..ef20ddb189 100644 --- a/product/Vifib/__init__.py +++ b/product/Vifib/__init__.py @@ -28,6 +28,7 @@ # ############################################################################## from Products.ERP5Type.Utils import initializeProduct, updateGlobals +from AccessControl.Permissions import manage_users as ManageUsers import sys import Permissions this_module = sys.modules[ __name__ ] @@ -38,6 +39,9 @@ content_classes = () content_constructors = () from Tool import SlapTool portal_tools = ( SlapTool.SlapTool, ) +from Products.PluggableAuthService.PluggableAuthService import registerMultiPlugin + +import VifibMachineAuthenticationPlugin def initialize(context): import Document @@ -45,3 +49,15 @@ def initialize(context): document_classes=document_classes, object_classes=object_classes, portal_tools=portal_tools, content_constructors=content_constructors, content_classes=content_classes) + + context.registerClass( VifibMachineAuthenticationPlugin.VifibMachineAuthenticationPlugin + , permission=ManageUsers + , constructors=( + VifibMachineAuthenticationPlugin.manage_addVifibMachineAuthenticationPluginForm, + VifibMachineAuthenticationPlugin.addVifibMachineAuthenticationPlugin, ) + , visibility=None + , icon='www/portal.gif' + ) + + +registerMultiPlugin(VifibMachineAuthenticationPlugin.VifibMachineAuthenticationPlugin.meta_type) diff --git a/product/Vifib/www/Vifib_addVifibMachineAuthenticationPlugin.zpt b/product/Vifib/www/Vifib_addVifibMachineAuthenticationPlugin.zpt new file mode 100644 index 0000000000..ed20b3bd7b --- /dev/null +++ b/product/Vifib/www/Vifib_addVifibMachineAuthenticationPlugin.zpt @@ -0,0 +1,46 @@ +<h1 tal:replace="structure here/manage_page_header">Header</h1> + +<h2 tal:define="form_title string:Add Vifib Machine Authentication Plugin" + tal:replace="structure here/manage_form_title">Form Title</h2> + +<p class="form-help"> +Vifib Machine Authentication Plugin allows to login machines (Computers and +Software Instances) +</p> + +<form action="addVifibMachineAuthenticationPlugin" method="post"> +<table cellspacing="0" cellpadding="2" border="0"> + <tr> + <td align="left" valign="top"> + <div class="form-label"> + Id + </div> + </td> + <td align="left" valign="top"> + <input type="text" name="id" size="40" /> + </td> + </tr> + <tr> + <td align="left" valign="top"> + <div class="form-optional"> + Title + </div> + </td> + <td align="left" valign="top"> + <input type="text" name="title" size="40" /> + </td> + </tr> + <tr> + <td align="left" valign="top"> + </td> + <td align="left" valign="top"> + <div class="form-element"> + <input class="form-element" type="submit" name="submit" + value=" Add " /> + </div> + </td> + </tr> +</table> +</form> + +<h1 tal:replace="structure here/manage_page_footer">Footer</h1> diff --git a/product/Vifib/www/portal.gif b/product/Vifib/www/portal.gif new file mode 100644 index 0000000000000000000000000000000000000000..dabd2e37c4bdc1bcfae8481290554df8b0db3290 GIT binary patch literal 281 zcmV+!0p|WkNk%w1VGsZi0E7SltgO8=Gh7T1K>z?V2M0MjJ7U(>-WfAyDN=<qW|=}l zXy4!E6DL|PUXdwQix7UX0KNDUbEyE#|4&bH|NsB8vcVV_MgW7_0HEmyhROzW!xc@E z0A|d+y~+q!umAu5A^8LW6aXIpEC2ui01yBW000G+;3s}SAPfUh0OM#B#DOFUauCYm z22A5T5J<$)U<7oZLhm7IIv>ReiO_gZD3Yr)(hyV%2Zs~ult3H@1pyHWy5B;CWstaF z?)ZErL7;0cfPsP<2?GKM8yt#@j2j373So?s9B2v^0u70j92*S;9Ul`tn~hN-20T6+ f9v&M+3^^kUYBDr70ux9r6$%0b1QrvaBOw4gk`!EV literal 0 HcmV?d00001 -- 2.30.9