Merge lp:~canonical-isd-hackers/canonical-identity-provider/sso-preflight into lp:canonical-identity-provider/release

Proposed by David Owen
Status: Merged
Approved by: David Owen
Approved revision: no longer in the source branch.
Merged at revision: 135
Proposed branch: lp:~canonical-isd-hackers/canonical-identity-provider/sso-preflight
Merge into: lp:canonical-identity-provider/release
Diff against target: 239 lines (+83/-56)
8 files modified
debian/control (+2/-0)
identityprovider/auth.py (+9/-0)
identityprovider/decorators.py (+15/-0)
identityprovider/preflight.py (+42/-0)
identityprovider/tests/test_views_preflight.py (+12/-11)
identityprovider/urls.py (+0/-4)
identityprovider/views/versions.py (+0/-39)
setup.py (+3/-2)
To merge this branch: bzr merge lp:~canonical-isd-hackers/canonical-identity-provider/sso-preflight
Reviewer Review Type Date Requested Status
Ricardo Kirkner (community) Approve
Łukasz Czyżykowski Pending
Review via email: mp+52230@code.launchpad.net

Commit message

Added preflight, removed old +versions page

Description of the change

Be sure to grab the config changes at https://code.launchpad.net/~canonical-isd-hackers/isd-configs/sso-preflight/+merge/52261

Brings Łukasz's django-preflight into SSO. Part of preflight includes a version check, which completely supersedes SSO's previous /+versions page.

I've added only one preflight check (DB connectivity). I have filed bugs for logging and OOPS checks, which will not be trivial.

To post a comment you must log in.
Revision history for this message
David Owen (dsowen) wrote :

I rebased to pull in the new bootstrap changes, but I haven't been able to produce an environment that works since.

Revision history for this message
Ricardo Kirkner (ricardokirkner) wrote :

