Merge lp:~salgado/launchpad/bug-547054 into lp:launchpad/db-devel

Proposed by Guilherme Salgado
Status: Merged
Merged at revision: not available
Proposed branch: lp:~salgado/launchpad/bug-547054
Merge into: lp:launchpad/db-devel
Diff against target: 116 lines (+49/-11)
2 files modified
lib/canonical/launchpad/webapp/login.py (+20/-7)
lib/canonical/launchpad/webapp/tests/test_login.py (+29/-4)
To merge this branch: bzr merge lp:~salgado/launchpad/bug-547054
Reviewer Review Type Date Requested Status
Francis J. Lacoste (community) release-critical Approve
Brad Crittenden (community) code Approve
Deryck Hodge release-critical Pending
Review via email: mp+22460@code.launchpad.net

Description of the change

Do not render the login-error page when the user is already logged in.
Instead, redirect to the starting_url defined in the OpenID response and
add a notification message to the response.

--
Guilherme Salgado <email address hidden>

To post a comment you must log in.
Revision history for this message
Brad Crittenden (bac) :
review: Approve (code)
Revision history for this message
Francis J. Lacoste (flacoste) :
review: Approve (release-critical)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/launchpad/webapp/login.py'
2--- lib/canonical/launchpad/webapp/login.py 2010-03-18 15:21:03 +0000
3+++ lib/canonical/launchpad/webapp/login.py 2010-03-30 15:23:29 +0000
4@@ -284,7 +284,6 @@
5 def render(self):
6 if self.openid_response.status == SUCCESS:
7 identifier = self.openid_response.identity_url.split('/')[-1]
8- account_set = getUtility(IAccountSet)
9 should_update_last_write = False
10 # Force the use of the master database to make sure a lagged slave
11 # doesn't fool us into creating a Person/Account when one already
12@@ -311,15 +310,23 @@
13 # the master DB and thus see the changes we've just made.
14 session_data = ISession(self.request)['lp.dbpolicy']
15 session_data['last_write'] = datetime.utcnow()
16- target = self.request.form.get('starting_url')
17- if target is None:
18- target = self.getApplicationURL()
19- self.request.response.redirect(target, temporary_if_possible=True)
20+ self._redirect()
21 # No need to return anything as we redirect above.
22 retval = None
23 else:
24- retval = OpenIDLoginErrorView(
25- self.context, self.request, self.openid_response)()
26+ if self.account is not None:
27+ # The authentication failed (or was canceled), but the user is
28+ # already logged in, so we just add a notification message and
29+ # redirect.
30+ self.request.response.addNoticeNotification(
31+ _(u'Your authentication failed but you were already '
32+ 'logged into Launchpad.'))
33+ self._redirect()
34+ # No need to return anything as we redirect above.
35+ retval = None
36+ else:
37+ retval = OpenIDLoginErrorView(
38+ self.context, self.request, self.openid_response)()
39
40 # The consumer.complete() call above will create entries in
41 # OpenIDConsumerNonce to prevent replay attacks, but since this will
42@@ -329,6 +336,12 @@
43
44 return retval
45
46+ def _redirect(self):
47+ target = self.request.form.get('starting_url')
48+ if target is None:
49+ target = self.getApplicationURL()
50+ self.request.response.redirect(target, temporary_if_possible=True)
51+
52
53 class OpenIDLoginErrorView(LaunchpadView):
54
55
56=== modified file 'lib/canonical/launchpad/webapp/tests/test_login.py'
57--- lib/canonical/launchpad/webapp/tests/test_login.py 2010-03-04 14:03:34 +0000
58+++ lib/canonical/launchpad/webapp/tests/test_login.py 2010-03-30 15:23:29 +0000
59@@ -107,13 +107,16 @@
60 layer = DatabaseFunctionalLayer
61
62 def _createViewWithResponse(
63- self, account, response_status=SUCCESS, response_msg=''):
64+ self, account, response_status=SUCCESS, response_msg='',
65+ view_class=StubbedOpenIDCallbackView):
66 openid_response = FakeOpenIDResponse(
67 ITestOpenIDPersistentIdentity(account).openid_identity_url,
68 status=response_status, message=response_msg)
69- return self._createAndRenderView(openid_response)
70+ return self._createAndRenderView(
71+ openid_response, view_class=view_class)
72
73- def _createAndRenderView(self, response):
74+ def _createAndRenderView(self, response,
75+ view_class=StubbedOpenIDCallbackView):
76 request = LaunchpadTestRequest(
77 form={'starting_url': 'http://launchpad.dev/after-login'},
78 environ={'PATH_INFO': '/'})
79@@ -122,7 +125,7 @@
80 # setup a newInteraction() using our request.
81 logout()
82 newInteraction(request)
83- view = StubbedOpenIDCallbackView(object(), request)
84+ view = view_class(object(), request)
85 view.initialize()
86 view.openid_response = response
87 # Monkey-patch getByOpenIDIdentifier() to make sure the view uses the
88@@ -235,6 +238,28 @@
89 main_content = extract_text(find_main_content(html))
90 self.assertIn('Your login was unsuccessful', main_content)
91
92+ def test_negative_openid_assertion_when_user_already_logged_in(self):
93+ # The OpenID provider responded with a negative assertion, but the
94+ # user already has a valid cookie, so we add a notification message to
95+ # the response and redirect to the starting_url specified in the
96+ # OpenID response.
97+ test_account = self.factory.makeAccount('Test account')
98+ class StubbedOpenIDCallbackViewLoggedIn(StubbedOpenIDCallbackView):
99+ account = test_account
100+ view, html = self._createViewWithResponse(
101+ test_account, response_status=FAILURE,
102+ response_msg='Server denied check_authentication',
103+ view_class=StubbedOpenIDCallbackViewLoggedIn)
104+ self.assertFalse(view.login_called)
105+ response = view.request.response
106+ self.assertEquals(httplib.TEMPORARY_REDIRECT, response.getStatus())
107+ self.assertEquals(view.request.form['starting_url'],
108+ response.getHeader('Location'))
109+ notification_msg = view.request.response.notifications[0].message
110+ expected_msg = ('Your authentication failed but you were already '
111+ 'logged into Launchpad')
112+ self.assertIn(expected_msg, notification_msg)
113+
114 def test_IAccountSet_getByOpenIDIdentifier_monkey_patched(self):
115 with IAccountSet_getByOpenIDIdentifier_monkey_patched():
116 self.assertRaises(

Subscribers

People subscribed via source and target branches

to status/vote changes: