summaryrefslogtreecommitdiff
path: root/docs/quick_tutorial/authentication
diff options
context:
space:
mode:
authorPaul Everitt <paul@agendaless.com>2013-09-13 16:52:14 -0400
committerPaul Everitt <paul@agendaless.com>2013-09-13 16:52:14 -0400
commitb1b92284f496800a4dfd2cea72cb9be07ba8661c (patch)
tree9dfa72427fd6aa0a3a7aaba72be4a4e49380ee26 /docs/quick_tutorial/authentication
parent1d04f8f0b483b8d595f5ada24ae5108affe80160 (diff)
downloadpyramid-b1b92284f496800a4dfd2cea72cb9be07ba8661c.tar.gz
pyramid-b1b92284f496800a4dfd2cea72cb9be07ba8661c.tar.bz2
pyramid-b1b92284f496800a4dfd2cea72cb9be07ba8661c.zip
First cut at import of quick tutorial.
Diffstat (limited to 'docs/quick_tutorial/authentication')
-rw-r--r--docs/quick_tutorial/authentication/development.ini42
-rw-r--r--docs/quick_tutorial/authentication/setup.py13
-rw-r--r--docs/quick_tutorial/authentication/tutorial/__init__.py24
-rw-r--r--docs/quick_tutorial/authentication/tutorial/home.pt18
-rw-r--r--docs/quick_tutorial/authentication/tutorial/login.pt25
-rw-r--r--docs/quick_tutorial/authentication/tutorial/security.py8
-rw-r--r--docs/quick_tutorial/authentication/tutorial/tests.py47
-rw-r--r--docs/quick_tutorial/authentication/tutorial/views.py64
8 files changed, 241 insertions, 0 deletions
diff --git a/docs/quick_tutorial/authentication/development.ini b/docs/quick_tutorial/authentication/development.ini
new file mode 100644
index 000000000..5d4580ff5
--- /dev/null
+++ b/docs/quick_tutorial/authentication/development.ini
@@ -0,0 +1,42 @@
+[app:main]
+use = egg:tutorial
+pyramid.reload_templates = true
+pyramid.includes =
+ pyramid_debugtoolbar
+tutorial.secret = 98zd
+
+[server:main]
+use = egg:pyramid#wsgiref
+host = 0.0.0.0
+port = 6543
+
+# Begin logging configuration
+
+[loggers]
+keys = root, tutorial
+
+[logger_tutorial]
+level = DEBUG
+handlers =
+qualname = tutorial
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = INFO
+handlers = console
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
+
+# End logging configuration
diff --git a/docs/quick_tutorial/authentication/setup.py b/docs/quick_tutorial/authentication/setup.py
new file mode 100644
index 000000000..9997984d3
--- /dev/null
+++ b/docs/quick_tutorial/authentication/setup.py
@@ -0,0 +1,13 @@
+from setuptools import setup
+
+requires = [
+ 'pyramid',
+]
+
+setup(name='tutorial',
+ install_requires=requires,
+ entry_points="""\
+ [paste.app_factory]
+ main = tutorial:main
+ """,
+) \ No newline at end of file
diff --git a/docs/quick_tutorial/authentication/tutorial/__init__.py b/docs/quick_tutorial/authentication/tutorial/__init__.py
new file mode 100644
index 000000000..7aa049427
--- /dev/null
+++ b/docs/quick_tutorial/authentication/tutorial/__init__.py
@@ -0,0 +1,24 @@
+from pyramid.authentication import AuthTktAuthenticationPolicy
+from pyramid.authorization import ACLAuthorizationPolicy
+from pyramid.config import Configurator
+
+from .security import groupfinder
+
+
+def main(global_config, **settings):
+ config = Configurator(settings=settings)
+
+ # Security policies
+ authn_policy = AuthTktAuthenticationPolicy(
+ settings['tutorial.secret'], callback=groupfinder,
+ hashalg='sha512')
+ authz_policy = ACLAuthorizationPolicy()
+ config.set_authentication_policy(authn_policy)
+ config.set_authorization_policy(authz_policy)
+
+ config.add_route('home', '/')
+ config.add_route('hello', '/howdy')
+ config.add_route('login', '/login')
+ config.add_route('logout', '/logout')
+ config.scan('.views')
+ return config.make_wsgi_app() \ No newline at end of file
diff --git a/docs/quick_tutorial/authentication/tutorial/home.pt b/docs/quick_tutorial/authentication/tutorial/home.pt
new file mode 100644
index 000000000..6ecd0081b
--- /dev/null
+++ b/docs/quick_tutorial/authentication/tutorial/home.pt
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>Quick Tour: ${name}</title>
+</head>
+<body>
+
+<div>
+ <a tal:condition="view.logged_in is None"
+ href="${request.application_url}/login">Log In</a>
+ <a tal:condition="view.logged_in is not None"
+ href="${request.application_url}/logout">Logout</a>
+</div>
+
+<h1>Hi ${name}</h1>
+<p>Visit <a href="${request.route_url('hello')}">hello</a></p>
+</body>
+</html> \ No newline at end of file
diff --git a/docs/quick_tutorial/authentication/tutorial/login.pt b/docs/quick_tutorial/authentication/tutorial/login.pt
new file mode 100644
index 000000000..4451fc4f8
--- /dev/null
+++ b/docs/quick_tutorial/authentication/tutorial/login.pt
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>Quick Tour: ${name}</title>
+</head>
+<body>
+<h1>Login</h1>
+<span tal:replace="message"/>
+
+<form action="${url}" method="post">
+ <input type="hidden" name="came_from"
+ value="${came_from}"/>
+ <label for="login">Username</label>
+ <input type="text" id="login"
+ name="login"
+ value="${login}"/><br/>
+ <label for="password">Password</label>
+ <input type="password" id="password"
+ name="password"
+ value="${password}"/><br/>
+ <input type="submit" name="form.submitted"
+ value="Log In"/>
+</form>
+</body>
+</html> \ No newline at end of file
diff --git a/docs/quick_tutorial/authentication/tutorial/security.py b/docs/quick_tutorial/authentication/tutorial/security.py
new file mode 100644
index 000000000..ab90bab2c
--- /dev/null
+++ b/docs/quick_tutorial/authentication/tutorial/security.py
@@ -0,0 +1,8 @@
+USERS = {'editor': 'editor',
+ 'viewer': 'viewer'}
+GROUPS = {'editor': ['group:editors']}
+
+
+def groupfinder(userid, request):
+ if userid in USERS:
+ return GROUPS.get(userid, []) \ No newline at end of file
diff --git a/docs/quick_tutorial/authentication/tutorial/tests.py b/docs/quick_tutorial/authentication/tutorial/tests.py
new file mode 100644
index 000000000..6ff554a1e
--- /dev/null
+++ b/docs/quick_tutorial/authentication/tutorial/tests.py
@@ -0,0 +1,47 @@
+import unittest
+
+from pyramid import testing
+
+
+class TutorialViewTests(unittest.TestCase):
+ def setUp(self):
+ self.config = testing.setUp()
+
+ def tearDown(self):
+ testing.tearDown()
+
+ def test_home(self):
+ from .views import TutorialViews
+
+ request = testing.DummyRequest()
+ inst = TutorialViews(request)
+ response = inst.home()
+ self.assertEqual('Home View', response['name'])
+
+ def test_hello(self):
+ from .views import TutorialViews
+
+ request = testing.DummyRequest()
+ inst = TutorialViews(request)
+ response = inst.hello()
+ self.assertEqual('Hello View', response['name'])
+
+
+class TutorialFunctionalTests(unittest.TestCase):
+ def setUp(self):
+ from tutorial import main
+ app = main({})
+ from webtest import TestApp
+
+ self.testapp = TestApp(app)
+
+ def tearDown(self):
+ testing.tearDown()
+
+ def test_home(self):
+ res = self.testapp.get('/', status=200)
+ self.assertIn(b'<h1>Hi Home View', res.body)
+
+ def test_hello(self):
+ res = self.testapp.get('/howdy', status=200)
+ self.assertIn(b'<h1>Hi Hello View', res.body)
diff --git a/docs/quick_tutorial/authentication/tutorial/views.py b/docs/quick_tutorial/authentication/tutorial/views.py
new file mode 100644
index 000000000..3038b6d9b
--- /dev/null
+++ b/docs/quick_tutorial/authentication/tutorial/views.py
@@ -0,0 +1,64 @@
+from pyramid.httpexceptions import HTTPFound
+from pyramid.security import (
+ remember,
+ forget,
+ authenticated_userid
+ )
+from pyramid.view import (
+ view_config,
+ view_defaults
+ )
+
+from .security import USERS
+
+
+@view_defaults(renderer='home.pt')
+class TutorialViews:
+ def __init__(self, request):
+ self.request = request
+ self.logged_in = authenticated_userid(request)
+
+ @view_config(route_name='home')
+ def home(self):
+ return {'name': 'Home View'}
+
+ @view_config(route_name='hello')
+ def hello(self):
+ return {'name': 'Hello View'}
+
+ @view_config(route_name='login', renderer='login.pt')
+ def login(self):
+ request = self.request
+ login_url = request.route_url('login')
+ referrer = request.url
+ if referrer == login_url:
+ referrer = '/' # never use login form itself as came_from
+ came_from = request.params.get('came_from', referrer)
+ message = ''
+ login = ''
+ password = ''
+ if 'form.submitted' in request.params:
+ login = request.params['login']
+ password = request.params['password']
+ if USERS.get(login) == password:
+ headers = remember(request, login)
+ return HTTPFound(location=came_from,
+ headers=headers)
+ message = 'Failed login'
+
+ return dict(
+ name='Login',
+ message=message,
+ url=request.application_url + '/login',
+ came_from=came_from,
+ login=login,
+ password=password,
+ )
+
+ @view_config(route_name='logout')
+ def logout(self):
+ request = self.request
+ headers = forget(request)
+ url = request.route_url('home')
+ return HTTPFound(location=url,
+ headers=headers)