Fine work. Please just remove the commented code.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2011-01-21 23:23:08 +0000
3+++ debian/control 2011-03-07 23:24:09 +0000
4@@ -18,6 +18,8 @@
5 canonical-isd-web-dependencies (>= 1.0.18),
6 memcached,
7 python-django-oauth-backend (= 0.1.dev1),
8+ python-django-preflight (>= 0.1),
9+ python-django-preflight (<< 0.2),
10 python-django-settings (>= 0.2),
11 python-memcache,
12 python-lazr.restful (>= 0.9.18),
13
14=== modified file 'identityprovider/auth.py'
15--- identityprovider/auth.py 2011-01-10 15:02:53 +0000
16+++ identityprovider/auth.py 2011-03-07 23:24:09 +0000
17@@ -3,6 +3,7 @@
18
19 from datetime import datetime
20
21+from django.conf import settings
22 from oauth_backend.models import Consumer, Token
23
24 from identityprovider.models import Account, AccountPassword, EmailAddress
25@@ -84,3 +85,11 @@
26 return account
27 else:
28 return None
29+
30+
31+def internal_authorize(user):
32+ if user.is_authenticated() and user.person is not None:
33+ for team in getattr(settings, 'SSO_VERSIONS_TEAMS', []):
34+ if user.person.in_team(team):
35+ return True
36+ return False
37
38=== modified file 'identityprovider/decorators.py'
39--- identityprovider/decorators.py 2010-08-23 15:54:23 +0000
40+++ identityprovider/decorators.py 2011-03-07 23:24:09 +0000
41@@ -14,6 +14,8 @@
42 import functools
43 from hashlib import sha1
44
45+from identityprovider import auth
46+
47
48 def guest_required(func):
49 def _guest_required_decorator(request, *args, **kwargs):
50@@ -195,3 +197,16 @@
51 }
52 args.update(options)
53 super(limitlogin, self).__init__(**args)
54+
55+
56+def internal_only(view):
57+ """
58+ Restricts access to internal team members only, and masks the
59+ existence of the view from others.
60+ """
61+ @functools.wraps(view)
62+ def wrapper(request, *args, **kwargs):
63+ if auth.internal_authorize(request.user):
64+ return view(request, *args, **kwargs)
65+ raise Http404
66+ return wrapper
67
68=== added file 'identityprovider/preflight.py'
69--- identityprovider/preflight.py 1970-01-01 00:00:00 +0000
70+++ identityprovider/preflight.py 2011-03-07 23:24:09 +0000
71@@ -0,0 +1,42 @@
72+from __future__ import absolute_import
73+
74+import preflight
75+
76+from .auth import internal_authorize
77+
78+
79+# Remember that the preflight may be run from the command-line or
80+# queried from a web-browser. Some tests may always pass in one
81+# environment (e.g. if you can even *hit* the preflight page in a
82+# browser, you already know the DB is up), and that's okay.
83+#
84+# Make sure that each test at least works in both environment: a test
85+# shouldn't fail in either environment unless there's really a
86+# problem.
87+
88+@preflight.register
89+class SSOPreflight(preflight.Preflight):
90+
91+ def authenticate(self, request):
92+ return internal_authorize(request.user)
93+
94+ def versions(self):
95+ import lazr
96+ import openid
97+ import identityprovider
98+ return [
99+ {'name': 'SSO', 'version': identityprovider.__version__},
100+ {'name': 'lazr.restful', 'version': lazr.restful.__version__},
101+ {'name': 'openid', 'version': openid.__version__},
102+ ]
103+
104+
105+ def check_database(self):
106+ 'Are database connections accepted?'
107+ from django import db
108+
109+ cursor = db.connection.cursor()
110+ cursor.execute('SELECT 42')
111+ cursor.fetchone()
112+
113+ return True
114
115=== renamed file 'identityprovider/tests/test_views_versions.py' => 'identityprovider/tests/test_views_preflight.py'
116--- identityprovider/tests/test_views_versions.py 2010-06-18 15:36:18 +0000
117+++ identityprovider/tests/test_views_preflight.py 2011-03-07 23:24:09 +0000
118@@ -1,33 +1,34 @@
119+from django.conf import settings
120+
121+from identityprovider.models.account import Account
122 from identityprovider.tests.utils import BasicAccountTestCase
123-from identityprovider.models.account import Account
124-from django.conf import settings
125-
126-
127-
128-class VersionsViewAccessTestCase(BasicAccountTestCase):
129+
130+
131+class PreflightViewAccessTestCase(BasicAccountTestCase):
132
133 fixtures = ["test"]
134+ URL = '/preflight/'
135
136 def test_non_authenticated_users_are_getting_404(self):
137- r = self.client.get('/+versions')
138+ r = self.client.get(self.URL)
139 self.assertEquals(r.status_code, 404)
140
141 def test_account_withtout_person_receives_404(self):
142 account = Account.objects.create_account(
143 "test", "abcd@example.com", "test")
144 self.client.login(username="abcd@example.com", password="test")
145- r = self.client.get('/+versions')
146+ r = self.client.get(self.URL)
147 self.assertEquals(r.status_code, 404)
148 account.delete()
149
150 def test_person_not_in_the_required_team_will_get_404(self):
151 self.client.login(username="test@canonical.com", password="test")
152- r = self.client.get('/+versions')
153+ r = self.client.get(self.URL)
154 self.assertEquals(r.status_code, 404)
155
156 def test_person_in_ubuntu_team_can_access_the_page(self):
157 settings.SSO_VERSIONS_TEAMS = ["ubuntu-team"]
158 self.client.login(username="member@canonical.com", password="test")
159
160- r = self.client.get('/+versions')
161- self.assertTemplateUsed(r, "versions.html")
162+ r = self.client.get(self.URL)
163+ self.assertTemplateUsed(r, "preflight/overview.html")
164
165=== modified file 'identityprovider/urls.py'
166--- identityprovider/urls.py 2010-10-21 21:39:03 +0000
167+++ identityprovider/urls.py 2011-03-07 23:24:09 +0000
168@@ -82,10 +82,6 @@
169 (r'^set_language$', 'set_language'),
170 )
171
172-urlpatterns += patterns('identityprovider.views.versions',
173- (r'\+versions','versions'),
174-)
175-
176 urlpatterns += patterns('identityprovider.views.readonly',
177 (r'^readonly$', 'readonly_admin'),
178 (r'^readonly/((?P<appserver>[A-Za-z0-9\-_.:]+)/)?(?P<action>enable|disable|set|clear)(/(?P<conn>[A-Za-z0-9\-_.]+))?',
179
180=== removed file 'identityprovider/views/versions.py'
181--- identityprovider/views/versions.py 2010-06-21 08:09:20 +0000
182+++ identityprovider/views/versions.py 1970-01-01 00:00:00 +0000
183@@ -1,39 +0,0 @@
184-# Copyright 2010 Canonical Ltd. This software is licensed under the
185-# GNU Affero General Public License version 3 (see the file LICENSE).
186-
187-from django.template import RequestContext
188-from django.shortcuts import render_to_response
189-from django.http import Http404
190-from django.conf import settings
191-
192-
193-def gather_version_information():
194- import identityprovider
195- import lazr.restful
196- import django
197- import openid
198- import sys
199-
200- return [
201- {'name': 'SSO', 'version': identityprovider.__version__},
202- {'name': 'Django', 'version': django.get_version()},
203- {'name': 'lazr.restful', 'version': lazr.restful.__version__},
204- {'name': 'openid', 'version': openid.__version__},
205- {'name': 'Python', 'version': sys.version},
206- ]
207-
208-
209-def versions(request):
210- # 404 to not reveal this to automatic scripts
211- if not request.user.is_authenticated() or request.user.person is None:
212- raise Http404
213-
214- for team in getattr(settings, 'SSO_VERSIONS_TEAMS', []):
215- if request.user.person.in_team(team):
216- break
217- else:
218- raise Http404
219-
220- versions = gather_version_information()
221- return render_to_response("versions.html",
222- RequestContext(request, {'versions': versions}))
223
224=== modified file 'setup.py'
225--- setup.py 2011-03-03 03:12:06 +0000
226+++ setup.py 2011-03-07 23:24:09 +0000
227@@ -77,9 +77,10 @@
228 'South==0.6',
229 'configglue==0.9pre1',
230 'django-configglue==0.3',
231+ # need to install it via requirements.txt until a release is made:
232+ #'django-oauth-backend',
233 'django-openid-auth==0.2',
234- # need to install it via requirements.txt until a release is made
235- #'django-oauth-backend',
236+ 'django-preflight==0.1',
237 'lazr.authentication==0.1.2',
238 'lazr.restful==0.9.19',
239 # PyPi calls upstream's 1.0a "1.0.1" maybe because it doesn't