Closed
Bug 663221
Opened 14 years ago
Closed 14 years ago
Update account-portal to the new user spec
Categories
(Cloud Services :: Server: Account Portal, defect)
Tracking
(Not tracked)
VERIFIED
FIXED
People
(Reporter: telliott, Assigned: telliott)
References
Details
Attachments
(2 files)
27.04 KB,
patch
|
jrconlin
:
review+
tarek
:
feedback+
|
Details | Diff | Splinter Review |
29.27 KB,
patch
|
jrconlin
:
review+
|
Details | Diff | Splinter Review |
new spec with the user object needs a-p changes
Assignee | ||
Comment 1•14 years ago
|
||
As a special bonus, abstracting out the reset codes made testing the rest of the forgot password flow easier.
Assignee: nobody → telliott
Attachment #538341 -
Flags: review?(jrconlin)
Attachment #538341 -
Flags: feedback?(tarek)
Assignee | ||
Updated•14 years ago
|
Comment 2•14 years ago
|
||
Comment on attachment 538341 [details] [diff] [review]
rewrites the auth bits to use the new auth module
* While I appreciate the reason, probably ought to drop old code in account.py:95..104
* probably want to use a generic email in the tests.
Attachment #538341 -
Flags: review?(jrconlin) → review+
Assignee | ||
Comment 3•14 years ago
|
||
ironically, 95...104 isn't old code. It's code that gets uncommented when pete finishes the ldap dn change.
Comment 4•14 years ago
|
||
Comment on attachment 538341 [details] [diff] [review]
rewrites the auth bits to use the new auth module
>diff -r 72248e493553 AccountPortal.spec
>--- a/AccountPortal.spec Thu Jun 02 16:11:20 2011 -0700
>+++ b/AccountPortal.spec Thu Jun 09 13:47:53 2011 -0700
>@@ -5,7 +5,7 @@
> Group: Mozilla
> License: MPL
> Packager: Toby Elliott <telliott@mozilla.com>
>-Source0: AccountPortal-1.2.tar.gz
>+Source0: AccountPortal-%{version}.tar.gz
> Requires: python26 python26-setuptools python26-webob python26-paste python26-pastedeploy python26-pastescript python26-services python26-beaker python26-memcached python26-simplejson python26-wsgi_intercept python26-beautifulsoup python26-ldap python26-pycryptopp python26-recaptcha-client python26-cef
> BuildRoot: %{_tmppath}/%{pythonname}-%{version}-%{release}-buildroot
>
>@@ -16,7 +16,7 @@
> rm -rf $RPM_BUILD_ROOT
>
> %prep
looks like something we can commit right away on its own
>-%setup -n AccountPortal-1.2
>+%setup -n AccountPortal-%{version}
>
> %build
> python2.6 setup.py build
>diff -r 72248e493553 accountportal/controllers/__init__.py
>--- a/accountportal/controllers/__init__.py Thu Jun 02 16:11:20 2011 -0700
>+++ b/accountportal/controllers/__init__.py Thu Jun 09 13:47:53 2011 -0700
>@@ -42,7 +42,7 @@
>
> from hashlib import sha256
> from time import time
>-from services.auth import get_auth
>+from services.pluginreg import load_and_configure
> from cef import log_cef
> from accountportal import logger
> from mako.lookup import TemplateLookup
>@@ -77,10 +77,15 @@
> def __init__(self, conf):
> self.config = conf
> try:
>- self.auth = get_auth(self.config)
>+ self.auth = load_and_configure(self.config, 'auth')
> except Exception, e:
> logger.error("unable to load auth. Problem? %s" % e)
> self.auth = None
>+ try:
>+ self.reset = load_and_configure(self.config, 'reset_codes')
>+ except Exception, e:
do str(e) here or you might not get the error. Also if you want to log the traceback,
use the traceback module (see how I do in services.util or services.baseapp)
>+ logger.error("unable to load reset codes. Problem? %s" % e)
>+ self.reset = None
>
> def render(self, template, **data):
> return self._lookup.get_template(template).render(**data)
>diff -r 72248e493553 accountportal/controllers/account.py
>--- a/accountportal/controllers/account.py Thu Jun 02 16:11:20 2011 -0700
>+++ b/accountportal/controllers/account.py Thu Jun 09 13:47:53 2011 -0700
>@@ -38,6 +38,7 @@
> from gettext import gettext as _
>
> from services.util import valid_email, valid_password, extract_username
>+from services.user import User
> from cef import log_cef
>
> from accountportal import logger
>@@ -82,23 +83,25 @@
> return self.render(template, **data)
>
> #because changing the email now changes the username, we need to check
>- #for collisions
>+ #for collisions - NOT YET
> new_username = extract_username(new_email)
> if self.auth.get_user_id(new_username):
> data['error'] = \
> _('The email address you specified is already in use.')
> return self.render(template, **data)
>
>- uid = beaker.get('uid')
>- if self.auth.update_email(uid, new_email, beaker.get('password')):
>+ if self.auth.update_field(request._user, beaker.get('password'),
>+ 'mail', new_email):
I agree with JR: commiting commented code smells bad. I'd remove it and introduce it later, since Hg is useful for this
>+ #self.auth.update_field(request._user, beaker.get('password'),
>+ # 'uid', extract_username(new_email)):
> data['success'] = \
> _('Your account name was succesfully changed to %s.' % new_email)
> #make sure to change our session to have the new email
> beaker['email'] = new_email
>- beaker['username'] = new_email
>+ #beaker['username'] = extract_username(new_email)
> beaker.save()
> data['email'] = new_email
>- data['username'] = new_email
>+ #data['username'] = new_email
> else:
> data['error'] = \
> _('An unknown problem ocurred. Please try again later.')
>@@ -111,7 +114,6 @@
> beaker = request.environ['beaker.session']
> data = self.get_base_data(request)
> template = 'change_password.mako'
>- uid = beaker.get('uid')
>
> data['trail'] = [[None, _('Change Password')]]
> password = request.params.get('new_password')
>@@ -132,7 +134,8 @@
> _('Please make sure your password is at least 8 characters long.')
> return self.render(template, **data)
>
>- if self.auth.update_password(uid, password, beaker.get('password')):
>+ if self.auth.update_password(request._user, beaker.get('password'),
>+ password):
> data['success'] = _('Your password was succesfully changed.')
> log_cef('Password Changed', 5,
> request.environ, self.config, data['username'],
>@@ -165,24 +168,25 @@
> return self.render(template, **data)
>
> data['crumb'] = self.generate_crumb(request)
>- uid = self.auth.authenticate_user(username, pwd)
>- if not uid:
>+ if not self.auth.authenticate_user(request._user, pwd):
> data['error'] = _('We were unable to authenticate your account.')
> return self.render(template, **data)
>
> #if this supports a sync cluster, need to purge from there
> if "sync" in self.config.get('console.modules'):
>- client = SyncClient(self.config,
>- self.auth.get_user_node(uid, False),
>- username,
>- beaker.get('password'))
>- if not client.delete_data():
>- data['alert'] = \
>- _("We were unable to delete your data on the weave node. "
>- "Don't worry, it's encrypted on the node and will be "
>- "cleaned up shortly.")
>+ self.auth.get_user_info(request._user, ['syncNode'])
>+ if request._user.get('syncNode', None):
>+ client = SyncClient(self.config,
>+ request._user['syncNode'],
>+ request._user['userName'],
>+ pwd)
>+ if not client.delete_data():
>+ data['alert'] = \
>+ _("We were unable to delete your data on the weave node. "
>+ "Don't worry, it's encrypted on the node and will be "
>+ "cleaned up shortly.")
>
>- if not self.auth.delete_user(uid, pwd):
>+ if not self.auth.delete_user(request._user, pwd):
> data['error'] = _('Deleting your account failed unexpectedly. '
> 'Please try again later.')
> return self.render(template, **data)
>diff -r 72248e493553 accountportal/controllers/console.py
>--- a/accountportal/controllers/console.py Thu Jun 02 16:11:20 2011 -0700
>+++ b/accountportal/controllers/console.py Thu Jun 09 13:47:53 2011 -0700
>@@ -35,8 +35,10 @@
> # ***** END LICENSE BLOCK *****
> from gettext import gettext as _
>
>-from services.auth import NoEmailError, InvalidCodeError
>-from services.util import valid_password, extract_username
>+from services.auth import NoEmailError
>+from services.resetcodes import AlreadySentError, InvalidCodeError
>+from services.util import (valid_password, extract_username,
>+ send_email, valid_email, filter_params)
> from cef import log_cef, AUTH_FAILURE, CAPTCHA_FAILURE
>
> from accountportal import logger
>@@ -67,58 +69,64 @@
>
> beaker = request.environ['beaker.session']
> if beaker.get('uid'):
>- request.remote_user = beaker.get('username')
>+ request._user['userName'] = beaker.get('username')
>+ request._user['userId'] = beaker.get('uid')
> return True, ''
>
> data = self.get_base_data(request)
> template = 'login.mako'
>
> if 'username' in request.POST: # trying to log in
>- username = extract_username(request.POST.get('username'))
>+ request._user['userName'] = \
>+ extract_username(request.POST.get('username'))
> pwd = request.POST.get('password')
> if not pwd:
> data['error'] = _('Password required')
> return False, self.render(template, **data)
>
>- uid = self.auth.authenticate_user(username, pwd)
>+ uid = self.auth.authenticate_user(request._user, pwd, ['mail'])
> if uid:
>- __, email = self.auth.get_user_info(uid)
> beaker['uid'] = uid
>- beaker['email'] = email
>- beaker['username'] = username
>+ beaker['email'] = request._user['mail']
>+ beaker['username'] = request._user['userName']
> beaker['password'] = pwd
> beaker.save()
>- request.remote_user = username
>+ request._user['userId'] = uid
> return True, ''
> else:
> log_cef('Authentication Failed', 5,
>- request.environ, self.config, username,
>+ request.environ, self.config, request._user['userName'],
> signature=AUTH_FAILURE)
> data['error'] = _('We were unable to log you in')
>
> return False, self.render(template, **data)
>
>+ def _render_step_1(self, request, data):
>+ # preserve it in the form if there's a problem
Here you should do this instead of these 3 lines:
data['form_username'] = request.params.get('username', '')
>+ data['form_username'] = ''
>+ if request.params.get('username', None):
>+ data['form_username'] = request.params['username']
>+ data['captcha'] = request._captcha.form()
>+ return self.render('password_reset1.mako', **data)
>+
>+
> def forgot(self, request, **args):
> """Multi-step process to retrieve a forgotten password"""
>
> data = self.get_base_data(request)
>- data['form_username'] = ''
>
> #only page with no userid is the starting one
> if not request.params.get('username'):
>- data['captcha'] = request._captcha.form()
>- return self.render('password_reset1.mako', **data)
>+ return self._render_step_1(request, data)
>
> username = extract_username(request.params['username'])
>- user_id = self.auth.get_user_id(username)
>- if username: # preserve it in the form if there's a problem
>- data['form_username'] = request.params['username']
>+ request._user['userName'] = username
>+ user_id = self.auth.get_user_id(request._user)
>
> if not user_id:
> data['error'] = \
> _('Unable to locate your account. Please check your username.')
>- data['captcha'] = request._captcha.form()
>- return self.render('password_reset1.mako', **data)
>+ return self._render_step_1(request, data)
>
> #if no reset code, time to ship them one
> if not request.params.get('key'):
>@@ -128,19 +136,39 @@
> signature=CAPTCHA_FAILURE)
> data['error'] = _('The captcha did not match. '
> 'Please try again')
>- data['captcha'] = request._captcha.form()
>- return self.render('password_reset1.mako', **data)
>+ return self._render_step_1(request, data)
>
> try:
>- if not self.auth.generate_reset_code(user_id):
>+ reset_code = self.reset.generate_reset_code(request._user, True)
>+ if not reset_code:
> data['error'] = _('Getting a reset code failed '
> 'unexpectedly. Please try again later.')
> logger.error("Could not generate a reset code")
>- return self.render('password_reset1.mako', **data)
>+ return self._render_step_1(request, data)
>+ self.auth.get_user_info(request._user, ['mail'])
>+ if not valid_email(request._user['mail']):
>+ raise NoEmailError()
>+
>+ maildata = {'forgot_url': '%s/forgot' % request.host_url,
>+ 'username': username,
>+ 'code': reset_code
>+ }
>+ body = self.render('password_reset_mail.mako', **maildata)
>+ subject = _('Resetting your Mozilla Services password')
>+ smtp = filter_params('smtp', self.config)
>+ #sender has a required position, so we can't pass it in in the
>+ #dict
>+ del smtp['sender']
>+ send_email(self.config['smtp.sender'], request._user['mail'],
>+ subject, body, **smtp)
no need for ",e"
>+ except AlreadySentError, e:
>+ #backend handled the reset code email. Keep going
>+ pass
no need for ",e"
> except NoEmailError, e:
> data['error'] = _('We do not have an email on file for this '
> 'account and cannot send you a reset code.')
>- return self.render('password_reset1.mako', **data)
>+ return self._render_step_1(request, data)
>
> return self.render('password_reset2.mako', **data)
>
>@@ -149,38 +177,47 @@
> data['key'] = code
> data['usernm'] = username
>
>+ #validate the access code
>+ #NOTE: sreg automatically returns true here, and defers code validation
>+ #until later
>+ if not self.reset.verify_reset_code(request._user, code):
>+ data['error'] = _('The reset code you submitted was '
>+ 'invalid. Please request a new one.')
>+ return self._render_step_1(request, data)
>+
> password = request.params.get('new_password')
>- if password:
>- #verify that password and confirm match
>- confirm = request.params.get('confirm_password')
>- if password != confirm:
>- data['error'] = _('The new password and confirmation do '
>- 'not match. Please try again.')
>+ if not password:
>+ #no new password, so give them the password form
>+ return self.render('password_reset3.mako', **data)
>+
>+ #verify that password and confirm match
>+ confirm = request.params.get('confirm_password')
>+ if password != confirm:
>+ data['error'] = _('The new password and confirmation do '
>+ 'not match. Please try again.')
>+ return self.render('password_reset3.mako', **data)
>+
>+ if not valid_password(username, password):
>+ data['error'] = _('The new password is not valid. '
>+ 'Please try again.')
>+ return self.render('password_reset3.mako', **data)
>+
>+ try:
>+ if not self.auth.admin_update_password(request._user, password, code):
>+ data['error'] = _('Changing the password failed. '
>+ 'Please ask for a new key and try again later')
> return self.render('password_reset3.mako', **data)
No need for ",e"
>+ except InvalidCodeError, e:
>+ data['error'] = _('The reset code you submitted was '
>+ 'invalid. Please request a new one.')
>+ return self._render_step_1(request, data)
>
>- if not valid_password(username, password):
>- data['error'] = _('The new password is not valid. '
>- 'Please try again.')
>- return self.render('password_reset3.mako', **data)
>+ log_cef('Password Changed', 5,
>+ request.environ, self.config, username,
>+ signature="PasswordReset")
>+ self.reset.clear_reset_code(request._user)
>+ return self.render('password_reset4.mako', **data)
>
>- try:
>- if not self.auth.admin_update_password(user_id, password, key=code):
>- data['error'] = _('Changing the password failed. '
>- 'Please ask for a new key and try again later')
>- return self.render('password_reset3.mako', **data)
>- except InvalidCodeError, e:
>- data['error'] = _('The reset code you submitted was '
>- 'invalid. Please request a new one.')
>- return self.render('password_reset1.mako', **data)
>-
>- log_cef('Password Changed', 5,
>- request.environ, self.config, username,
>- signature="PasswordReset")
>-
>- return self.render('password_reset4.mako', **data)
>-
>- #no new password, so give them the password form
>- return self.render('password_reset3.mako', **data)
>
> def console(self, request, **args):
> """Shows the home page. Not much to do there right now"""
>diff -r 72248e493553 accountportal/controllers/sync.py
>--- a/accountportal/controllers/sync.py Thu Jun 02 16:11:20 2011 -0700
>+++ b/accountportal/controllers/sync.py Thu Jun 09 13:47:53 2011 -0700
>@@ -38,8 +38,6 @@
> from gettext import gettext as _
> import re
>
>-from services.auth import get_auth
>-
> from accountportal import logger
> from accountportal.controllers import BaseController, get_template_lookup
> from accountportal.clients.sync import SyncClient
>@@ -91,20 +89,20 @@
> data['success'] = 1
>
> else:
>- uid = beaker.get('uid')
>- client = SyncClient(self.config,
>- self.auth.get_user_node(uid, False),
>- beaker.get('username'),
>- beaker.get('password'))
>- results = client.get_quota_used()
>+ data['quota'] = ''
>+ self.auth.get_user_info(request._user, ['syncNode'])
>+ if request._user.get('syncNode', None):
>+ client = SyncClient(self.config,
>+ request._user['syncNode'],
>+ request._user['userName'],
>+ beaker.get('password'))
>+ results = client.get_quota_used()
>
>- if results[0] is not None:
>- data['quota'] = "%s %sK" % (_('You are currently using'),
>- results[0])
>- if results[1] is not None:
>- data['quota'] += " %s %sK" % (_('out of'), results[1])
>- else:
>- data['quota'] = ''
>+ if results[0] is not None:
>+ data['quota'] = "%s %sK" % (_('You are currently using'),
>+ results[0])
>+ if results[1] is not None:
>+ data['quota'] += " %s %sK" % (_('out of'), results[1])
>
> data['crumb'] = self.generate_crumb(request)
> return self.render(template, **data)
>@@ -119,19 +117,18 @@
> data['trail'] = [[None, _('Purge Sync')]]
> purge = request.params.get('purge')
> if purge and self.check_crumb(request):
>- if self.auth is None:
>- self.auth = get_auth(self.config)
>-
>- uid = beaker.get('uid')
>- client = SyncClient(self.config,
>- self.auth.get_user_node(uid, False),
>- beaker.get('username'),
>- beaker.get('password'))
>- if not client.delete_data():
>- data['alert'] = _('We had a problem purging the data from your'
>- + ' account. Please try again later.')
>- else:
>- data['success'] = 1
>+ self.auth.get_user_info(request._user, ['syncNode'])
>+ if request._user.get('syncNode', None):
>+ client = SyncClient(self.config,
>+ request._user['syncNode'],
>+ request._user['userName'],
>+ beaker.get('password'))
>+ if not client.delete_data():
>+ data['alert'] = _('We had a problem purging the data '
>+ 'from your account. Please try again '
>+ 'later.')
>+ else:
>+ data['success'] = 1
>
> data['crumb'] = self.generate_crumb(request)
> return self.render(template, **data)
>diff -r 72248e493553 accountportal/templates/console/password_reset_mail.mako
>--- a/accountportal/templates/console/password_reset_mail.mako Thu Jun 02 16:11:20 2011 -0700
>+++ b/accountportal/templates/console/password_reset_mail.mako Thu Jun 09 13:47:53 2011 -0700
>@@ -1,6 +1,6 @@
> ${_('You asked to reset your Mozilla Services password. To do so, please click this link')}:
>
>- ${host}/console/forgot?username=${user_name | u}&key=${code |u}
>+ ${forgot_url}?username=${username | u}&key=${code |u}
>
> ${_("This will let you change your password to something new. If you didn't ask for this, don't worry, we'll keep your password safe.")}
>
>diff -r 72248e493553 accountportal/tests/base.py
>--- a/accountportal/tests/base.py Thu Jun 02 16:11:20 2011 -0700
>+++ b/accountportal/tests/base.py Thu Jun 09 13:47:53 2011 -0700
>@@ -42,7 +42,7 @@
>
> from webtest import TestApp
>
>-from services.auth import get_auth
>+from services.pluginreg import load_and_configure
> from services.tests.support import TestEnv, patch_captcha
>
> from accountportal.wsgiapp import make_app
>@@ -73,31 +73,28 @@
> return
>
> self.appdir = env.topdir
>- self.auth = get_auth(self.config)
>- self.app = TestApp(make_app(self.config))
>+ self.auth = load_and_configure(env.config, 'auth')
>+ self.reset = load_and_configure(env.config, 'reset_codes')
>+ self.app = TestApp(make_app(env.config))
> self.session = ''
>+
> # adding a user if needed
> userint = random.randint(1, 1000)
> self.username = 'test_user%d' % userint
>- self.user_id = self.auth.get_user_id(self.username)
> self.email = self.config.get('test_email',
> 'telliott+%d@mozilla.com' % userint)
> self.password = 'x' * 9
>
>- if self.user_id is None:
>- self.create_user()
>+ self.user = self.auth.create_user(self.username,
>+ self.password, self.email)
>
> def tearDown(self):
>- if self.user_id:
>- self.auth.delete_user(self.user_id, self.password)
>- self.user_id is None
>+ if self.user:
>+ self.auth.delete_user(self.user, self.password)
> cef_logs = os.path.join(self.appdir, 'test_cef.log')
> if os.path.exists(cef_logs):
> os.remove(cef_logs)
>
>- def create_user(self):
>- self.auth.create_user(self.username, self.password, self.email)
>- self.user_id = self.auth.get_user_id(self.username)
>
> def log_in(self):
> if not self.session:
>@@ -165,18 +162,47 @@
> good_req = self.app.post(test_url,
> {'username': self.username,
> 'recaptcha_challenge_field': 'foo',
>- 'recaptcha_response_field': 'bar'})
>+ 'recaptcha_response_field': 'bar'
>+ })
> assert "We have emailed a reset code" in good_req
>
>- #can't really test whether we get the email
>+ #can't really test whether we get the email, but we can get the reset
>+ #code from the db
>
>- #this test is no longer valid, since we don't verify the key at this stage
>- #bad_key_req = self.app.get(test_url, {'username': self.username,
>- # 'key': 'bad'})
>- #assert "The reset code you submitted was invalid" in bad_key_req
>+ code = self.reset.generate_reset_code(self.user, overwrite=False)
>+ good_req = self.app.post(test_url,
>+ {'username': self.username, 'key': code})
>
>- #we have no method to get the key to submit it, which makes unit
>- #testing the rest of this mostly impossible
>+
>+ old_password = self.password
>+ new_password = 'z' * 9
>+
>+ # clear the session and try to log in again
>+ self.log_in()
>+ res_in = self.app.get("/")
>+
>+ #now change the password
>+ good_req = self.app.post(test_url,
>+ {'username': self.username, 'key': code,
>+ 'new_password': new_password,
>+ 'confirm_password': new_password
>+ })
>+ assert "Your password has been successfully changed" in good_req
>+
>+ self.password = new_password
>+
>+ self.log_out()
>+ assert self.logged_out
>+
>+ res_bad = self.app.post("/", {'username': self.username,
>+ 'password': old_password})
>+ assert "We were unable to log you in" in res_bad
>+
>+ #log in with the new password
>+ self.log_in()
>+ res_in2 = self.app.get("/")
>+ assert res_in.html == res_in2.html
>+
>
> def _get_app(self):
> return self.app
>diff -r 72248e493553 accountportal/wsgiapp.py
>--- a/accountportal/wsgiapp.py Thu Jun 02 16:11:20 2011 -0700
>+++ b/accountportal/wsgiapp.py Thu Jun 09 13:47:53 2011 -0700
>@@ -46,6 +46,7 @@
> from accountportal import logger
> import accountportal.beakerpatch # NOQA
>
>+from services.user import User
> from services.util import convert_config, CatchErrorMiddleware, filter_params
> from services.captcha import ServicesCaptcha
>
>@@ -137,6 +138,9 @@
> #adding our captcha to the environment
> request._captcha = self.captcha
>
>+ #adding a user object to the environment
>+ request._user = User()
>+
> match = self.mapper.routematch(environ=request.environ)
> if match is None:
> return HTTPNotFound()
>@@ -176,8 +180,9 @@
> # result is already a Response
> response = result
>
>- if request.remote_user:
>- response.headers.add('X-Services-Username', request.remote_user)
>+ if request._user.get('userName', None):
>+ response.headers.add('X-Services-Username',
>+ request._user['userName'])
>
> response.headers.add('X-Frame-Options', 'DENY')
> return response
>diff -r 72248e493553 etc/accountportal_test.cfg
>--- a/etc/accountportal_test.cfg Thu Jun 02 16:11:20 2011 -0700
>+++ b/etc/accountportal_test.cfg Thu Jun 09 13:47:53 2011 -0700
>@@ -30,8 +30,18 @@
> timeout = 20
>
> [auth]
>-backend = sql
>+backend = services.user.sql.SQLUser
> sqluri = sqlite:////tmp/account.db
>+create_tables = True
>+
>+[nodes]
>+backend = syncnodes.admincontroller.AdminController
>+sqluri = sqlite:////tmp/account.db
>+
>+[reset_codes]
>+backend = services.resetcodes.rc_sql.ResetCodeSQL
>+sqluri = sqlite:////tmp/reset.db
>+create_tables = True
>
> [cef]
> use = true
>@@ -39,8 +49,6 @@
> vendor = mozilla
> version = 0
> device_version = 1.3
>-
>-[cef]
> product = portal
>
> [captcha]
>diff -r 72248e493553 tests.ini
>--- a/tests.ini Thu Jun 02 16:11:20 2011 -0700
>+++ b/tests.ini Thu Jun 09 13:47:53 2011 -0700
>@@ -1,6 +1,7 @@
> [DEFAULT]
> debug = True
> translogger = False
>+extends = etc/accountportal_test.cfg
>
> [server:main]
> use = egg:Paste#http
>@@ -9,7 +10,6 @@
>
> [app:main]
> use = egg:AccountPortal
>-configuration = file:%(here)s/etc/accountportal_test.cfg
>
> # Logging configuration
> [loggers]
Attachment #538341 -
Flags: feedback?(tarek) → feedback+
Assignee | ||
Comment 5•14 years ago
|
||
Attachment #541313 -
Flags: review?(jrconlin)
Comment 6•14 years ago
|
||
Comment on attachment 541313 [details] [diff] [review]
The rewritten account portal that takes advantage of our new core changes
Minor nit: Having seen this happen, I'll agree with Tarek that you want to str() any generic Exception you catch when you log it. Bad exceptions don't always render correctly.
Attachment #541313 -
Flags: review?(jrconlin) → review+
Assignee | ||
Comment 7•14 years ago
|
||
Pushed in http://hg.mozilla.org/services/account-portal/rev/9cf80e83f1a6
Note that this requires server-core v2.0+ and I've put that in setup.py to ensure it
Status: NEW → RESOLVED
Closed: 14 years ago
Resolution: --- → FIXED
Updated•14 years ago
|
Status: RESOLVED → VERIFIED
You need to log in
before you can comment on or make changes to this bug.
Description
•