[Checkins] SVN: Sandbox/luciano/kirbi/src/kirbi/ interfaces and templates refactored

Luciano Ramalho luciano at ramalho.org
Tue Aug 14 23:58:21 EDT 2007


Log message for revision 78834:
  interfaces and templates refactored
  

Changed:
  U   Sandbox/luciano/kirbi/src/kirbi/app.py
  U   Sandbox/luciano/kirbi/src/kirbi/app_templates/master.pt
  U   Sandbox/luciano/kirbi/src/kirbi/book.py
  U   Sandbox/luciano/kirbi/src/kirbi/copy.py
  U   Sandbox/luciano/kirbi/src/kirbi/interfaces.py
  U   Sandbox/luciano/kirbi/src/kirbi/pac.py
  U   Sandbox/luciano/kirbi/src/kirbi/pac_templates/addbooks.pt
  D   Sandbox/luciano/kirbi/src/kirbi/pac_templates/incomplete.pt
  U   Sandbox/luciano/kirbi/src/kirbi/static/master.css
  U   Sandbox/luciano/kirbi/src/kirbi/user.py

-=-
Modified: Sandbox/luciano/kirbi/src/kirbi/app.py
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/app.py	2007-08-15 03:24:20 UTC (rev 78833)
+++ Sandbox/luciano/kirbi/src/kirbi/app.py	2007-08-15 03:58:21 UTC (rev 78834)
@@ -20,13 +20,6 @@
 
 class Index(grok.View):
 
-    def menu_items(self):
-        return [
-            {'url':self.url(self.context[USER_FOLDER_NAME],'join'),  'text':u'join'},
-            {'url':'''http://circulante.incubadora.fapesp.br/''',
-                'text':u'about'},
-        ]
-
     def pac_url(self):
         return self.url(self.context[PAC_NAME])
 
@@ -48,3 +41,4 @@
 class Master(grok.View):
     """The master page template macro."""
     grok.context(Interface)
+            

Modified: Sandbox/luciano/kirbi/src/kirbi/app_templates/master.pt
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/app_templates/master.pt	2007-08-15 03:24:20 UTC (rev 78833)
+++ Sandbox/luciano/kirbi/src/kirbi/app_templates/master.pt	2007-08-15 03:58:21 UTC (rev 78834)
@@ -25,10 +25,16 @@
         <img tal:attributes="src static/circulante-logo-transp-212x51.png"
         title="Circulante.org" width="212" height="51" />
     </a>
-    <ul>
-        <li tal:repeat="item view/menu_items"><a tal:attributes="href item/url"
-           tal:content="item/text">catalog</a></li>
+    <ul tal:condition="not:exists:view/request/principal/getLogin">
+        <li><a tal:attributes="href python:view.application_url('pac')">catalog</a></li>
+        <li><a tal:attributes="href python:view.application_url('u/join')">join</a></li>
     </ul>
+    <ul tal:condition="exists:view/request/principal/getLogin">
+        <li><a tal:attributes="href python:view.application_url('pac')">catalog</a></li>
+        <li><a tal:attributes="href python:view.application_url('u')">users</a></li>
+        <li><a tal:attributes="href python:view.application_url('pac/addbooks')">add books</a></li>
+        <li><a tal:attributes="href python:view.application_url('u/logout')">logout</a></li>
+    </ul>
   </div>
   <div metal:define-slot="body">
     <div class="content_menu">
@@ -38,6 +44,14 @@
             Content title
             </span>
         </span>
+        <span class="content_login">
+           <span tal:condition="exists:view/request/principal/getLogin">
+              login: <span tal:replace="view/request/principal/getLogin" />
+           </span>
+           <span tal:condition="not:exists:view/request/principal/getLogin">
+              (not logged in)
+           </span>
+        </span>
         <span metal:define-slot="content_actions" />
       </span>
     </div>

Modified: Sandbox/luciano/kirbi/src/kirbi/book.py
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/book.py	2007-08-15 03:24:20 UTC (rev 78833)
+++ Sandbox/luciano/kirbi/src/kirbi/book.py	2007-08-15 03:58:21 UTC (rev 78834)
@@ -268,11 +268,3 @@
         return self.static.get(cover_name,
                                self.static['covers/small-placeholder.jpg'])()
 
-    def menu_items(self):
-        return [
-            {'url':self.url(self.context.__parent__.__parent__[USER_FOLDER_NAME],'join'),
-                'text':u'join'},
-            {'url':'''http://circulante.incubadora.fapesp.br/''',
-                'text':u'about'},
-        ]
-

Modified: Sandbox/luciano/kirbi/src/kirbi/copy.py
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/copy.py	2007-08-15 03:24:20 UTC (rev 78833)
+++ Sandbox/luciano/kirbi/src/kirbi/copy.py	2007-08-15 03:58:21 UTC (rev 78834)
@@ -1,28 +1,16 @@
 import grok
+from interfaces import ICopy, ILease
 from zope.interface import Interface, implements, invariant
 from zope import schema
 
-class ICopy(Interface):
-    """An exemplar of a book."""
-    
-    book_id = schema.TextLine(title=u"Book id",
-                    description=u"The id of the book of which this is a copy.",
-                    required=True)
-    description = schema.Text(title=u"Description",
-                    description=(u"Details of this copy, such as autographs,"
-                                 u"marks, damage etc."),
-                            required=False)
-    #XXX: This should be filled automatically.
-    catalog_date = schema.Date(title=u"Catalog date",
-                    description=u"Date when added to your collection.",
-                            required=False)
-    
 class Copy(grok.Container):
     """An exemplar of a book.
     
-    A Copy is associated to a Book instance.
+    A copy is associated to a Book instance.
     
-    A Copy can contain Lease instances, recording each time it was lent.   
+    A copy can contain Lease instances, recording each time it was lent.
+    When a copy is transferred or deleted, the lease history automatically
+    goes with it.
     """
 
     implements(ICopy)
@@ -30,42 +18,3 @@
     def __init__(self, book_id):
         super(User, self).__init__()
         
-
-class ILease(Interface):
-    """A book lease."""
-    
-    copy_id = schema.TextLine(title=u"Copy id",
-                    description=u"The id of the copy being lent.",
-                    required=True)
-
-    # Note: the lender_id can usually be obtained from the copy, however if a
-    # copy is given to a new owner, the lease history would become incomplete.
-    lender_id = schema.Text(title=u"Lender",
-                            description=(u"Lender login."),
-                            required=True)
-
-    borrower_id = schema.Text(title=u"Borrower",
-                            description=(u"Borrower login."),
-                            required=True)
-
-    #XXX: This should be filled automatically.
-    request_date = schema.Date(title=u"Request date",
-                    description=u"When the lease was requested.",
-                    required=False)
-
-    delivery_date = schema.Date(title=u"Delivery date",
-                    description=u"When the copy was delivered to the borrower.",
-                    required=False)
-
-    due_date = schema.Date(title=u"Due date",
-                description=u"When the copy should be returned to the lender.",
-                required=False)
-                           
-    return_date = schema.Date(title=u"Returnd date",
-                    description=u"When the copy was returned to the lender.",
-                    required=False)
-
-    @invariant
-    def dueAfterDelivery(lease):
-        if not (lease.due_date > lease.delivery_date):
-            raise Invalid(u'The due date must be after the delivery date.')

Modified: Sandbox/luciano/kirbi/src/kirbi/interfaces.py
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/interfaces.py	2007-08-15 03:24:20 UTC (rev 78833)
+++ Sandbox/luciano/kirbi/src/kirbi/interfaces.py	2007-08-15 03:58:21 UTC (rev 78834)
@@ -64,5 +64,58 @@
         if (not book.title or not book.title.strip()) and (not book.isbn):
             raise Invalid('Either the title or the ISBN must be given.')
 
