[Checkins] SVN: grokapps/LoginDemo/ initial import of LoginDemo

Luciano Ramalho luciano at ramalho.org
Fri Dec 28 10:49:04 EST 2007


Log message for revision 82500:
  initial import of LoginDemo
  

Changed:
  A   grokapps/LoginDemo/
  A   grokapps/LoginDemo/buildout.cfg
  A   grokapps/LoginDemo/setup.py
  A   grokapps/LoginDemo/src/
  A   grokapps/LoginDemo/src/logindemo/
  A   grokapps/LoginDemo/src/logindemo/__init__.py
  A   grokapps/LoginDemo/src/logindemo/app.py
  A   grokapps/LoginDemo/src/logindemo/app_templates/
  A   grokapps/LoginDemo/src/logindemo/app_templates/index.pt
  A   grokapps/LoginDemo/src/logindemo/app_templates/login.pt
  A   grokapps/LoginDemo/src/logindemo/configure.zcml
  A   grokapps/LoginDemo/src/logindemo/ftesting.zcml
  A   grokapps/LoginDemo/src/logindemo/ftests/
  A   grokapps/LoginDemo/src/logindemo/ftests/__init__.py
  A   grokapps/LoginDemo/src/logindemo/ftests/index.txt
  A   grokapps/LoginDemo/src/logindemo/ftests/test_functional.py
  A   grokapps/LoginDemo/src/logindemo/interfaces.py
  A   grokapps/LoginDemo/src/logindemo/login.txt
  A   grokapps/LoginDemo/src/logindemo/testing.py

-=-
Added: grokapps/LoginDemo/buildout.cfg
===================================================================
--- grokapps/LoginDemo/buildout.cfg	                        (rev 0)
+++ grokapps/LoginDemo/buildout.cfg	2007-12-28 15:49:03 UTC (rev 82500)
@@ -0,0 +1,68 @@
+[buildout]
+develop = .
+parts = app data zopectl i18n test
+find-links = http://download.zope.org/distribution/
+newest = false
+extends= http://grok.zope.org/releaseinfo/grok-0.11.cfg
+versions = versions
+
+[data]
+recipe = zc.recipe.filestorage
+
+[app]
+recipe = zc.zope3recipes>=0.5.3:application
+eggs = LoginDemo
+site.zcml = <include package="logindemo" />
+            <include package="zope.app.twisted" />
+
+            <configure i18n_domain="logindemo">
+              <unauthenticatedPrincipal id="zope.anybody"
+                                        title="Unauthenticated User" />
+              <unauthenticatedGroup id="zope.Anybody"
+                                    title="Unauthenticated Users" />
+              <authenticatedGroup id="zope.Authenticated"
+                                title="Authenticated Users" />
+              <everybodyGroup id="zope.Everybody"
+                              title="All Users" />
+              <principal id="zope.manager"
+                         title="Manager"
+                         login="grok"
+                         password_manager="Plain Text"
+                         password="grok"
+                         />
+
+              <!-- Replace the following directive if you don't want
+                   public access -->
+              <grant permission="zope.View"
+                     principal="zope.Anybody" />
+              <grant permission="zope.app.dublincore.view"
+                     principal="zope.Anybody" />
+
+              <role id="zope.Manager" title="Site Manager" />
+              <role id="zope.Member" title="Site Member" />
+              <grantAll role="zope.Manager" />
+              <grant role="zope.Manager"
+                     principal="zope.manager" />
+           </configure>
+
+[data]
+recipe = zc.recipe.filestorage
+
+# this section named so that the start/stop script is called bin/zopectl
+[zopectl]
+recipe = zc.zope3recipes:instance
+application = app
+zope.conf = ${data:zconfig}
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = LoginDemo
+defaults = ['--tests-pattern', '^f?tests$', '-v']
+
+# this section named so that the i18n scripts are called bin/i18n...
+[i18n]
+recipe = lovely.recipe:i18n
+package = logindemo
+domain = logindemo
+location = src/logindemo
+output = locales

Added: grokapps/LoginDemo/setup.py
===================================================================
--- grokapps/LoginDemo/setup.py	                        (rev 0)
+++ grokapps/LoginDemo/setup.py	2007-12-28 15:49:03 UTC (rev 82500)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = '0.0'
+
+setup(name='LoginDemo',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # Add extra requirements here
+                        ],
+      entry_points="""
+      # Add entry points here
+      """,
+      )

Added: grokapps/LoginDemo/src/logindemo/__init__.py
===================================================================
--- grokapps/LoginDemo/src/logindemo/__init__.py	                        (rev 0)
+++ grokapps/LoginDemo/src/logindemo/__init__.py	2007-12-28 15:49:03 UTC (rev 82500)
@@ -0,0 +1 @@
+# this directory is a package

