Re: [Zope-dev] REQUEST.AUTHENTICATED_USER question
Excellent! Precisely what I'm looking for. Thanks! Vio * Jens Vagelpohl [EMAIL PROTECTED] [020124 10:46]: vio, for your situation the simplest thing would be to use the CookieUserFolder (see http://www.dataflake.org/software/cookieuserfolder) which is as simple as the standard user folder and adds cookie-capability and customizable login and logout forms. no need to get all tripped up in zpatterns or user auth sources or other confusing stuff. jens ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] REQUEST.AUTHENTICATED_USER question
First, thanks for your time on this thread, everybody! * Leonardo Rochael Almeida [EMAIL PROTECTED] [020123 19:42]: Hi Vio, By the contents of your message, you seem to be a little off track w.r.t. the way authentication works between the browser and Zope. By now you seem to have discovered that the browser sends the user credentials whenever it fetches a page. If you aren't using a custom user folder that uses cookies, then you're most likely using basic authentication (which is likely since you don't want the overhead of a product). To know for sure answer this question: when you are anonymous and you want to access a forbiden area, does the browser-standard-login-popup-window shows up? yes. If yes, then there simply is no way you can use a few placed calls to the Zope machinery to convince the browser that it needs to switch identities because you're talking to Zope, not to the browser. Zope cannot tell the browser stop pretending you are anonymous and start pretending you're John. The only thing Zope can tell the browser is This user you are using is not authorized, in which case the browser will ask the user for another login/password combo, using it's own standard login popup window. Ok, maybe I didn't express myself very clearly in my past messages. Imagine the following simple scenario, which makes heavy use of 'CoreSessionTracking', by the way: 1. In my 'standard_html_header' I put a dtml routine who checks for a specific session variable, let's call it 'user_id'. If it isn't there, or there is no session running, it redirects user to my custom 'loginForm'. dtml-if sessionData.get('user_id') get the beef dtml-else redirect to loginForm 2. The manage_login() who processes the 'loginForm' data, validates user credentials against some internal list. Actually, for now I'm using a standard Users_folder object, but I am tempted to swich to something even simpler, like a dictionary or a list. I hope you follow me up to now. In that list, each user_id has also associated with it a list of roles. So here we have a central list of 'authorised' users (or a UsersFolder): clean_users.append([user_id, password, list_of_roles]) or Users_folder._addUser(name,password,confirm,roles,domains) Session-storing the credentials: manage_login() stores this related data as session variables: sessionData.set('user_id',user_id) sessionData.set('user_roles', list_of_roles) 3. Make all user-visible objects in my product 'Public', knowing that they are not 'really' public: any user without a 'user_id' session variable will get redirected to my custom login page 'no matter what'. But Zope's own security machinery is out of the loop on this one (simply by-passed). 4. The little routine in 'standard_html_header' will take care of all dtml. But I will need to call a similar validating method (or specialized instance) before running any 'executable' code: by 'executable' I mean code who Creates, Destroys, Modifies restricted objects, or modifies my custom security settings. This code simply compares content of 'user_roles' session variable with 'my_object_permissions' object attribute (which can be acquired). Only if there's a match, the 'executable' python code is allowed to run. An alternative here would have been to protect all objects with a Zope permission (instead of declaring everything public), then switch to a user with that permission for the duration of this transaction with: SecurityManagement.newSecurityManager(None, UserWithPermission) This is what I ment with a few well placed calls to the Zope machinery. Of course I know I'm not talking to the browser, which is but a dumb client with cookies (and no milk). So it's not the browser who tells Zope I'm doctor Zoidberg, but my own code (which acts like a proxy). In my view, this scenario implements Zope's security core 'principles' of 'Roles' matching 'Permissions', but using CoreSessionTracking. Writing this isn't as complicated as it sounds, only cumbersome to paste code into existing python classes, and edit many dtml pages to add a 'myPermissions' input field to all objects (or at least to the top objects in my hierarchy, and let those custom permissions get acquired from lower down). A full evening's work, for sure. (I think all hackers are optimists by nature) My alternative being to study and understand an existing cookie-based user-folder product, and make it play nice with my own code. Having tried the latter for the last week without satisfactory results (again, only my fault if I don't understand totally how things work), I must admit that giving a shot at the former scenario sounds quite tempting. Let's see ... But many thanks for all your help and suggestion, which has been very appreciated and useful. If you smell something rotten in my stuff here, please do let me know (besides the fact that I am trying to re
Re: [Zope-dev] REQUEST.AUTHENTICATED_USER question
* Leonardo Rochael Almeida [EMAIL PROTECTED] [020124 00:03]: Hi vio, Pardon our insistence in helping you out, but you asked to be told if something in your description smelt rotten and, besides the fact that yes, you are reinventing the wheel (and reinventing it square, by the way :-), there isn't a single thing in the scenario you described below that isn't possible with plain vanilla Zope (ok, plain vanilla Zope is an oxymoron. There is nothing 'plain' about an out-of-the-box Zope, but I digress :-), you don't even need CoreSessionTracking as far as I understand it! First, thanks again for 'insisting' in helping me out. Really appreciate it! Ok, you asked what I really want, and it's very 'plain vanilla' stuff. In a sentence: to log users from a custom dtml page. Period. In more than one sentence: I want to 'integrate' the login process and 'user management' into my own product, give it my own product's 'look and feel', to create a consistent GUI and user experience. Idealy, I'd prefer just using plain Zope, no additional 3rd party products. But I really would prefer to present the user with a nicely customised login page instead of the standard Zope dialog. Well, that's about it. Looking for a solution here has been a great learning experience into Zope security, first of all. Now all your suggestions are pointing out towards using an existing product, 2 names flying around: LoginManager and exUserFolder. LoginManager would seem more appealing, as some comments I've read would suggest that it's very customizable. My problem with that is that Zope won't 'chew' it properly, spits it out with ImportError: can't import name 'expr_globals' in Products/ZPatterns/Expressions.py line 38. Indeed, after browsing the sources, no trace of 'expr_globals' anywhere. Deprecated? Any idea what this was replaced with (by the way, in case you're wondering, I'm running on Zope 2.4.1 with python 2.1, while on the other hand LoginManager-0-8-8b1 with ZPatterns-0-4-3b1 and PlugIns-0-4-3b1 are trying to earn a living on my hard drive). exUserFolder installed ok, so I'll give it a test drive also. But some hints on debugging LoginMgr would be also appreciated. Cheers, Vio ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
[Zope-dev] REQUEST.AUTHENTICATED_USER question
Hi, Does anybody know what is the method call to modify the AUTHENTICATED_USER attribute? I am unable to trace where REQUEST feeds data for its AUTHENTICATED_USER attribute. Some context to my question: I am using a custom method to authenticate users coming to my site. So when the user logs in, he is 'Anonymous User' (from call: AUTHENTICATED_USER.getUserName()). But after his login name and password checked ok, how do I switch his identity in Zope from 'Anonymous User' to his/her new identity? What I am looking for is that next time I call 'REQUEST.AUTHENTICATED_USER.getUserName()' to get the new UserName he just logged in as, not 'Anonymous User' again. Examining CookieCrumbler.py source, this authentication product uses the 'before_publishing_traverse hook' mechanism. But isn't there a simpler way to do this than modifying REQUEST.RESPONSE at each traversal? Sounds like a lot of overhead. Vio ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Security Gurus Wanted
Just a word to thank you for your reply. But incidently, wouldn't it be a good idea for Globals.InitializeClass() to throw an error or a warning of some kind for hanging 'security.stuff()' declarations, declarations which do not have a related ClassSecurityInfo object AT THE CLASS LEVEL? To the unaware beginner (like myself) this creates a very obscure bug: the declaration at the module level 'hiding' the missing ClassSecurityInfo object (at the class level). I see some other discussions on this list on this topic, so maybe this problem is already being addressed. Anyway, I would never have found this alone by a long shot. Thanks. Sorry for the cross-post. * Steve Alexander [EMAIL PROTECTED] [020118 15:43]: vio wrote: Could someone have a look at the following 'Boring' class with the security functionality added (as described in ZopeBook/6.Security and some other products). Could 'security' machinery be broken in Zope-2.4.1 ? It surely doesn't seem to work as adverised, on my machine at least (Debian Linux 2.2, Zope 2.4.1 (source release) python 2.1.0, linux2). Tell me if it works on your installation. Boring.py __doc__ = __version__ = '0.1' import Globals from Globals import HTMLFile # fakes a method from a DTML file from Globals import MessageDialog # provid from Globals import Persistent# makes an object stick in the ZODB import OFS.SimpleItem import Acquisition import AccessControl.Role from AccessControl import ClassSecurityInfo READ_PERM = 'View Stuff' WRITE_PERM = 'Change Stuff' security = ClassSecurityInfo() You have declared your ClassSecurityInfo object at the module level, rather than as an attribute of the class you wish to make security statements about. Please do not cross-post to both [EMAIL PROTECTED] and [EMAIL PROTECTED] Post to one or the other. -- Steve Alexander ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Security Gurus Wanted
* vio [EMAIL PROTECTED] [020119 09:56]: vio wrote: Just a word to thank you for your reply. But incidently, wouldn't it be a good idea for Globals.InitializeClass() to throw an error or a warning of some kind for hanging 'security.stuff()' declarations, declarations which do not have a related ClassSecurityInfo object AT THE CLASS LEVEL? That would be a fine idea. Unfortunately, there is no straightforward way telling that you called methods on the security object in the class definition. Why not simply check for the keyword 'security.' in the class source ? Anything beginning with that word most probably has something to do with security. But if 'security' is not a reference to a security object, just throw an exception. This would make everything so much simpler. When you call Globals.InitializeClass(your_class), it looks for a ClassSecurityInfo object, and doesn't find one. If I understood correctly, this should be treated like an error: not allow the programmer to have calls to security methods which aren't there, because that's more or less what's happening here. And definitely not be silent about it !!! That's a syntax error or something. So Globals.InitializeClass(your_class) finds the declaration 'security.declareSomething()' inside a class, but 'security' being a reference to a ClassSecurityInfo object AT THE MODULE LEVEL somehow has no effect at the class level (while I wrongly thought that by declaring it at the module level like that, it will behave more or less like a 'global' variable). I wonder what was carried at the class level, but something definitely was, else Python would have thrown something ugly at me. In my opinion, Globals.InitializeClass() should check such calls to security methods, and by all means NOT remain silent if it can not carry out the call because it couldn't find a ClassSecurityInfo object's method. Throw a 'method not found' error or something like that. Silence = 'bad'. I'll even say it's a bug. Vio ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Security Gurus Wanted
You are right, I struggled a lot to understand Zope's declarative security model. And I am still learning, so practice makes better. I didn't read Globals.InitializeClass() source, and I wrote my following comments out of the blue. Developping an error-correcting system might still be a little out of my league, for now. Anyway, the important thing is that your initial comments regarding Boring.py were right on target: 'security = ClassSecurityInfo()' must be declared INSIDE the class. It really solved my problem. Thanks again !!! Cheers, Vio * Steve Alexander [EMAIL PROTECTED] [020119 11:05]: vio wrote: deletia So Globals.InitializeClass(your_class) finds the declaration 'security.declareSomething()' inside a class, but 'security' being a reference to a ClassSecurityInfo object AT THE MODULE LEVEL somehow has no effect at the class level (while I wrongly thought that by declaring it at the module level like that, it will behave more or less like a 'global' variable). deletia In my opinion, Globals.InitializeClass() should check such calls to security methods You appear not to understand how Python and the declarative security system in Zope work. Globals.InitializeClass() does not read the source to your modules. You would need some sort of lint tool to perform the checking you describe. Why not try to implement a simple case of the error-correcting system that you describe? You might want to extend an existing lint tool such as PyChecker, to take account of conventions used in Zope products. http://pychecker.sourceforge.net/ -- Steve Alexander ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Re: [Zope-dev] Security Gurus Wanted
* Phillip J. Eby [EMAIL PROTECTED] [020119 12:04]: ... IMHO, you don't want to share a security object between more than one class, since presumably they will have different declarations and thus each require their own. So there's no reason to create a ClassSecurityInfo object at the module level, anyway. Good point. Actually, I only declared ClassSecurityInfo object at the module level out of convenience: I thought each class (presuming there were more than one in the module) could reference that same security object, so maybe save a few CPU cycles in the process (plus, I saw this done in some product I used as a learning example). But your point is well taken ... plus module-level security declarations have no effect at the class level. Vio ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
[Zope-dev] Security Gurus Wanted
Could someone have a look at the following 'Boring' class with the security functionality added (as described in ZopeBook/6.Security and some other products). Could 'security' machinery be broken in Zope-2.4.1 ? It surely doesn't seem to work as adverised, on my machine at least (Debian Linux 2.2, Zope 2.4.1 (source release) python 2.1.0, linux2). Tell me if it works on your installation. Boring.py __doc__ = __version__ = '0.1' import Globals from Globals import HTMLFile # fakes a method from a DTML file from Globals import MessageDialog # provid from Globals import Persistent# makes an object stick in the ZODB import OFS.SimpleItem import Acquisition import AccessControl.Role from AccessControl import ClassSecurityInfo READ_PERM = 'View Stuff' WRITE_PERM = 'Change Stuff' security = ClassSecurityInfo() manage_addBoringForm = HTMLFile('boringAdd', globals()) def manage_addBoring(self, id, title='', REQUEST=None): Add a Boring to a folder. self._setObject(id, Boring(id, title)) if REQUEST is not None: return self.manage_main(self, REQUEST) class Boring( OFS.SimpleItem.Item, # A simple Principia object. Not Folderish. Persistent,# Make us persistent. Yaah! Acquisition.Implicit, # Uh, whatever. AccessControl.Role.RoleManager # Security manager. ): Boring object. meta_type = 'Boring' # what do people think they're adding? manage_options = ( # what management options are there? {'label': 'Edit', 'action': 'manage_main'}, {'label': 'View', 'action': ''}, # defaults to index_html {'label': 'Security', 'action': 'manage_access'}, ) # NOTE: commented out following as it seem to conflict with # 'security.declareP...()' declarations later on #__ac_permissions__=( # what permissions make sense for us? # ('View management screens', ('manage_tabs','manage_main')), # ('Change permissions', ('manage_access',) ), # ('Change Borings' , ('manage_edit',) ), # ('View Borings',('',)), # ) def __init__(self, id, title=''): initialise a new instance of Boring self.id = id self.title = title # SECURITY - # here I played with '#'s, then simply tried to access 'index_html' # after each security declaration, # as user 'Anonymous', and noted the results on same line. # 'NOT-WORKING' simply means not working as advertised (allowed access when # it shouldn't, and vice-versa). As you can see, there are too many # 'NOT-WORKING' results. Do you come to similar results? # My conclusion is that security declarations have no effect whatsoever, # whether I declare something, then its oposite, I end up with the same # result. This shouldn't be. security.setPermissionDefault(READ_PERM, ['Stuff Manager','Manager']) security.setDefaultAccess('deny') # == NOT-WORKING # security.declarePrivate('index_html') # == NOT-WORKING # security.declarePublic('index_html')# == OK # security.declareProtected(READ_PERM, 'index_html') # == NOT-WORKING index_html = HTMLFile('index', globals()) security.declarePublic('manage_main') # == NOT-WORKING manage_main = HTMLFile('boringEdit', globals()) def manage_edit(self, title, REQUEST=None): self.title = title if REQUEST is not None: return MessageDialog( title = 'Edited', message = Properties for %s changed. % self.id, action = './manage_main', ) Globals.InitializeClass(Boring) ___ Zope-Dev maillist - [EMAIL PROTECTED] http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )