[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