Added: grokapps/LoginDemo/src/logindemo/app.py
===================================================================
--- grokapps/LoginDemo/src/logindemo/app.py	                        (rev 0)
+++ grokapps/LoginDemo/src/logindemo/app.py	2007-12-28 15:49:03 UTC (rev 82500)
@@ -0,0 +1,98 @@
+import grok
+
+from urllib import urlencode
+
+from zope.interface import Interface
+from zope.app.authentication import PluggableAuthentication
+from zope.app.authentication.principalfolder import PrincipalFolder
+from zope.app.authentication.principalfolder import InternalPrincipal
+from zope.app.authentication.session import SessionCredentialsPlugin
+from zope.app.security.interfaces import IAuthentication
+from zope.app.security.interfaces import IUnauthenticatedPrincipal
+from zope.app.securitypolicy.interfaces import IRole
+from zope.app.securitypolicy.interfaces import IPrincipalRoleManager
+from zope.app.securitypolicy.role import LocalRole
+from zope.component import getUtility
+
+
+
+from logindemo.interfaces import IUser
+
+def setup_pau(pau):
+    pau['principals'] = PrincipalFolder()
+    pau.authenticatorPlugins = ('principals',)
+    pau['session'] = session = SessionCredentialsPlugin()
+    session.loginpagename = 'login'
+    pau.credentialsPlugins = ('No Challenge if Authenticated', 'session',)
+
+def role_factory(*args):
+    def factory():
+        return LocalRole(*args)
+    return factory
+
+class LoginDemo(grok.Application, grok.Container):
+    """
+    An app that lets you create an account and change your password.
+    """
+    grok.local_utility(PluggableAuthentication, IAuthentication,
+                       setup=setup_pau)
+    grok.local_utility(role_factory(u'Site Member'), IRole,
+                       name='logindemo.member',
+                       name_in_container='logindemo.member')
+
+class Index(grok.View):
+    """
+    The main page, where the user can login or click a link to join.
+    """
+    
+    def logged_in(self):
+        return not IUnauthenticatedPrincipal.providedBy(self.request.principal)
+
+class Login(grok.View):
+    grok.context(Interface)
+    
+    message = '' # used to give feedback on failed logins
+
+    def update(self, login_submit=None):
+        # XXX: need to display some kind of feedback when the login fails
+        if login_submit is not None:
+            if IUnauthenticatedPrincipal.providedBy(self.request.principal):
+                self.message = u'Invalid login name and/or password'
+            else:
+                destination = self.request.get('camefrom', self.application_url())
+                self.redirect(destination)
+
+class Logout(grok.View):
+    grok.context(Interface)
+    def render(self):
+        session = getUtility(IAuthentication)['session']
+        session.logout(self.request)
+        self.redirect(self.application_url())
+        
+class Join(grok.AddForm):
+    """User registration form"""
+
+    form_fields = grok.AutoFields(IUser)
+    #template = grok.PageTemplateFile('form.pt')
+    form_title = u'User registration'
+
+    @grok.action('Save')
+    def join(self, **data):
+        login = data['login']
+        pau = getUtility(IAuthentication)
+        principals = pau['principals']
+        if login in principals: # duplicate login name
+            ### XXX: find out how to display this message in the form template
+            msg = u'Duplicate login. Please choose a different one.'
+            self.redirect(self.url()+'?'+urlencode({'error_msg':msg}))
+        else:
+            # add principal to principal folder
+            principals[login] = InternalPrincipal(login, data['password'],
+                                                  data['name'])    
+            # assign role to principal
+            role_manager = IPrincipalRoleManager(self.context)
+            role_manager.assignRoleToPrincipal('logindemo.member', 
+                                   principals.prefix + login)
+            self.redirect(self.url('login')+'?'+urlencode({'login':login}))
+
+        
\ No newline at end of file

Added: grokapps/LoginDemo/src/logindemo/app_templates/index.pt
===================================================================
--- grokapps/LoginDemo/src/logindemo/app_templates/index.pt	                        (rev 0)
+++ grokapps/LoginDemo/src/logindemo/app_templates/index.pt	2007-12-28 15:49:03 UTC (rev 82500)
@@ -0,0 +1,31 @@
+<html>
+<head>
+<title>Grok Login Sample Application</title>
+</head>
+<body>
+    <h1>Front Page</h1>
+    
+    <h3>User information</h3>
+    <dl>
+        <dt>principal.id</dt>
+            <dd tal:content="request/principal/id" />
+        
+    </dl>
+    <dl>
+        <dt>principal.title</dt>
+            <dd tal:content="request/principal/title" />
+        
+    </dl>
+    
+    <p>
+        You are <em tal:condition="not:view/logged_in">not </em>logged in.
+    </p>
+    
+    <tal:not_logged_in condition="not:view/logged_in">
+  
+        <form metal:use-macro="context/@@login/macros/loginform" />
+        
+    </tal:not_logged_in>
+  
+</body>
+</html>

Added: grokapps/LoginDemo/src/logindemo/app_templates/login.pt
===================================================================
--- grokapps/LoginDemo/src/logindemo/app_templates/login.pt	                        (rev 0)
+++ grokapps/LoginDemo/src/logindemo/app_templates/login.pt	2007-12-28 15:49:03 UTC (rev 82500)
@@ -0,0 +1,40 @@
+<html>
+<head>
+<title>Login</title>
+</head>
+<body>
+    <h1>Login</h1>
+    
+    <div tal:condition="view/message" tal:content="view/message" />
+    
+    <form metal:define-macro="loginform" action="login" method="post">
+        <input type="hidden" name="camefrom"
+            tal:condition="exists:request/camefrom"
+            tal:attributes="value request/camefrom" />
+        
+        <table>
+            <tr>
+                <th>Login</th>
+                <td>
+                    <input type="text" name="login" id="login"
+                        tal:attributes="value request/login|nothing"/>
+                </td>
+            </tr>
+            <tr>
+                <th>Password</th>
+                <td>
+                    <input type="password" name="password" id="password" />
+                </td>
+            </tr>
+            <tr>
+                <td></td>
+                <td>
+                    <input type="submit" name="login_submit" value="Log in" />
+                </td>
+            </tr>
+        </table>
+    </form>
+    
+  
+</body>
+</html>

Added: grokapps/LoginDemo/src/logindemo/configure.zcml
===================================================================
--- grokapps/LoginDemo/src/logindemo/configure.zcml	                        (rev 0)
+++ grokapps/LoginDemo/src/logindemo/configure.zcml	2007-12-28 15:49:03 UTC (rev 82500)
@@ -0,0 +1,5 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+           xmlns:grok="http://namespaces.zope.org/grok">
+  <include package="grok" />
+  <grok:grok package="." />
+</configure>

Added: grokapps/LoginDemo/src/logindemo/ftesting.zcml
===================================================================
--- grokapps/LoginDemo/src/logindemo/ftesting.zcml	                        (rev 0)
+++ grokapps/LoginDemo/src/logindemo/ftesting.zcml	2007-12-28 15:49:03 UTC (rev 82500)
@@ -0,0 +1,35 @@
+<configure
+   xmlns="http://namespaces.zope.org/zope"
+   i18n_domain="logindemo"
+   package="logindemo"
+   >
+
+  <include package="grok" />
+  <include package="logindemo" />
+
+  <!-- Typical functional testing security setup -->
+  <securityPolicy
+      component="zope.app.securitypolicy.zopepolicy.ZopeSecurityPolicy"
+      />
+
+  <unauthenticatedPrincipal
+      id="zope.anybody"
+      title="Unauthenticated User"
+      />
+  <grant
+      permission="zope.View"
+      principal="zope.anybody"
+      />
+
+  <principal
+      id="zope.mgr"
+      title="Manager"
+      login="mgr"
+      password="mgrpw"
+      />
+
+  <role id="zope.Manager" title="Site Manager" />
+  <grantAll role="zope.Manager" />
+  <grant role="zope.Manager" principal="zope.mgr" />
+
+</configure>

Added: grokapps/LoginDemo/src/logindemo/ftests/__init__.py
===================================================================
--- grokapps/LoginDemo/src/logindemo/ftests/__init__.py	                        (rev 0)
+++ grokapps/LoginDemo/src/logindemo/ftests/__init__.py	2007-12-28 15:49:03 UTC (rev 82500)
@@ -0,0 +1 @@
+# this directory is a package

Added: grokapps/LoginDemo/src/logindemo/ftests/index.txt
===================================================================
--- grokapps/LoginDemo/src/logindemo/ftests/index.txt	                        (rev 0)
+++ grokapps/LoginDemo/src/logindemo/ftests/index.txt	2007-12-28 15:49:03 UTC (rev 82500)
@@ -0,0 +1,42 @@
+=====================
+Testing the main page
+=====================
+
+First we setup the app and our test browser, and go to the main page::
+
+    >>> from logindemo.app import LoginDemo
+    >>> root = getRootFolder()
+    >>> app = root['ld'] = LoginDemo()
+    >>> browser = Browser()
+    >>> browser.open('http://localhost/ld/')                 
+
+Now we check the contents of the page::
+
+    >>> browser.contents
+    '...<dt>principal.id</dt>...<dd>zope.anybody</dd>...'
+    >>> browser.contents
+    '...<dt>principal.title</dt>...<dd>Unauthenticated User</dd>...'
+    >>> 'You are <em>not </em>logged in.' in browser.contents
+    True
+    
+If the user is already authenticated, he will se a different message::
+
+    >>> auth_browser = Browser()
+    >>> auth_browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+    >>> auth_browser.open('http://localhost/ld/')                 
+    >>> 'You are logged in.' in auth_browser.contents
+    True
+
+Back to our original browser, let's use the login form to authenticate.
+
+First, we will provide the wrong password, and that will take us to the
+login page with a feedback message::
+
+    >>> browser.getControl(name='login').value = 'mgr'
+    >>> browser.getControl(name='password').value = 'mgrpw'
+    >>> browser.getControl('Log in').click()
+    >>> browser.url
+    'http://localhost/ld/login'
+    >>> 'Invalid login name and/or password' in browser.contents
+    True
+    

Added: grokapps/LoginDemo/src/logindemo/ftests/test_functional.py
===================================================================
--- grokapps/LoginDemo/src/logindemo/ftests/test_functional.py	                        (rev 0)
+++ grokapps/LoginDemo/src/logindemo/ftests/test_functional.py	2007-12-28 15:49:03 UTC (rev 82500)
@@ -0,0 +1,31 @@
+import os
+import unittest
+import logindemo
+from zope.testing import doctest
+from zope.app.testing.functional import (FunctionalTestSetup, ZCMLLayer,
+                                         getRootFolder, FunctionalDocFileSuite)
+import zope.testbrowser.browser
+import zope.testbrowser.testing
+
+ftesting_zcml = os.path.join(os.path.dirname(logindemo.__file__), 'ftesting.zcml')
+TestedSampleFunctionalLayer = ZCMLLayer(ftesting_zcml, __name__, 'TestedSampleFunctionalLayer')
+
+def test_suite():
+    suite = unittest.TestSuite()
+    docfiles = ['index.txt']
+
+    for docfile in docfiles:
+        test = FunctionalDocFileSuite(
+             docfile,
+             globs=dict(getRootFolder=getRootFolder, Browser=zope.testbrowser.testing.Browser),
+             optionflags = (doctest.ELLIPSIS
+                            | doctest.REPORT_NDIFF
+                            | doctest.NORMALIZE_WHITESPACE),)
+        test.layer = TestedSampleFunctionalLayer
+        suite.addTest(test)
+
+    return suite
+
+if __name__ == '__main__':
+    unittest.main()
+

Added: grokapps/LoginDemo/src/logindemo/interfaces.py
===================================================================
--- grokapps/LoginDemo/src/logindemo/interfaces.py	                        (rev 0)
+++ grokapps/LoginDemo/src/logindemo/interfaces.py	2007-12-28 15:49:03 UTC (rev 82500)
@@ -0,0 +1,13 @@
+from zope.interface import Interface
+from zope import schema
+
+class IUser(Interface):
+    """Basic user data."""
+    login = schema.TextLine(title=u"Login",
+                            required=True)
+    password = schema.Password(title=u"Password",
+                            required=True)
+    name = schema.TextLine(title=u"Real name",
+                            required=False)
+    email = schema.ASCIILine(title=u"E-mail",
+                            required=False)

Added: grokapps/LoginDemo/src/logindemo/login.txt
===================================================================
--- grokapps/LoginDemo/src/logindemo/login.txt	                        (rev 0)
+++ grokapps/LoginDemo/src/logindemo/login.txt	2007-12-28 15:49:03 UTC (rev 82500)
@@ -0,0 +1,13 @@
+The initial page of the app shows the principal id and title.
+For an unauthenticated request, the login form is also shown.
+
+    >>> from zope.testbrowser import Browser
+    >>> browser = Browser()
+    >>> browser.open('http://localhost/')
+    >>> 'principal.id' in browser.contents
+    True
+    >>> 'principal.title' in browser.contents
+    True
+
+
+

Added: grokapps/LoginDemo/src/logindemo/testing.py
===================================================================
--- grokapps/LoginDemo/src/logindemo/testing.py	                        (rev 0)
+++ grokapps/LoginDemo/src/logindemo/testing.py	2007-12-28 15:49:03 UTC (rev 82500)
@@ -0,0 +1,7 @@
+import os.path
+import logindemo
+from zope.app.testing.functional import ZCMLLayer
+
+ftesting_zcml = os.path.join(
+    os.path.dirname(logindemo.__file__), 'ftesting.zcml')
+FunctionalLayer = ZCMLLayer(ftesting_zcml, __name__, 'FunctionalLayer')



More information about the Checkins mailing list