How to use "lower" attribute (or function) to catch duplicate User IDs?
I am new to Zope (less than a week) and I'm in the process of writing a small portal where users can sign themselves up. Right now it is working, but I have a few known problems - one of which is that my routine that checks for duplicate User IDs is case-sensitive (i.e. it would allow "bob","Bob" and "BOB" all to register). I also realize that what I have right now is kluged together - I'm sure there is a more efficient (and more elegant) way of doing what I've done. Here's the basic outline of what I have done so far. It is very skeletal right now, as I'm figuring out how to use Zope. Public Access page: -> Contains link to sign up -> Contains link to members only side Private Page: -> contains link to make entry in member database -> contains link to list members Logic Flow: NewLAGUserForm - captures first attempt to create User ID & calls VerifyLAGUserForm VerifyLAGUserForm - checks data, if all OK, calls AddLAGUser, otherwise redisplays entry form (with appropriate error messages) and submits input to VerifyLAGUserForm again AddLAGUser - makes entry into acl_users with appropriate role, makes entry into SQL database with user information, emails "thank you" message to user with User ID & password info SECURITY QUESTION: - In order for this to work I had to set the security for on acl_users (for this folder) to "Manage users" for "Anonymous". Does this open up any way for someone to gain access directly to the acl_users folder? I've tried to and it seems like it is still safe - I have the 'Member' role hardcoded into the add user script. Code Examples Rather than post lengthy codes segments to the list, I put all of the code examples online as text files via the following link: http://examples.subbob.net (non-zope) The working implementation of the above files may be found at: http://www.subbob.net:8081/wargames Feel free to try it out as I'm only in testing right now and will be purging the database when testing is complete. Outstanding Questions: 1) How to track a "state" within a given DTML Document or Method? The Verify form is very cumbersome as I go through each "test" twice. The first set of nested ifs are used to determine the overall validity of the submission - if it gets to the "center" of the nest, the data is submitted. If any errors exist, then I retest each parameter prior to redisplaying the form in order to flag the associated input box with an error message. I had to do that way because I couldn't figure out a way to accomplish it like this in DTML: If email-good then email-error=0 else email-error=1 Then check, if all error values=0, submit the form, otherwise display the errors. I'll appreciate any feedback on what I've done so far - I've probably violated most accepted practices of "good" zope coding! :)
At 07:58 PM 2/26/2003, Bob King wrote:
I am new to Zope (less than a week) and I'm in the process of writing a small portal where users can sign themselves up.
Welcome.
Right now it is working, but I have a few known problems - one of which is that my routine that checks for duplicate User IDs is case-sensitive (i.e. it would allow "bob","Bob" and "BOB" all to register).
That's the default behavior. If you want to make sure that doesn't happen, you could do one of two things: 1. Force all user names to upper or lower case when you register them 2. Do a check for case-insensitive matches by single-casing your input and testing it against a single-case version of each existing user. The first solution is easy: <dtml-call "manage_addUser(username.lower(), password, roles)"> The second a bit more cumbersome: --------------- <dtml-call "REQUEST.set('matches', [])"> <dtml-in objectIds prefix=object> <dtml-if "object_item.lower() == username.lower()"> <dtml-call "matches.append(1)"> </dtml-if> </dtml-in> <dtml-if matches> Sorry, can't do that... we've got a name like <dtml-var username> already. <dtml-else> <dtml-call "manage_addUser(username, password, roles)"> </dtml-if> ---------------
SECURITY QUESTION: - In order for this to work I had to set the security for on acl_users (for this folder) to "Manage users" for "Anonymous".
On first glance, that strikes me as a bad idea.
Does this open up any way for someone to gain access directly to the acl_users folder?
Probably, though I don't have an exploit to offer you. In general, it's a good idea to keep permissions as low as possible. A better way to do this, generally, is to write a method that performs *just* this privileged operation and give that method a proxy role that is sufficient to perform the operation. You can then call that method in the context of a regular user's privileges and they will still be able to do whatever it is that method does. Proxy roles are well worth looking into carefully, as they are a potential source of insecurity if written uncautiously.
1) How to track a "state" within a given DTML Document or Method? The Verify form is very cumbersome as I go through each "test" twice.
Within a method, the easiest way is to set a value in the REQUEST object, eg: <dtml-call "REQUEST.set('some_var', some_python_expression)"> Between methods, there are ways of passing values: <dtml-var "some_other_method(arg1=value1, arg2=value2)"> and placing variables into the namespace: <dtml-let spam="'pork shoulder and ham'"> <dtml-var some_method> </dtml-let> Note the use of double and single quotes above... the outer double quotes denote this as a Python expression, the inner single quotes convey that the expression consists of a string value. Tracking state between hits can be done in a number of ways, but I would recommend a bit more reading first.
If any errors exist, then I retest each parameter prior to redisplaying the form in order to flag the associated input box with an error message. I had to do that way because I couldn't figure out a way to accomplish it like this in DTML:
If email-good then email-error=0 else email-error=1
In DTML, it's: <dtml-if email_good> <dtml-call "REQUEST.set('email_error', 0)"> <dtml-else> <dtml-call "REQUEST.set('email_error', 1)"> </dtml-if> I would strongly advise you to get in the habit of using underscores instead of dashes in your variable names (as shown above). When the variable email-error is evaluated as part of a Python expression, it will translate as "email minus error". There are ways around this, of course, but the easiest thing to do as a beginner is to cultivate good naming habits.
Then check, if all error values=0, submit the form, otherwise display the errors.
If you're performing a lot of these tests, I'd advise running them in sequence instead of nesting them. It's heck of a lot easier to keep track of it all and you're going to want to tell the user *all* the ways they screwed up, not just the first one. :-) Here's a quick sketch with a few different types of tests: ---------------- <!-- use a list object to collect errors --> <dtml-call "REQUEST.set('errors', [])"> <dtml-unless expected_field_1> <dtml-call "errors.append('You need to enter a value for Expected Field 1')"> </dtml-if> <dtml-if "_.len(expected_field_2) < 3"> <dtml-call "errors.append('Expected Field 2 must contain at least three letters or digits')"> </dtml-if> <dtml-if "expected_field_3 in ['yo mamma', 'up yours', 'lamer']"> <dtml-call "errors.append('You need to provide a value for Expected Field 3 that is less insulting')"> </dtml-if> <!-- more tests go here --> <dtml-if errors> You had errors:<UL> <dtml-in errors prefix=error> <LI><dtml-var error_item></LI> </dtml-in> </UL> <dtml-else> <!-- call your form processing routine: --> <dtml-call "some_thing(REQUEST.form)"> </dtml-if> ---------------- From here, I'd recommend some reading... Dig in to The Zope Book and be aware that there are two versions available: http://www.zope.org/Documentation/Books/ZopeBook/ I'd also highly recommend Dieter Maurer's book in progress: http://www.dieter.handshake.de/pyprojects/zope/book/book.html After that, feel free to let us know if you have more questions. Dylan
participants (2)
-
Bob King -
Dylan Reinhardt