+class ICopy(Interface):
+    """An exemplar of a book."""
+    
+    book_id = schema.TextLine(title=u"Book id",
+                    description=u"The id of the book of which this is a copy.",
+                    required=True)
+    description = schema.Text(title=u"Description",
+                    description=(u"Details of this copy, such as autographs,"
+                                 u"marks, damage etc."),
+                            required=False)
+    #XXX: This should be filled automatically.
+    catalog_date = schema.Date(title=u"Catalog date",
+                    description=u"Date when added to your collection.",
+                            required=False)
+    
+class ILease(Interface):
+    """A book lease."""
+    
+    copy_id = schema.TextLine(title=u"Copy id",
+                    description=u"The id of the copy being lent.",
+                    required=True)
+
+    # Note: the lender_id can usually be obtained from the copy, however if a
+    # copy is given to a new owner, the lease history would become incomplete.
+    lender_id = schema.Text(title=u"Lender",
+                            description=(u"Lender login."),
+                            required=True)
+
+    borrower_id = schema.Text(title=u"Borrower",
+                            description=(u"Borrower login."),
+                            required=True)
+
+    #XXX: This should be filled automatically.
+    request_date = schema.Date(title=u"Request date",
+                    description=u"When the lease was requested.",
+                    required=False)
+
+    delivery_date = schema.Date(title=u"Delivery date",
+                    description=u"When the copy was delivered to the borrower.",
+                    required=False)
+
+    due_date = schema.Date(title=u"Due date",
+                description=u"When the copy should be returned to the lender.",
+                required=False)
+                           
+    return_date = schema.Date(title=u"Returnd date",
+                    description=u"When the copy was returned to the lender.",
+                    required=False)
+
+    @invariant
+    def dueAfterDelivery(lease):
+        if not (lease.due_date > lease.delivery_date):
+            raise Invalid(u'The due date must be after the delivery date.')
         
 

Modified: Sandbox/luciano/kirbi/src/kirbi/pac.py
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/pac.py	2007-08-15 03:24:20 UTC (rev 78833)
+++ Sandbox/luciano/kirbi/src/kirbi/pac.py	2007-08-15 03:58:21 UTC (rev 78834)
@@ -84,46 +84,10 @@
     if not book.title and book.isbn13:
         pac = book.__parent__
         pac.addIncomplete(book.isbn13)
-
-class Incomplete(grok.View):
-
-    def menu_items(self):
-        return [
-            {'url':self.url(self.context.__parent__[USER_FOLDER_NAME],'join'),
-                'text':u'join'},
-            {'url':'''http://circulante.incubadora.fapesp.br/''',
-                'text':u'about'},
-        ]
-
-    def sortedByTime(self, isbn_dict):
-        pairs = ((timestamp, isbn) for isbn, timestamp in
-                    isbn_dict.items())
-        return (dict(timestamp=timestamp,isbn=isbn)
-                for timestamp, isbn in sorted(pairs))
-            
-    def incompleteIsbns(self):
-        return list(self.sortedByTime(self.context.getIncomplete()))
-
-    def pendingIsbns(self):
-        return list(self.sortedByTime(self.context.getPending()))
-    
-    def update(self, isbns=None):
-        if isbns:
-            self.context.retryPending(isbns)
-        if self.context.getIncomplete() or self.context.getPending():
-            self.request.response.setHeader("Refresh", "5; url=%s" % self.url())
         
 class Index(grok.View):
     grok.context(Pac)
             
-    def menu_items(self):
-        return [
-            {'url':self.url(self.context.__parent__[USER_FOLDER_NAME],'join'),
-                'text':u'join'},
-            {'url':'''http://circulante.incubadora.fapesp.br/''',
-                'text':u'about'},
-        ]
-
     def coverUrl(self, book):
         cover_name = 'covers/large/'+book.isbn13+'.jpg'
         return self.static.get(cover_name,
@@ -193,18 +157,10 @@
     
     invalid_isbns = []
     
-    def menu_items(self):
-        return [
-            {'url':self.url(self.context.__parent__[USER_FOLDER_NAME],'join'),
-                'text':u'join'},
-            {'url':'''http://circulante.incubadora.fapesp.br/''',
-                'text':u'about'},
-        ]
-
-    def update(self, isbns=None):
+    def update(self, isbns=None, retry_isbns=None):
+        self.invalid_isbns = []
         if isbns is not None:
             isbns = list(set(isbns.split()))
-            self.invalid_isbns = []
             for isbn in isbns:
                 if isValidISBN(isbn):
                     book = Book(isbn=isbn)
@@ -212,6 +168,13 @@
                         self.context.addBook(book)
                 else:
                     self.invalid_isbns.append(isbn)
+        if retry_isbns:
+            self.context.retryPending(retry_isbns)
+        # XXX this would be great with AJAX, avoiding the ugly refresh
+        if (not self.invalid_isbns) and (self.context.getIncomplete()
+                                         or self.context.getPending()):
+            self.request.response.setHeader("Refresh", "5; url=%s" % self.url())
+
                     
     def invalidISBNs(self):
         if self.invalid_isbns:
@@ -219,6 +182,18 @@
         else:
             return ''
 
+    def sortedByTime(self, isbn_dict):
+        pairs = ((timestamp, isbn) for isbn, timestamp in
+                    isbn_dict.items())
+        return (dict(timestamp=timestamp,isbn=isbn)
+                for timestamp, isbn in sorted(pairs))
+            
+    def incompleteIsbns(self):
+        return list(self.sortedByTime(self.context.getIncomplete()))
+
+    def pendingIsbns(self):
+        return list(self.sortedByTime(self.context.getPending()))
+    
 class NameChooser(grok.Adapter, BaseNameChooser):
     implements(INameChooser)
 

Modified: Sandbox/luciano/kirbi/src/kirbi/pac_templates/addbooks.pt
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/pac_templates/addbooks.pt	2007-08-15 03:24:20 UTC (rev 78833)
+++ Sandbox/luciano/kirbi/src/kirbi/pac_templates/addbooks.pt	2007-08-15 03:58:21 UTC (rev 78834)
@@ -14,11 +14,12 @@
     </form>
   </span>
   <div metal:fill-slot="content">
-
+  <table><tr>
+    <td valign="top">
     <form tal:attributes="action view/url" method="post">
         <p>Type or scan several ISBNs separated by spaces or newlines.</p>
         <p>Either 10 or 13-digit ISBNs can be used.</p>
-        <textarea name="isbns" rows="30" cols="40"
+        <textarea name="isbns" rows="20" cols="40"
             tal:content="view/invalidISBNs">
         </textarea>
         <br /> 
@@ -37,6 +38,100 @@
     </form>
     </p>
 
-  </div>
+    </td><td valign="top">
+
+    <div tal:condition="view/incompleteIsbns">
+        <h3>New Book Records Without Title</h3>
+        <table class="isbn_list">
+            <tr tal:repeat="item view/incompleteIsbns">
+                <th align="right" tal:content="repeat/item/number" />
+                <td tal:content="item/timestamp" />
+                <td>
+                    <a tal:attributes="href python:view.url(item['isbn'])+'/details'"
+                            tal:content="item/isbn">9780123456789</a>
+    
+                </td>
+            </tr>
+        </table>
+    </div>
+        
+    <form tal:condition="view/pendingIsbns" method="post"
+        tal:attributes="action view/url">
+        <h3>Pending Book Searches</h3>
+        <table class="isbn_list">
+            <tr>
+                <th></th>
+                <th>#</th>
+                <th>Created</th>
+                <th>ISBN-13</th>
+                <th>
+                    <a tal:attributes="href string:http://www.worldcatlibraries.org/"
+                        title="WorldCat Libraries Search">
+                        <img tal:attributes="src static/worldcat24.gif" />
+                    </a>
+                </th>
+                <th>
+                    <a tal:attributes="href string:http://www.alibris.com/search/search.cfm"
+                        title="Alibris Book Search">
+                        <img tal:attributes="src static/alibris24.gif" />
+                    </a>
+                </th>
+                <th>
+                    <a tal:attributes="href string:http://books.google.com/"
+                        title="Google Book Search">
+                        <img tal:attributes="src static/googlebook24.gif" />
+                    </a>
+                </th>
+                <th>
+                    <a tal:attributes="href string:http://google.com/"
+                        title="Google Search">
+                        <img tal:attributes="src static/google24.gif" />
+                    </a>
+                </th>
+            </tr>
+            <tr tal:repeat="item view/pendingIsbns">
+                <td>
+                    <input type="checkbox" name="retry_isbns:list"
+                            tal:attributes="value item/isbn" />
+    
+                </td>
+                <th align="right" tal:content="repeat/item/number" />
+                <td tal:content="item/timestamp" />
+                <td>
+                    <a tal:attributes="href python:view.url(item['isbn'])+'/details'"
+                            tal:content="item/isbn">9780123456789</a>
+    
+                </td>
+                <td>
+                    <a tal:attributes="href string:http://www.worldcatlibraries.org/search?q=${item/isbn}"
+                        title="WorldCat Libraries Search">
+                        <img tal:attributes="src static/worldcat16.gif" />
+                    </a>
+                </td>
+                <td>
+                    <a tal:attributes="href string:http://www.alibris.com/search/search.cfm?wtit=${item/isbn}"
+                        title="Alibris Book Search">
+                        <img tal:attributes="src static/alibris16.gif" />
+                    </a>
+                </td>
+                <td>
+                    <a tal:attributes="href string:http://books.google.com/books?q=${item/isbn}"
+                        title="Google Book Search">
+                        <img tal:attributes="src static/google16.gif" />
+                    </a>
+                </td>
+                <td>
+                    <a tal:attributes="href string:http://google.com/search?q=${item/isbn}"
+                        title="Google Search">
+                        <img tal:attributes="src static/google16.gif" />
+                    </a>
+
+                </td>
+            </tr>
+        </table>
+        <input type="submit" name="retry" value="Retry">
+    </form>
+
+  </div><!--/content-->
 </body>
 </html>

Deleted: Sandbox/luciano/kirbi/src/kirbi/pac_templates/incomplete.pt
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/pac_templates/incomplete.pt	2007-08-15 03:24:20 UTC (rev 78833)
+++ Sandbox/luciano/kirbi/src/kirbi/pac_templates/incomplete.pt	2007-08-15 03:58:21 UTC (rev 78834)
@@ -1,118 +0,0 @@
-<html metal:use-macro="context/@@master/page">
-<head>
-    <title metal:fill-slot="title">
-        Public Catalog
-    </title>
-
-</head>
-<body>
-  <span metal:fill-slot="content_title">Collective catalog</span>
-  <span metal:fill-slot="content_actions">
-    <form class="search" action=".">
-        <input type="text" name="query">
-        <input type="submit" name="submit" value="search">
-    </form>
-  </span>
-  <div metal:fill-slot="content">
-
-    <div tal:condition="view/incompleteIsbns">
-        <h3>New Book Records Without Title</h3>
-        <table class="isbn_list">
-            <tr tal:repeat="item view/incompleteIsbns">
-                <th align="right" tal:content="repeat/item/number" />
-                <td tal:content="item/timestamp" />
-                <td>
-                    <a tal:attributes="href python:view.url(item['isbn'])+'/details'"
-                            tal:content="item/isbn">9780123456789</a>
-    
-                </td>
-            </tr>
-        </table>
-    </div>
-    <p tal:condition="not:view/incompleteIsbns">No new book records without title.</p>
-        
-    <form tal:condition="view/pendingIsbns" method="post"
-        tal:attributes="action view/url">
-        <h3>Pending Book Searches</h3>
-        <table class="isbn_list">
-            <tr>
-                <th><input type="checkbox" name="select_all"></th>
-                <th>#</th>
-                <th>Created</th>
-                <th>ISBN-13</th>
-                <th>
-                    <a tal:attributes="href string:http://www.worldcatlibraries.org/"
-                        title="WorldCat Libraries Search">
-                        <img tal:attributes="src static/worldcat24.gif" />
-                    </a>
-                </th>
-                <th>
-                    <a tal:attributes="href string:http://www.alibris.com/search/search.cfm"
-                        title="Alibris Book Search">
-                        <img tal:attributes="src static/alibris24.gif" />
-                    </a>
-                </th>
-                <th>
-                    <a tal:attributes="href string:http://books.google.com/"
-                        title="Google Book Search">
-                        <img tal:attributes="src static/googlebook24.gif" />
-                    </a>
-                </th>
-                <th>
-                    <a tal:attributes="href string:http://google.com/"
-                        title="Google Search">
-                        <img tal:attributes="src static/google24.gif" />
-                    </a>
-                </th>
-            </tr>
-            <tr tal:repeat="item view/pendingIsbns">
-                <td>
-                    <input type="checkbox" name="isbns:list"
-                            tal:attributes="value item/isbn" />
-    
-                </td>
-                <th align="right" tal:content="repeat/item/number" />
-                <td tal:content="item/timestamp" />
-                <td>
-                    <a tal:attributes="href python:view.url(item['isbn'])+'/details'"
-                            tal:content="item/isbn">9780123456789</a>
-    
-                </td>
-                <td>
-                    <a tal:attributes="href string:http://www.worldcatlibraries.org/search?q=${item/isbn}"
-                        title="WorldCat Libraries Search">
-                        <img tal:attributes="src static/worldcat16.gif" />
-                    </a>
-                </td>
-                <td>
-                    <a tal:attributes="href string:http://www.alibris.com/search/search.cfm?wtit=${item/isbn}"
-                        title="Alibris Book Search">
-                        <img tal:attributes="src static/alibris16.gif" />
-                    </a>
-                </td>
-                <td>
-                    <a tal:attributes="href string:http://books.google.com/books?q=${item/isbn}"
-                        title="Google Book Search">
-                        <img tal:attributes="src static/google16.gif" />
-                    </a>
-                </td>
-                <td>
-                    <a tal:attributes="href string:http://google.com/search?q=${item/isbn}"
-                        title="Google Search">
-                        <img tal:attributes="src static/google16.gif" />
-                    </a>
-
-                </td>
-            </tr>
-        </table>
-        <input type="submit" name="retry" value="Retry">
-    </form>
-    <p tal:condition="not:view/pendingIsbns">No pending book searches.</p>
-
-    <p><a tal:attributes="href python:view.url('addbook')">
-            Add Book
-    </a></p>
-
-  </div>
-</body>
-</html>

Modified: Sandbox/luciano/kirbi/src/kirbi/static/master.css
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/static/master.css	2007-08-15 03:24:20 UTC (rev 78833)
+++ Sandbox/luciano/kirbi/src/kirbi/static/master.css	2007-08-15 03:58:21 UTC (rev 78834)
@@ -68,6 +68,12 @@
     margin-top: 1px;
 }
 
