[Checkins] SVN: Sandbox/luciano/kirbi/src/kirbi/ working on user
management
Luciano Ramalho
luciano at ramalho.org
Mon Aug 13 22:39:07 EDT 2007
Log message for revision 78807:
working on user management
Changed:
U Sandbox/luciano/kirbi/src/kirbi/app_templates/master.pt
U Sandbox/luciano/kirbi/src/kirbi/ftests/test_functional.py
A Sandbox/luciano/kirbi/src/kirbi/ftests/user.txt
U Sandbox/luciano/kirbi/src/kirbi/ftests/xmlrpc.txt
U Sandbox/luciano/kirbi/src/kirbi/user.py
U Sandbox/luciano/kirbi/src/kirbi/user_templates/index.pt
-=-
Modified: Sandbox/luciano/kirbi/src/kirbi/app_templates/master.pt
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/app_templates/master.pt 2007-08-13 23:54:27 UTC (rev 78806)
+++ Sandbox/luciano/kirbi/src/kirbi/app_templates/master.pt 2007-08-14 02:39:07 UTC (rev 78807)
@@ -28,7 +28,7 @@
<ul>
<li><a tal:attributes="href python:view.application_url('pac')">catalog</a></li>
<li><a tal:attributes="href python:view.application_url()">collection</a></li>
- <li><a tal:attributes="href python:view.application_url('users')">users</a></li>
+ <li><a tal:attributes="href python:view.application_url('u')">users</a></li>
<li><a tal:attributes="href python:view.application_url()">leases</a></li>
<li><a tal:attributes="href python:view.application_url('pac')+'/incomplete'">incomplete</a></li>
</ul>
Modified: Sandbox/luciano/kirbi/src/kirbi/ftests/test_functional.py
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/ftests/test_functional.py 2007-08-13 23:54:27 UTC (rev 78806)
+++ Sandbox/luciano/kirbi/src/kirbi/ftests/test_functional.py 2007-08-14 02:39:07 UTC (rev 78807)
@@ -20,7 +20,7 @@
def test_suite():
suite = unittest.TestSuite()
- docfiles = ['xmlrpc.txt']
+ docfiles = ['xmlrpc.txt', 'user.txt']
for docfile in docfiles:
test = FunctionalDocFileSuite(
Added: Sandbox/luciano/kirbi/src/kirbi/ftests/user.txt
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/ftests/user.txt (rev 0)
+++ Sandbox/luciano/kirbi/src/kirbi/ftests/user.txt 2007-08-14 02:39:07 UTC (rev 78807)
@@ -0,0 +1,24 @@
+==========================
+Testing user funcionality
+==========================
+
+Users can be adapted to IPrincipalInfo::
+
+ >>> from kirbi.user import IUser, User
+ >>> from zope.app.authentication.interfaces import IPrincipalInfo
+ >>> alice = User('alice', u'Vincent Damon Furnier', u'headless-chicken')
+ >>> IUser.providedBy(alice)
+ True
+ >>> IPrincipalInfo.providedBy(alice)
+ False
+ >>> principal = IPrincipalInfo(alice)
+ >>> IPrincipalInfo.providedBy(principal)
+ True
+ >>> principal.description
+ u'Vincent Damon Furnier (alice)'
+ >>> principal.title = u'Alice Cooper'
+ >>> alice.name
+ u'Alice Cooper'
+
+
+
Modified: Sandbox/luciano/kirbi/src/kirbi/ftests/xmlrpc.txt
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/ftests/xmlrpc.txt 2007-08-13 23:54:27 UTC (rev 78806)
+++ Sandbox/luciano/kirbi/src/kirbi/ftests/xmlrpc.txt 2007-08-14 02:39:07 UTC (rev 78807)
@@ -5,50 +5,50 @@
First we setup the app and XML-RPC proxy to the PAC (the public access
book catalog)::
- >>> from grok.ftests.xmlrpc_helper import ServerProxy
- >>> from kirbi.app import Kirbi
- >>> root = getRootFolder()
- >>> root['kirbi'] = Kirbi()
- >>> pac = ServerProxy("http://localhost/kirbi/pac")
+ >>> from grok.ftests.xmlrpc_helper import ServerProxy
+ >>> from kirbi.app import Kirbi
+ >>> root = getRootFolder()
+ >>> root['kirbi'] = Kirbi()
+ >>> pac = ServerProxy("http://localhost/kirbi/pac")
Now we use the proxy to add books to the PAC::
- >>> pac.add(dict(title="One Flew Over the Cuckoo's Nest"))
- 'k0001'
- >>> pac.add(dict(isbn13='9780684833392'))
- '9780684833392'
- >>> pac.add(dict(isbn13='9780486273471'))
- '9780486273471'
- >>> pac.add(dict(title=u'Utopia', isbn13='9780140449105'))
- '9780140449105'
- >>> sorted(pac.list())
- ['9780140449105', '9780486273471', '9780684833392', 'k0001']
+ >>> pac.add(dict(title="One Flew Over the Cuckoo's Nest"))
+ 'k0001'
+ >>> pac.add(dict(isbn13='9780684833392'))
+ '9780684833392'
+ >>> pac.add(dict(isbn13='9780486273471'))
+ '9780486273471'
+ >>> pac.add(dict(title=u'Utopia', isbn13='9780140449105'))
+ '9780140449105'
+ >>> sorted(pac.list())
+ ['9780140449105', '9780486273471', '9780684833392', 'k0001']
The second and third books added have ISBN but no title, so they are added to
the incomplete attribute of the PAC, to be retrieved by Kirbifetch::
- >>> sorted(pac.dumpIncomplete())
- ['9780486273471', '9780684833392']
+ >>> sorted(pac.dumpIncomplete())
+ ['9780486273471', '9780684833392']
Once retrieved, they are moved from the incomplete to the pending attribute
of the PAC::
- >>> pac.dumpIncomplete()
- []
+ >>> pac.dumpIncomplete()
+ []
When the metadata is found at an external source, the book record can be
updated (the number of books updated is returned)::
- >>> metadata = [dict(isbn13='9780684833392',title=u'Catch-22',creators=[u'Joseph Heller'])]
- >>> pac.updateBooks(metadata)
- 1
+ >>> metadata = [dict(isbn13='9780684833392',title=u'Catch-22',creators=[u'Joseph Heller'])]
+ >>> pac.updateBooks(metadata)
+ 1
But only pending books may be updated by this API::
- >>> metadata = [dict(title=u'Utopia', isbn13='9780140449105')]
- >>> pac.updateBooks(metadata)
- Traceback (most recent call last):
- ...
- Fault: <Fault -1: 'Unexpected Zope exception: LookupError: 9780140449105
- not in pending ISBNs; update not allowed.'>
+ >>> metadata = [dict(title=u'Utopia', isbn13='9780140449105')]
+ >>> pac.updateBooks(metadata)
+ Traceback (most recent call last):
+ ...
+ Fault: <Fault -1: 'Unexpected Zope exception: LookupError: 9780140449105
+ not in pending ISBNs; update not allowed.'>
Modified: Sandbox/luciano/kirbi/src/kirbi/user.py
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/user.py 2007-08-13 23:54:27 UTC (rev 78806)
+++ Sandbox/luciano/kirbi/src/kirbi/user.py 2007-08-14 02:39:07 UTC (rev 78807)
@@ -1,65 +1,85 @@
import grok
from zope.app.authentication.interfaces import IPrincipalInfo
-from zope.interface import implements, invariant, Invalid
+from zope.interface import Interface, implements, invariant, Invalid
+from zope import schema
import sha
class UserFolder(grok.Container):
pass
-class User(object):
- """
- A Kirbi user. To implement IPrincipalInfo but still use more familiar
- attribute names, we use properties to make ``id`` the same as ``login``
- and ``title`` the same as ``name``.
- >>> alice = User('alice', u'Vincent Damon Furnier', u'headless-chicken')
- >>> alice.id, alice.title, alice.description
- ("alice", u"Vincent Damon Furnier", u"Vincent Damon Furnier (alice)")
+class IUser(Interface):
+ login = schema.TextLine(title=u"Login",
+ required=True)
+ name = schema.TextLine(title=u"Name",
+ required=False)
+ password = schema.Password(title=u"Password",
+ required=True)
- >>> alice.title = u'Alice Cooper'
- >>> alice.name
- u"Alice Cooper"
+class User(grok.Container):
+ """
+ A Kirbi user. A User will contain Copy instances, representing book copies
+ owned by the user.
- >>> alice.passwd_hash
- ABC
+ >>> alice = User('alice', u'Alice Cooper', u'headless-chicken')
+ >>> IUser.providedBy(alice)
+ True
+ >>> alice.passwordHash()
+ 'f030ff587c602e0e9a68aba75f41c51a0dc22c62'
+ >>> alice.name_and_login()
+ u'Alice Cooper (alice)'
"""
- implements(IPrincipalInfo)
+ implements(IUser)
- login = ''
- name = ''
- passwd_hash = ''
+ login = u''
+ name = u''
+ password = u''
- def __init__(self, login, name, passwd):
+ def __init__(self, login, name, password):
+ super(User, self).__init__()
self.login = login
self.name = name
- self.passwd = sha.new(passwd).hexdigest()
+ self.password = password
+ def passwordHash(self):
+ return sha.new(self.password).hexdigest()
+
+ def name_and_login(self):
+ if self.name:
+ return '%s (%s)' % (self.name, self.login)
+ else:
+ return self.login
+
+
+class PrincipalInfoAdapter(grok.Adapter):
+ grok.context(User)
+ grok.implements(IPrincipalInfo)
+
+ def __init__(self, context):
+ self.context = context
+
def getId(self):
- return self.login
+ return self.context.login
def setId(self, id):
- self.login = id
+ self.context.login = id
id = property(getId, setId)
def getTitle(self):
- return self.name
+ return self.context.name
def setTitle(self, title):
- self.name = title
+ self.context.name = title
- id = property(getId, setId)
+ title = property(getTitle, setTitle)
@property
def description(self):
- return '%s (%s)' % (self.name, self.login)
+ return self.context.name_and_login()
-
-
-
-
class Index(grok.View):
grok.context(UserFolder)
def update(self, query=None):
@@ -70,10 +90,10 @@
grok.context(UserFolder)
""" User registration form """
- form_fields = grok.AutoFields(IPrincipalInfo)
+ form_fields = grok.AutoFields(IUser)
@grok.action('Add entry')
def add(self, **data):
- self.context[id] = User(**data)
- self.redirect(self.url('users'))
+ self.context[data['login']] = User(**data)
+ self.redirect(self.url('u'))
Modified: Sandbox/luciano/kirbi/src/kirbi/user_templates/index.pt
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/user_templates/index.pt 2007-08-13 23:54:27 UTC (rev 78806)
+++ Sandbox/luciano/kirbi/src/kirbi/user_templates/index.pt 2007-08-14 02:39:07 UTC (rev 78807)
@@ -17,9 +17,9 @@
<h3 tal:content="view/results_title">999 items matched the query</h3>
<table>
- <tr tal:repeat="item view/context/keys">
+ <tr tal:repeat="item view/context/values">
<th align="right" tal:content="repeat/item/number" />
- <td tal:content="item/id" />
+ <td tal:content="item/name_and_login" />
</tr>
</table>
More information about the Checkins
mailing list