+span.content_login {
+    position: relative;
+    left: 33%;
+    font-family: sans-serif;
+}
+
 div.content {
     margin: 20px;
 }

Modified: Sandbox/luciano/kirbi/src/kirbi/user.py
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/user.py	2007-08-15 03:24:20 UTC (rev 78833)
+++ Sandbox/luciano/kirbi/src/kirbi/user.py	2007-08-15 03:58:21 UTC (rev 78834)
@@ -1,6 +1,7 @@
 import grok
 from interfaces import IUser
 from zope.app.authentication.interfaces import IPrincipalInfo
+from zope.app.authentication.interfaces import IAuthenticatorPlugin
 from zope.interface import Interface, implements, invariant, Invalid
 from zope import schema
 import sha
@@ -46,16 +47,7 @@
         
 class Index(grok.View):
     grok.context(User)
-    
-    def menu_items(self):
-        return [
-            {'url':self.url(self.context.__parent__,'join'),
-                'text':u'join'},
-            {'url':'''http://circulante.incubadora.fapesp.br/''',
-                'text':u'about'},
-        ]
 
-
 class PrincipalInfoAdapter(grok.Adapter):
     grok.context(User)
     grok.implements(IPrincipalInfo)
@@ -87,14 +79,6 @@
     grok.context(UserFolder)
     grok.name('index')
 
-    def menu_items(self):
-        return [
-            {'url':self.url('join'),
-                'text':u'join'},
-            {'url':'''http://circulante.incubadora.fapesp.br/''',
-                'text':u'about'},
-        ]
-
     def update(self, query=None):
         self.results_title = '%d users' % len(self.context)
 
@@ -103,6 +87,11 @@
     def render(self):
         return 'This should log you in...'
     
+class Logout(grok.View):
+    grok.context(UserFolder)
+    def render(self):
+        return "This should log you out (but doesn't yet)."
+
 class Join(grok.AddForm):
     grok.context(UserFolder)
     """User registration form"""
@@ -114,4 +103,31 @@
         login = data['login']
         self.context[login] = User(**data)
         self.redirect(self.url(login))
+        
+        
+class UserAuthenticationPlugin(object):
+    """Simple authentication and search plugin"""
+    implements(IAuthenticatorPlugin)
 
+    principals = (
+        {'id':'alice', 'login':'alice', 'password':'123'},
+        {'id':'bob', 'login':'bob', 'password':'123'}
+        )
+
+    prefix = "users" # principal id prefix
+    
+    def principalInfo(self, id):
+        """Find a principal given an id"""
+        for principal in self.principals:
+            if self.prefix + "." + principal['id'] == id:
+                return {'login' : principal['login']}
+
+    def authenticateCredentials(self, credentials):
+        """Authenticate a principal"""
+        for principal in self.principals:
+            if credentials['login']==principal['login'] and \
+               credentials['password']==principal['password']:
+                return (self.prefix + "." + principal['id'],
+                         {'login' : principal['login']})
+
+



More information about the Checkins mailing list