From 6755f50e8e073c651bf9f26824068396bc216405 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sat, 2 Apr 2011 10:29:54 -0500 Subject: Basic authentication tools using py-bcrypt --- mediagoblin/auth/__init__.py | 0 mediagoblin/auth/lib.py | 66 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 mediagoblin/auth/__init__.py create mode 100644 mediagoblin/auth/lib.py (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/__init__.py b/mediagoblin/auth/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py new file mode 100644 index 00000000..29b955a0 --- /dev/null +++ b/mediagoblin/auth/lib.py @@ -0,0 +1,66 @@ +# GNU Mediagoblin -- federated, autonomous media hosting +# Copyright (C) 2011 Free Software Foundation, Inc +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import os + +import bcrypt + + +def bcrypt_check_password(raw_pass, stored_hash, extra_salt=None): + """ + Check to see if this password matches. + + Args: + - raw_pass: user submitted password to check for authenticity. + - stored_hash: The hash of the raw password (and possibly extra + salt) to check against + - extra_salt: (optional) If this password is with stored with a + non-database extra salt (probably in the config file) for extra + security, factor this into the check. + + Returns: + True or False depending on success. + """ + if extra_salt: + raw_pass = u"%s:%s" % (extra_salt, raw_pass) + + hashed_pass = bcrypt.hashpw(raw_pass, stored_hash) + + # Reduce risk of timing attacks by hashing again with a random + # number (thx to zooko on this advice, which I hopefully + # incorporated right.) + # + # See also: + rand_salt = bcrypt.gensalt(5) + randplus_stored_hash = bcrypt.hashpw(stored_hash, rand_salt) + randplus_hashed_pass = bcrypt.hashpw(hashed_pass, rand_salt) + + return randplus_stored_hash == randplus_hashed_pass + + +def bcrypt_gen_password_hash(raw_pass, extra_salt=None): + """ + Generate a salt for this new password. + + Args: + - raw_pass: user submitted password + - extra_salt: (optional) If this password is with stored with a + non-database extra salt + """ + if extra_salt: + raw_pass = u"%s:%s" % (extra_salt, raw_pass) + + return bcrypt.hashpw(raw_pass, bcrypt.gensalt()) -- cgit v1.2.3 From e0bc23d3700cd37926e0d95057d7cd2daab69d78 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sun, 3 Apr 2011 13:33:45 -0500 Subject: We should return a unicode object in bcrypt_gen_password_hash --- mediagoblin/auth/lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index 29b955a0..8de67d14 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -63,4 +63,4 @@ def bcrypt_gen_password_hash(raw_pass, extra_salt=None): if extra_salt: raw_pass = u"%s:%s" % (extra_salt, raw_pass) - return bcrypt.hashpw(raw_pass, bcrypt.gensalt()) + return unicode(bcrypt.hashpw(raw_pass, bcrypt.gensalt())) -- cgit v1.2.3 From 24181820162ad73823dcebf902c951200b90559b Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sun, 3 Apr 2011 13:35:18 -0500 Subject: Registering almost works right :) --- mediagoblin/auth/forms.py | 37 +++++++++++++++++++++++ mediagoblin/auth/routing.py | 11 +++++++ mediagoblin/auth/views.py | 72 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 mediagoblin/auth/forms.py create mode 100644 mediagoblin/auth/routing.py create mode 100644 mediagoblin/auth/views.py (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py new file mode 100644 index 00000000..ce786002 --- /dev/null +++ b/mediagoblin/auth/forms.py @@ -0,0 +1,37 @@ +# GNU Mediagoblin -- federated, autonomous media hosting +# Copyright (C) 2011 Free Software Foundation, Inc +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import wtforms + + +class RegistrationForm(wtforms.Form): + username = wtforms.TextField( + 'Username', + [wtforms.validators.Required(), + wtforms.validators.Length(min=3, max=30), + wtforms.validators.Regexp(r'^\w+$')]) + password = wtforms.TextField( + 'Password', + [wtforms.validators.Required(), + wtforms.validators.Length(min=8, max=30), + wtforms.validators.EqualTo('confirm_password')]) + confirm_password = wtforms.TextField( + 'Confirm password', + [wtforms.validators.Required()]) + email = wtforms.TextField( + 'Email address', + [wtforms.validators.Required(), + wtforms.validators.Email()]) diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py new file mode 100644 index 00000000..5b604fdd --- /dev/null +++ b/mediagoblin/auth/routing.py @@ -0,0 +1,11 @@ +from routes.route import Route + +auth_routes = [ + Route('mediagoblin.auth.register', '/register/', + controller='mediagoblin.auth.views:register'), + Route('mediagoblin.auth.register_success', '/register/success/', + controller='mediagoblin.auth.views:register_success'), + Route('mediagoblin.auth.login', '/login/', + controller='mediagoblin.auth.views:login'), + Route('mediagoblin.auth.logout', '/logout/', + controller='mediagoblin.auth.views:logout')] diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py new file mode 100644 index 00000000..d970679b --- /dev/null +++ b/mediagoblin/auth/views.py @@ -0,0 +1,72 @@ +# GNU Mediagoblin -- federated, autonomous media hosting +# Copyright (C) 2011 Free Software Foundation, Inc +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + + +from webob import Response, exc + +from mediagoblin.auth import lib as auth_lib +from mediagoblin.auth import forms as auth_forms + + +def register(request): + """ + Your classic registration view! + """ + register_form = auth_forms.RegistrationForm(request.POST) + + if request.method == 'POST' and register_form.validate(): + # TODO: Make sure the user doesn't exist already + users_with_username = \ + request.db.User.find({'username': request.POST['username']}).count() + + if users_with_username: + register_form.username.errors.append( + u'Sorry, a user with that name already exists.') + + else: + # Create the user + entry = request.db.User() + entry['username'] = request.POST['username'] + entry['email'] = request.POST['email'] + entry['pw_hash'] = auth_lib.bcrypt_gen_password_hash( + request.POST['password']) + entry.save(validate=True) + + # TODO: Send email authentication request + + # Redirect to register_success + return exc.HTTPTemporaryRedirect( + location=request.urlgen("mediagoblin.auth.register_success")) + + # render + template = request.template_env.get_template( + 'mediagoblin/auth/register.html') + return Response( + template.render( + {'request': request, + 'register_form': register_form})) + + +def register_success(request): + template = request.template_env.get_template( + 'mediagoblin/auth/register_success.html') + return Response( + template.render( + {'request': request})) + + +def login(): + pass -- cgit v1.2.3 From 73cb7b8efccd5f220de04005e3b933018f8c227c Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sun, 3 Apr 2011 14:58:51 -0500 Subject: Return an HTTPFound, not HTTPTemporaryRedirect --- mediagoblin/auth/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index d970679b..d60e9157 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -48,7 +48,7 @@ def register(request): # TODO: Send email authentication request # Redirect to register_success - return exc.HTTPTemporaryRedirect( + return exc.HTTPFound( location=request.urlgen("mediagoblin.auth.register_success")) # render -- cgit v1.2.3 From f5def6fe239f0f1b2dabfe122ca8b3b51aabb6d3 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sun, 3 Apr 2011 15:02:06 -0500 Subject: Use the passwordfield for password fields, obviously ;o --- mediagoblin/auth/forms.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index ce786002..86d82a61 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -23,12 +23,12 @@ class RegistrationForm(wtforms.Form): [wtforms.validators.Required(), wtforms.validators.Length(min=3, max=30), wtforms.validators.Regexp(r'^\w+$')]) - password = wtforms.TextField( + password = wtforms.PasswordField( 'Password', [wtforms.validators.Required(), - wtforms.validators.Length(min=8, max=30), + wtforms.validators.Length(min=6, max=30), wtforms.validators.EqualTo('confirm_password')]) - confirm_password = wtforms.TextField( + confirm_password = wtforms.PasswordField( 'Confirm password', [wtforms.validators.Required()]) email = wtforms.TextField( -- cgit v1.2.3 From c15c9843b452a1c6468f8c0d1b2f358eb31a1e10 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sun, 3 Apr 2011 15:31:16 -0500 Subject: Added a fake_login_attempt utility. --- mediagoblin/auth/lib.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index 8de67d14..5db4982b 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -16,7 +16,7 @@ import os -import bcrypt +import random def bcrypt_check_password(raw_pass, stored_hash, extra_salt=None): @@ -64,3 +64,20 @@ def bcrypt_gen_password_hash(raw_pass, extra_salt=None): raw_pass = u"%s:%s" % (extra_salt, raw_pass) return unicode(bcrypt.hashpw(raw_pass, bcrypt.gensalt())) + + +def fake_login_attempt(): + """ + Pretend we're trying to login. + + Nothing actually happens here, we're just trying to take up some + time. + """ + rand_salt = bcrypt.gensalt(5) + + hashed_pass = bcrypt.hashpw(str(random.random()), rand_salt) + + randplus_stored_hash = bcrypt.hashpw(str(random.random()), rand_salt) + randplus_hashed_pass = bcrypt.hashpw(hashed_pass, rand_salt) + + randplus_stored_hash == randplus_hashed_pass -- cgit v1.2.3 From 692fd1c981afcfb75fdebe9018d5a63d6e94e461 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sun, 3 Apr 2011 16:32:01 -0500 Subject: starting to write login code --- mediagoblin/auth/views.py | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index d60e9157..cbf7c816 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -68,5 +68,39 @@ def register_success(request): {'request': request})) -def login(): - pass +def login(request): + login_form = auth_forms.LoginForm(request.POST) + + if request.method == 'POST' and login_form.validate(): + #try: + user = request.db.User.find_one( + {'username': request.POST['username']}) + + if user.check_login(request.POST['password']): + # set up login in session + request.session['user_id'] = unicode(user['_id']) + + import pdb + pdb.set_trace() + + + else: + # Prevent detecting who's on this system by testing login + # attempt timings + auth_lib.fake_login_attempt() + + # render + template = request.template_env.get_template( + 'mediagoblin/auth/login.html') + return Response( + template.render( + {'request': request, + 'login_form': login_form})) + + +def logout(request): + template = request.template_env.get_template( + 'mediagoblin/auth/logout.html') + return Response( + template.render( + {'request': request})) -- cgit v1.2.3 From 51479a1d22a15744fecb8eddb367ab1a8dce8328 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sun, 3 Apr 2011 16:37:15 -0500 Subject: Clarified documentation on fake_login_attempt and restored bcrypt import --- mediagoblin/auth/lib.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index 5db4982b..907ba200 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -15,9 +15,10 @@ # along with this program. If not, see . import os - import random +import bcrypt + def bcrypt_check_password(raw_pass, stored_hash, extra_salt=None): """ @@ -71,7 +72,9 @@ def fake_login_attempt(): Pretend we're trying to login. Nothing actually happens here, we're just trying to take up some - time. + time, approximately the same amount of time as + bcrypt_check_password, so as to avoid figuring out what users are + on the system by intentionally faking logins a bunch of times. """ rand_salt = bcrypt.gensalt(5) -- cgit v1.2.3 From a37767172b7c67dbc35211c9d57dc69d1b1c783f Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sun, 3 Apr 2011 17:05:30 -0500 Subject: Logins seem to work. --- mediagoblin/auth/forms.py | 10 ++++++++++ mediagoblin/auth/views.py | 21 +++++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index 86d82a61..33403544 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -35,3 +35,13 @@ class RegistrationForm(wtforms.Form): 'Email address', [wtforms.validators.Required(), wtforms.validators.Email()]) + + +class LoginForm(wtforms.Form): + username = wtforms.TextField( + 'Username', + [wtforms.validators.Required(), + wtforms.validators.Regexp(r'^\w+$')]) + password = wtforms.PasswordField( + 'Password', + [wtforms.validators.Required()]) diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index cbf7c816..16588a5b 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -69,8 +69,15 @@ def register_success(request): def login(request): + """ + Mediagoblin login view. + + If you provide the POST with 'next', it'll redirect to that view. + """ login_form = auth_forms.LoginForm(request.POST) + login_failed = False + if request.method == 'POST' and login_form.validate(): #try: user = request.db.User.find_one( @@ -79,15 +86,19 @@ def login(request): if user.check_login(request.POST['password']): # set up login in session request.session['user_id'] = unicode(user['_id']) + request.session.save() - import pdb - pdb.set_trace() - + if request.POST.has_key('next'): + return exc.HTTPFound(location=request.POST['next']) + else: + return exc.HTTPFound( + location=request.urlgen("index")) else: # Prevent detecting who's on this system by testing login # attempt timings auth_lib.fake_login_attempt() + login_failed = True # render template = request.template_env.get_template( @@ -95,7 +106,9 @@ def login(request): return Response( template.render( {'request': request, - 'login_form': login_form})) + 'login_form': login_form, + 'next': request.GET.get('next') or request.POST.get('next'), + 'login_failed': login_failed})) def logout(request): -- cgit v1.2.3 From b97232fa2f8f5fbf5c1999c348a3cae66acf4834 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sun, 3 Apr 2011 18:23:40 -0500 Subject: Working logout function --- mediagoblin/auth/views.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 16588a5b..71c2d7a9 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -112,8 +112,8 @@ def login(request): def logout(request): - template = request.template_env.get_template( - 'mediagoblin/auth/logout.html') - return Response( - template.render( - {'request': request})) + # Maybe deleting the user_id parameter would be enough? + request.session.delete() + + return exc.HTTPFound( + location=request.urlgen("index")) -- cgit v1.2.3 From d193896315ea3729759fa92e227c21073f4d4568 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sun, 3 Apr 2011 18:28:17 -0500 Subject: Also handle when there is no such user --- mediagoblin/auth/views.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 71c2d7a9..03c31576 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -79,11 +79,10 @@ def login(request): login_failed = False if request.method == 'POST' and login_form.validate(): - #try: user = request.db.User.find_one( {'username': request.POST['username']}) - if user.check_login(request.POST['password']): + if user and user.check_login(request.POST['password']): # set up login in session request.session['user_id'] = unicode(user['_id']) request.session.save() -- cgit v1.2.3 From b058cf15f0ef79fcc4d24f2952e5d55ff0be46cc Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sun, 3 Apr 2011 18:32:29 -0500 Subject: We should use one instead of find_one to really make sure there's only one such user in the database --- mediagoblin/auth/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 03c31576..d56dfa43 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -79,7 +79,7 @@ def login(request): login_failed = False if request.method == 'POST' and login_form.validate(): - user = request.db.User.find_one( + user = request.db.User.one( {'username': request.POST['username']}) if user and user.check_login(request.POST['password']): -- cgit v1.2.3 From 146ad23e9b651d71cbdddf5be76a28ed5cb60353 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sun, 3 Apr 2011 18:58:23 -0500 Subject: Herp derp GPL notice blocks should even be on routing. --- mediagoblin/auth/routing.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index 5b604fdd..e304de9b 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -1,3 +1,19 @@ +# GNU Mediagoblin -- federated, autonomous media hosting +# Copyright (C) 2011 Free Software Foundation, Inc +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + from routes.route import Route auth_routes = [ -- cgit v1.2.3 From 8e1e744d27fbc887c6d9ce6e937848a25275ed6c Mon Sep 17 00:00:00 2001 From: Will Kahn-Greene Date: Wed, 13 Apr 2011 10:04:30 -0400 Subject: Changes Mediagoblin -> MediaGoblin. --- mediagoblin/auth/__init__.py | 15 +++++++++++++++ mediagoblin/auth/forms.py | 2 +- mediagoblin/auth/lib.py | 2 +- mediagoblin/auth/routing.py | 2 +- mediagoblin/auth/views.py | 4 ++-- 5 files changed, 20 insertions(+), 5 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/__init__.py b/mediagoblin/auth/__init__.py index e69de29b..c129cbf8 100644 --- a/mediagoblin/auth/__init__.py +++ b/mediagoblin/auth/__init__.py @@ -0,0 +1,15 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011 Free Software Foundation, Inc +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index 33403544..db8aaceb 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -1,4 +1,4 @@ -# GNU Mediagoblin -- federated, autonomous media hosting +# GNU MediaGoblin -- federated, autonomous media hosting # Copyright (C) 2011 Free Software Foundation, Inc # # This program is free software: you can redistribute it and/or modify diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index 907ba200..7cf021bc 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -1,4 +1,4 @@ -# GNU Mediagoblin -- federated, autonomous media hosting +# GNU MediaGoblin -- federated, autonomous media hosting # Copyright (C) 2011 Free Software Foundation, Inc # # This program is free software: you can redistribute it and/or modify diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index e304de9b..92f19371 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -1,4 +1,4 @@ -# GNU Mediagoblin -- federated, autonomous media hosting +# GNU MediaGoblin -- federated, autonomous media hosting # Copyright (C) 2011 Free Software Foundation, Inc # # This program is free software: you can redistribute it and/or modify diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index d56dfa43..aadde32f 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -1,4 +1,4 @@ -# GNU Mediagoblin -- federated, autonomous media hosting +# GNU MediaGoblin -- federated, autonomous media hosting # Copyright (C) 2011 Free Software Foundation, Inc # # This program is free software: you can redistribute it and/or modify @@ -70,7 +70,7 @@ def register_success(request): def login(request): """ - Mediagoblin login view. + MediaGoblin login view. If you provide the POST with 'next', it'll redirect to that view. """ -- cgit v1.2.3 From 574d1511d6a111efd4c6da78ef03593e4bcb2056 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sat, 23 Apr 2011 12:54:11 -0500 Subject: Probably better to request.POST.get? --- mediagoblin/auth/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index aadde32f..15e33e17 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -87,7 +87,7 @@ def login(request): request.session['user_id'] = unicode(user['_id']) request.session.save() - if request.POST.has_key('next'): + if request.POST.get('next'): return exc.HTTPFound(location=request.POST['next']) else: return exc.HTTPFound( -- cgit v1.2.3 From db1a438f3e6f8c5c8cec20b9326a21baf4579306 Mon Sep 17 00:00:00 2001 From: Joar Wandborg Date: Tue, 3 May 2011 19:49:39 +0200 Subject: Added functionality to support user email verification, email = TBD, verification = done. Signed-off-by: Joar Wandborg --- mediagoblin/auth/routing.py | 4 +++- mediagoblin/auth/views.py | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index 92f19371..59762840 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -24,4 +24,6 @@ auth_routes = [ Route('mediagoblin.auth.login', '/login/', controller='mediagoblin.auth.views:login'), Route('mediagoblin.auth.logout', '/logout/', - controller='mediagoblin.auth.views:logout')] + controller='mediagoblin.auth.views:logout'), + Route('mediagoblin.auth.verify_email', '/verify_email/', + controller='mediagoblin.auth.views:verify_email')] diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 15e33e17..dfb6899f 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -116,3 +116,26 @@ def logout(request): return exc.HTTPFound( location=request.urlgen("index")) + +def verify_email(request): + import bson.objectid + user = request.db.User.find_one( + {'_id': bson.objectid.ObjectId( unicode( request.GET.get('userid') ) )}) + + verification_successful = bool + + if user and user['verification_key'] == unicode( request.GET.get('token') ): + user['status'] = u'active' + user['email_verified'] = True + verification_successful = True + user.save() + else: + verification_successful = False + + template = request.template_env.get_template( + 'mediagoblin/auth/verify_email.html') + return Response( + template.render( + {'request': request, + 'user': user, + 'verification_successful': verification_successful})) -- cgit v1.2.3 From 5c42a82c5ad4fa410219084a6f43bdc414369114 Mon Sep 17 00:00:00 2001 From: Joar Wandborg Date: Sat, 7 May 2011 03:08:09 +0200 Subject: Added functionality to send out verification email upon successful registration Signed-off-by: Joar Wandborg --- mediagoblin/auth/views.py | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index dfb6899f..79c09f5b 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -19,6 +19,7 @@ from webob import Response, exc from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms +from mediagoblin.util import send_email def register(request): @@ -44,9 +45,28 @@ def register(request): entry['pw_hash'] = auth_lib.bcrypt_gen_password_hash( request.POST['password']) entry.save(validate=True) - - # TODO: Send email authentication request - + + # TODO: Move this setting to a better place + EMAIL_SENDER_ADDRESS = 'mediagoblin@fakehost' + + ''' TODO Index - Regarding sending of verification email + 1. There is no error handling in place + 2. Due to the distributed nature of GNU MediaGoblin, we should find a way to send some additional information about the specific GNU MediaGoblin instance in the subject line. For example "GNU MediaGoblin @ Wandborg - [...]". + 3. The verification link generation does not detect and adapt to access via the HTTPS protocol. + ''' + + # TODO (1) + send_email( + EMAIL_SENDER_ADDRESS, + entry['email'], + 'GNU MediaGoblin - Verify email', # TODO (2) + 'http://{host}{uri}?userid={userid}&token={verification_key}'.format( # TODO (3) + host = request.host, + uri = request.urlgen('mediagoblin.auth.verify_email'), + userid = unicode( entry['_id'] ), + verification_key = entry['verification_key'] + )) + # Redirect to register_success return exc.HTTPFound( location=request.urlgen("mediagoblin.auth.register_success")) -- cgit v1.2.3 From 4c093e85c7457e989b22b5274f240e3ccfdab210 Mon Sep 17 00:00:00 2001 From: Joar Wandborg Date: Sun, 8 May 2011 00:55:57 +0200 Subject: Made changes according to http://bugs.foocorp.net/issues/271#note-7 Signed-off-by: Joar Wandborg --- mediagoblin/auth/views.py | 48 ++++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 19 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 79c09f5b..7468def0 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -20,6 +20,7 @@ from webob import Response, exc from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms from mediagoblin.util import send_email +from mediagoblin import globals as mgoblin_globals def register(request): @@ -49,23 +50,26 @@ def register(request): # TODO: Move this setting to a better place EMAIL_SENDER_ADDRESS = 'mediagoblin@fakehost' - ''' TODO Index - Regarding sending of verification email - 1. There is no error handling in place - 2. Due to the distributed nature of GNU MediaGoblin, we should find a way to send some additional information about the specific GNU MediaGoblin instance in the subject line. For example "GNU MediaGoblin @ Wandborg - [...]". - 3. The verification link generation does not detect and adapt to access via the HTTPS protocol. - ''' - - # TODO (1) - send_email( - EMAIL_SENDER_ADDRESS, - entry['email'], - 'GNU MediaGoblin - Verify email', # TODO (2) - 'http://{host}{uri}?userid={userid}&token={verification_key}'.format( # TODO (3) - host = request.host, - uri = request.urlgen('mediagoblin.auth.verify_email'), - userid = unicode( entry['_id'] ), - verification_key = entry['verification_key'] - )) + email_template = request.template_env.get_template( + 'mediagoblin/auth/verification_email.txt') + + # TODO: There is no error handling in place + send_email( + mgoblin_globals.email_sender_address, + list(entry['email']), + # TODO + # Due to the distributed nature of GNU MediaGoblin, we should + # find a way to send some additional information about the + # specific GNU MediaGoblin instance in the subject line. For + # example "GNU MediaGoblin @ Wandborg - [...]". + 'GNU MediaGoblin - Verify email', + email_template.render( + username=entry['username'], + verification_url='http://{host}{uri}?userid={userid}&token={verification_key}'.format( + host=request.host, + uri=request.urlgen('mediagoblin.auth.verify_email'), + userid=unicode(entry['_id']), + verification_key=entry['verification_key']))) # Redirect to register_success return exc.HTTPFound( @@ -138,13 +142,19 @@ def logout(request): location=request.urlgen("index")) def verify_email(request): + """ + Email verification view + + validates GET parameters against database and unlocks the user account, if + you are lucky :) + """ import bson.objectid user = request.db.User.find_one( - {'_id': bson.objectid.ObjectId( unicode( request.GET.get('userid') ) )}) + {'_id': bson.objectid.ObjectId(unicode(request.GET.get('userid')))}) verification_successful = bool - if user and user['verification_key'] == unicode( request.GET.get('token') ): + if user and user['verification_key'] == unicode(request.GET.get('token')): user['status'] = u'active' user['email_verified'] = True verification_successful = True -- cgit v1.2.3 From 4942b63711e53162a0ae5e7e5fdfd902df4e5e66 Mon Sep 17 00:00:00 2001 From: Joar Wandborg Date: Sun, 8 May 2011 01:58:58 +0200 Subject: Removed unused variable Signed-off-by: Joar Wandborg --- mediagoblin/auth/views.py | 3 --- 1 file changed, 3 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 7468def0..3ef1e75f 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -47,9 +47,6 @@ def register(request): request.POST['password']) entry.save(validate=True) - # TODO: Move this setting to a better place - EMAIL_SENDER_ADDRESS = 'mediagoblin@fakehost' - email_template = request.template_env.get_template( 'mediagoblin/auth/verification_email.txt') -- cgit v1.2.3 From 3eae207c54b6c8fa4c2e122403b4462d93b8b713 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sat, 7 May 2011 22:44:37 -0500 Subject: [to_email] rather than list(to_email) which makes a nasty series like ['e','m','a','i','l'] --- mediagoblin/auth/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 3ef1e75f..c3d24c74 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -53,7 +53,7 @@ def register(request): # TODO: There is no error handling in place send_email( mgoblin_globals.email_sender_address, - list(entry['email']), + [entry['email']], # TODO # Due to the distributed nature of GNU MediaGoblin, we should # find a way to send some additional information about the -- cgit v1.2.3 From ce72a1bb15f421725696cc3eea28b94de098f8f2 Mon Sep 17 00:00:00 2001 From: Jakob Kramer Date: Sun, 29 May 2011 19:15:46 +0200 Subject: this should fix #354 --- mediagoblin/auth/views.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index c3d24c74..8775d4c4 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -14,6 +14,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import re from webob import Response, exc @@ -31,8 +32,11 @@ def register(request): if request.method == 'POST' and register_form.validate(): # TODO: Make sure the user doesn't exist already + users_with_username = \ - request.db.User.find({'username': request.POST['username']}).count() + request.db.User.find({ + 'username': request.POST['username'].lower() + }).count() if users_with_username: register_form.username.errors.append( @@ -41,7 +45,8 @@ def register(request): else: # Create the user entry = request.db.User() - entry['username'] = request.POST['username'] + entry['username'] = request.POST['username'].lower() + entry['username_repr'] = request.POST['username'] entry['email'] = request.POST['email'] entry['pw_hash'] = auth_lib.bcrypt_gen_password_hash( request.POST['password']) @@ -61,7 +66,7 @@ def register(request): # example "GNU MediaGoblin @ Wandborg - [...]". 'GNU MediaGoblin - Verify email', email_template.render( - username=entry['username'], + username=entry['username_repr'], verification_url='http://{host}{uri}?userid={userid}&token={verification_key}'.format( host=request.host, uri=request.urlgen('mediagoblin.auth.verify_email'), @@ -101,7 +106,7 @@ def login(request): if request.method == 'POST' and login_form.validate(): user = request.db.User.one( - {'username': request.POST['username']}) + {'username': request.POST['username'].lower()}) if user and user.check_login(request.POST['password']): # set up login in session -- cgit v1.2.3 From ff6b9f7279d7ee2efceae933da43f4a9b6459465 Mon Sep 17 00:00:00 2001 From: Jakob Kramer Date: Sun, 29 May 2011 19:17:44 +0200 Subject: don't import 're' --- mediagoblin/auth/views.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 8775d4c4..cf71be77 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -14,8 +14,6 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -import re - from webob import Response, exc from mediagoblin.auth import lib as auth_lib -- cgit v1.2.3 From db5912e358043c90194c6409fa09ab07d16df4c3 Mon Sep 17 00:00:00 2001 From: Jakob Kramer Date: Sun, 29 May 2011 19:49:25 +0200 Subject: remove all 'username_repr' stuff --- mediagoblin/auth/views.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index cf71be77..6b5ce88c 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -44,7 +44,6 @@ def register(request): # Create the user entry = request.db.User() entry['username'] = request.POST['username'].lower() - entry['username_repr'] = request.POST['username'] entry['email'] = request.POST['email'] entry['pw_hash'] = auth_lib.bcrypt_gen_password_hash( request.POST['password']) @@ -64,7 +63,7 @@ def register(request): # example "GNU MediaGoblin @ Wandborg - [...]". 'GNU MediaGoblin - Verify email', email_template.render( - username=entry['username_repr'], + username=entry['username'], verification_url='http://{host}{uri}?userid={userid}&token={verification_key}'.format( host=request.host, uri=request.urlgen('mediagoblin.auth.verify_email'), -- cgit v1.2.3 From 28afb47ca82b0857aad546ef4cbf869de1ca95a5 Mon Sep 17 00:00:00 2001 From: Aleksandar Micovic Date: Mon, 30 May 2011 23:51:30 -0400 Subject: Added a temporary verification page informing the user they need to authenticate. --- mediagoblin/auth/routing.py | 4 +++- mediagoblin/auth/views.py | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index 59762840..9544b165 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -26,4 +26,6 @@ auth_routes = [ Route('mediagoblin.auth.logout', '/logout/', controller='mediagoblin.auth.views:logout'), Route('mediagoblin.auth.verify_email', '/verify_email/', - controller='mediagoblin.auth.views:verify_email')] + controller='mediagoblin.auth.views:verify_email'), + Route('mediagoblin.auth.verify_email_notice', '/verification_required/', + controller='mediagoblin.auth.views:verify_email_notice')] diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 6b5ce88c..edac74a8 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -168,3 +168,18 @@ def verify_email(request): {'request': request, 'user': user, 'verification_successful': verification_successful})) + +def verify_email_notice(request): + """ + Verify warning view. + + When the user tries to do some action that requires their account + to be verified beforehand, this view is called upon! + """ + + template = request.template_env.get_template( + 'mediagoblin/auth/verification_needed.html') + return Response( + template.render( + {'request': request})) + -- cgit v1.2.3 From b93a6a229e1c7a7eef76e8322104912378f79a96 Mon Sep 17 00:00:00 2001 From: Aleksandar Micovic Date: Tue, 31 May 2011 17:14:23 -0400 Subject: Added the ability to regenerate a verification key. --- mediagoblin/auth/routing.py | 4 +++- mediagoblin/auth/views.py | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index 9544b165..069e3019 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -28,4 +28,6 @@ auth_routes = [ Route('mediagoblin.auth.verify_email', '/verify_email/', controller='mediagoblin.auth.views:verify_email'), Route('mediagoblin.auth.verify_email_notice', '/verification_required/', - controller='mediagoblin.auth.views:verify_email_notice')] + controller='mediagoblin.auth.views:verify_email_notice'), + Route('mediagoblin.auth.resend_verification', '/resend_verification/', + controller='mediagoblin.auth.views:resend_activation')] diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index edac74a8..22fdd46b 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -183,3 +183,44 @@ def verify_email_notice(request): template.render( {'request': request})) +def resend_activation(request): + """ + The reactivation view + + Resend the activation email. + """ + + request.user.generate_new_verification_key() + + # Copied shamelessly from the register view above. + + email_template = request.template_env.get_template( + 'mediagoblin/auth/verification_email.txt') + + # TODO: There is no error handling in place + send_email( + mgoblin_globals.email_sender_address, + [request.user['email']], + # TODO + # Due to the distributed nature of GNU MediaGoblin, we should + # find a way to send some additional information about the + # specific GNU MediaGoblin instance in the subject line. For + # example "GNU MediaGoblin @ Wandborg - [...]". + 'GNU MediaGoblin - Verify email', + email_template.render( + username=request.user['username'], + verification_url='http://{host}{uri}?userid={userid}&token={verification_key}'.format( + host=request.host, + uri=request.urlgen('mediagoblin.auth.verify_email'), + userid=unicode(request.user['_id']), + verification_key=request.user['verification_key']))) + + + # TODO: For now, we use the successful registration page until we get a + # proper messaging system. + + template = request.template_env.get_template( + 'mediagoblin/auth/register_success.html') + return exc.HTTPFound( + location=request.urlgen('mediagoblin.auth.register_success')) + -- cgit v1.2.3 From 5866d1a8fbe31709fe21b2c830f7ee3eab7b3775 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Tue, 31 May 2011 19:29:36 -0500 Subject: Give a "proper" view for resending verification email --- mediagoblin/auth/routing.py | 5 ++++- mediagoblin/auth/views.py | 15 +++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index 069e3019..a8909fbb 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -30,4 +30,7 @@ auth_routes = [ Route('mediagoblin.auth.verify_email_notice', '/verification_required/', controller='mediagoblin.auth.views:verify_email_notice'), Route('mediagoblin.auth.resend_verification', '/resend_verification/', - controller='mediagoblin.auth.views:resend_activation')] + controller='mediagoblin.auth.views:resend_activation'), + Route('mediagoblin.auth.resend_verification_success', + '/resend_verification_success/', + controller='mediagoblin.auth.views:resend_activation_success')] diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 22fdd46b..15cd65e5 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -140,6 +140,7 @@ def logout(request): return exc.HTTPFound( location=request.urlgen("index")) + def verify_email(request): """ Email verification view @@ -183,6 +184,7 @@ def verify_email_notice(request): template.render( {'request': request})) + def resend_activation(request): """ The reactivation view @@ -215,12 +217,13 @@ def resend_activation(request): userid=unicode(request.user['_id']), verification_key=request.user['verification_key']))) + return exc.HTTPFound( + location=request.urlgen('mediagoblin.auth.resend_verification_success')) - # TODO: For now, we use the successful registration page until we get a - # proper messaging system. +def resend_activation_success(request): template = request.template_env.get_template( - 'mediagoblin/auth/register_success.html') - return exc.HTTPFound( - location=request.urlgen('mediagoblin.auth.register_success')) - + 'mediagoblin/auth/resent_verification_email.html') + return Response( + template.render( + {'request': request})) -- cgit v1.2.3 From 73a1bc85f1beb257169c777452eb878fa7e684a1 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Tue, 31 May 2011 19:31:23 -0500 Subject: Moving import to outside of this function --- mediagoblin/auth/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 15cd65e5..906d6f13 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -14,6 +14,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import bson.objectid from webob import Response, exc from mediagoblin.auth import lib as auth_lib @@ -148,7 +149,6 @@ def verify_email(request): validates GET parameters against database and unlocks the user account, if you are lucky :) """ - import bson.objectid user = request.db.User.find_one( {'_id': bson.objectid.ObjectId(unicode(request.GET.get('userid')))}) -- cgit v1.2.3 From 155f24f9f5ac1c944addddf84c7a129d55f63263 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Tue, 31 May 2011 19:37:28 -0500 Subject: If a user doesn't provide a userid and a token to the verify_email function, might as well 404 --- mediagoblin/auth/views.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 906d6f13..4ccd3d86 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -149,12 +149,16 @@ def verify_email(request): validates GET parameters against database and unlocks the user account, if you are lucky :) """ + # If we don't have userid and token parameters, we can't do anything; 404 + if not request.GET.has_key('userid') or not request.GET.has_key('token'): + return exc.HTTPNotFound() + user = request.db.User.find_one( - {'_id': bson.objectid.ObjectId(unicode(request.GET.get('userid')))}) + {'_id': bson.objectid.ObjectId(unicode(request.GET['userid']))}) verification_successful = bool - if user and user['verification_key'] == unicode(request.GET.get('token')): + if user and user['verification_key'] == unicode(request.GET['token']): user['status'] = u'active' user['email_verified'] = True verification_successful = True -- cgit v1.2.3 From e0f8487005f4e9adca41648d35bb8dc6db850032 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Thu, 2 Jun 2011 08:47:30 -0500 Subject: Elrond put that ObjectId thing in the db.util module and wants us to use that one ;) --- mediagoblin/auth/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 4ccd3d86..0c125544 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -14,9 +14,9 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -import bson.objectid from webob import Response, exc +from mediagoblin.db.util import ObjectId from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms from mediagoblin.util import send_email @@ -154,7 +154,7 @@ def verify_email(request): return exc.HTTPNotFound() user = request.db.User.find_one( - {'_id': bson.objectid.ObjectId(unicode(request.GET['userid']))}) + {'_id': ObjectId(unicode(request.GET['userid']))}) verification_successful = bool -- cgit v1.2.3 From a77d952aa6659f0291f856495b18a43dd7e28508 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Thu, 2 Jun 2011 09:02:13 -0500 Subject: No need for a method for generating the verification key as a method on the class, can just do that in the view --- mediagoblin/auth/views.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 0c125544..e9d75f8b 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import uuid + from webob import Response, exc from mediagoblin.db.util import ObjectId @@ -195,8 +197,8 @@ def resend_activation(request): Resend the activation email. """ - - request.user.generate_new_verification_key() + request.user['verification_key'] = unicode(uuid.uuid4()) + request.user.save() # Copied shamelessly from the register view above. -- cgit v1.2.3 From f80cdc586840f845b1163e935588d2810d295793 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Thu, 2 Jun 2011 16:04:17 -0500 Subject: No reason for 'verification_successful = bool' here. --- mediagoblin/auth/views.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index e9d75f8b..948db188 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -158,8 +158,6 @@ def verify_email(request): user = request.db.User.find_one( {'_id': ObjectId(unicode(request.GET['userid']))}) - verification_successful = bool - if user and user['verification_key'] == unicode(request.GET['token']): user['status'] = u'active' user['email_verified'] = True -- cgit v1.2.3 From 02d80437d1cdda5b2a8596d024aafa8b286cb360 Mon Sep 17 00:00:00 2001 From: Aleksandar Micovic Date: Thu, 2 Jun 2011 21:07:37 -0400 Subject: Refactored the sending of verification emails. --- mediagoblin/auth/lib.py | 34 ++++++++++++++++++++++++++++++++ mediagoblin/auth/views.py | 50 +++++------------------------------------------ 2 files changed, 39 insertions(+), 45 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index 7cf021bc..dc5f9941 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -19,6 +19,9 @@ import random import bcrypt +from mediagoblin.util import send_email +from mediagoblin import globals as mgoblin_globals + def bcrypt_check_password(raw_pass, stored_hash, extra_salt=None): """ @@ -84,3 +87,34 @@ def fake_login_attempt(): randplus_hashed_pass = bcrypt.hashpw(hashed_pass, rand_salt) randplus_stored_hash == randplus_hashed_pass + + +def send_verification_email(user, request): + """ + Send the verification email to users to activate their accounts. + + Args: + - user: a user object + - request: the request + """ + + email_template = request.template_env.get_template( + 'mediagoblin/auth/verification_email.txt') + + # TODO: There is no error handling in place + send_email( + mgoblin_globals.email_sender_address, + [user['email']], + # TODO + # Due to the distributed nature of GNU MediaGoblin, we should + # find a way to send some additional information about the + # specific GNU MediaGoblin instance in the subject line. For + # example "GNU MediaGoblin @ Wandborg - [...]". + 'GNU MediaGoblin - Verify your email!', + email_template.render( + username=user['username'], + verification_url='http://{host}{uri}?userid={userid}&token={verification_key}'.format( + host=request.host, + uri=request.urlgen('mediagoblin.auth.verify_email'), + userid=unicode(user['_id']), + verification_key=user['verification_key']))) diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 948db188..e4f1a7b1 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -21,8 +21,7 @@ from webob import Response, exc from mediagoblin.db.util import ObjectId from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms -from mediagoblin.util import send_email -from mediagoblin import globals as mgoblin_globals +from mediagoblin.auth.lib import send_verification_email def register(request): @@ -52,27 +51,8 @@ def register(request): request.POST['password']) entry.save(validate=True) - email_template = request.template_env.get_template( - 'mediagoblin/auth/verification_email.txt') - - # TODO: There is no error handling in place - send_email( - mgoblin_globals.email_sender_address, - [entry['email']], - # TODO - # Due to the distributed nature of GNU MediaGoblin, we should - # find a way to send some additional information about the - # specific GNU MediaGoblin instance in the subject line. For - # example "GNU MediaGoblin @ Wandborg - [...]". - 'GNU MediaGoblin - Verify email', - email_template.render( - username=entry['username'], - verification_url='http://{host}{uri}?userid={userid}&token={verification_key}'.format( - host=request.host, - uri=request.urlgen('mediagoblin.auth.verify_email'), - userid=unicode(entry['_id']), - verification_key=entry['verification_key']))) - + send_verification_email(entry, request) + # Redirect to register_success return exc.HTTPFound( location=request.urlgen("mediagoblin.auth.register_success")) @@ -195,31 +175,11 @@ def resend_activation(request): Resend the activation email. """ + request.user['verification_key'] = unicode(uuid.uuid4()) request.user.save() - # Copied shamelessly from the register view above. - - email_template = request.template_env.get_template( - 'mediagoblin/auth/verification_email.txt') - - # TODO: There is no error handling in place - send_email( - mgoblin_globals.email_sender_address, - [request.user['email']], - # TODO - # Due to the distributed nature of GNU MediaGoblin, we should - # find a way to send some additional information about the - # specific GNU MediaGoblin instance in the subject line. For - # example "GNU MediaGoblin @ Wandborg - [...]". - 'GNU MediaGoblin - Verify email', - email_template.render( - username=request.user['username'], - verification_url='http://{host}{uri}?userid={userid}&token={verification_key}'.format( - host=request.host, - uri=request.urlgen('mediagoblin.auth.verify_email'), - userid=unicode(request.user['_id']), - verification_key=request.user['verification_key']))) + send_verification_email(request.user, request) return exc.HTTPFound( location=request.urlgen('mediagoblin.auth.resend_verification_success')) -- cgit v1.2.3 From b5d3aec615fd32439c9fc708d2266dc1cdfecc9d Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sat, 4 Jun 2011 17:36:36 -0500 Subject: Moving all views over to using util.render_template()! --- mediagoblin/auth/views.py | 44 ++++++++++++++++---------------------------- 1 file changed, 16 insertions(+), 28 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index e4f1a7b1..2d24328d 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -18,6 +18,7 @@ import uuid from webob import Response, exc +from mediagoblin.util import render_template from mediagoblin.db.util import ObjectId from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms @@ -58,20 +59,16 @@ def register(request): location=request.urlgen("mediagoblin.auth.register_success")) # render - template = request.template_env.get_template( - 'mediagoblin/auth/register.html') return Response( - template.render( - {'request': request, - 'register_form': register_form})) + render_template( + request, 'mediagoblin/auth/register.html', + {'register_form': register_form})) def register_success(request): - template = request.template_env.get_template( - 'mediagoblin/auth/register_success.html') return Response( - template.render( - {'request': request})) + render_template( + request, 'mediagoblin/auth/register_success.html', {})) def login(request): @@ -106,12 +103,10 @@ def login(request): login_failed = True # render - template = request.template_env.get_template( - 'mediagoblin/auth/login.html') return Response( - template.render( - {'request': request, - 'login_form': login_form, + render_template( + request, 'mediagoblin/auth/login.html', + {'login_form': login_form, 'next': request.GET.get('next') or request.POST.get('next'), 'login_failed': login_failed})) @@ -146,12 +141,10 @@ def verify_email(request): else: verification_successful = False - template = request.template_env.get_template( - 'mediagoblin/auth/verify_email.html') return Response( - template.render( - {'request': request, - 'user': user, + render_template( + request, 'mediagoblin/auth/verify_email.html', + {'user': user, 'verification_successful': verification_successful})) def verify_email_notice(request): @@ -161,12 +154,9 @@ def verify_email_notice(request): When the user tries to do some action that requires their account to be verified beforehand, this view is called upon! """ - - template = request.template_env.get_template( - 'mediagoblin/auth/verification_needed.html') return Response( - template.render( - {'request': request})) + render_template( + request, 'mediagoblin/auth/verification_needed.html', {})) def resend_activation(request): @@ -186,8 +176,6 @@ def resend_activation(request): def resend_activation_success(request): - template = request.template_env.get_template( - 'mediagoblin/auth/resent_verification_email.html') return Response( - template.render( - {'request': request})) + render_template( + request, 'mediagoblin/auth/resent_verification_email.html', {})) -- cgit v1.2.3 From 1c63ad5d352f5eb38a4d634b9aea84cbeee269a4 Mon Sep 17 00:00:00 2001 From: Elrond Date: Sun, 5 Jun 2011 15:25:45 +0200 Subject: Create render_to_reponse and use it everywhere. Just a shortcut for Response(render_template(...)) --- mediagoblin/auth/views.py | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 2d24328d..a5112299 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -16,9 +16,9 @@ import uuid -from webob import Response, exc +from webob import exc -from mediagoblin.util import render_template +from mediagoblin.util import render_to_response from mediagoblin.db.util import ObjectId from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms @@ -59,16 +59,14 @@ def register(request): location=request.urlgen("mediagoblin.auth.register_success")) # render - return Response( - render_template( + return render_to_response( request, 'mediagoblin/auth/register.html', - {'register_form': register_form})) + {'register_form': register_form}) def register_success(request): - return Response( - render_template( - request, 'mediagoblin/auth/register_success.html', {})) + return render_to_response( + request, 'mediagoblin/auth/register_success.html', {}) def login(request): @@ -103,12 +101,11 @@ def login(request): login_failed = True # render - return Response( - render_template( + return render_to_response( request, 'mediagoblin/auth/login.html', {'login_form': login_form, 'next': request.GET.get('next') or request.POST.get('next'), - 'login_failed': login_failed})) + 'login_failed': login_failed}) def logout(request): @@ -141,11 +138,10 @@ def verify_email(request): else: verification_successful = False - return Response( - render_template( + return render_to_response( request, 'mediagoblin/auth/verify_email.html', {'user': user, - 'verification_successful': verification_successful})) + 'verification_successful': verification_successful}) def verify_email_notice(request): """ @@ -154,9 +150,8 @@ def verify_email_notice(request): When the user tries to do some action that requires their account to be verified beforehand, this view is called upon! """ - return Response( - render_template( - request, 'mediagoblin/auth/verification_needed.html', {})) + return render_to_response( + request, 'mediagoblin/auth/verification_needed.html', {}) def resend_activation(request): @@ -176,6 +171,5 @@ def resend_activation(request): def resend_activation_success(request): - return Response( - render_template( - request, 'mediagoblin/auth/resent_verification_email.html', {})) + return render_to_response( + request, 'mediagoblin/auth/resent_verification_email.html', {}) -- cgit v1.2.3 From c9c24934357300c436ac63531f91b7608f80fd21 Mon Sep 17 00:00:00 2001 From: Elrond Date: Sun, 5 Jun 2011 16:02:12 +0200 Subject: Reformat render_to_response calls Just a simple indentation and ordering change, no functional change. --- mediagoblin/auth/views.py | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index a5112299..d54e673c 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -58,15 +58,14 @@ def register(request): return exc.HTTPFound( location=request.urlgen("mediagoblin.auth.register_success")) - # render - return render_to_response( - request, 'mediagoblin/auth/register.html', - {'register_form': register_form}) + return render_to_response(request, + 'mediagoblin/auth/register.html', + {'register_form': register_form}) def register_success(request): - return render_to_response( - request, 'mediagoblin/auth/register_success.html', {}) + return render_to_response(request, + 'mediagoblin/auth/register_success.html', {}) def login(request): @@ -100,12 +99,11 @@ def login(request): auth_lib.fake_login_attempt() login_failed = True - # render - return render_to_response( - request, 'mediagoblin/auth/login.html', - {'login_form': login_form, - 'next': request.GET.get('next') or request.POST.get('next'), - 'login_failed': login_failed}) + return render_to_response(request, + 'mediagoblin/auth/login.html', + {'login_form': login_form, + 'next': request.GET.get('next') or request.POST.get('next'), + 'login_failed': login_failed}) def logout(request): @@ -138,10 +136,10 @@ def verify_email(request): else: verification_successful = False - return render_to_response( - request, 'mediagoblin/auth/verify_email.html', - {'user': user, - 'verification_successful': verification_successful}) + return render_to_response(request, + 'mediagoblin/auth/verify_email.html', + {'user': user, + 'verification_successful': verification_successful}) def verify_email_notice(request): """ @@ -150,8 +148,8 @@ def verify_email_notice(request): When the user tries to do some action that requires their account to be verified beforehand, this view is called upon! """ - return render_to_response( - request, 'mediagoblin/auth/verification_needed.html', {}) + return render_to_response(request, + 'mediagoblin/auth/verification_needed.html', {}) def resend_activation(request): @@ -171,5 +169,5 @@ def resend_activation(request): def resend_activation_success(request): - return render_to_response( - request, 'mediagoblin/auth/resent_verification_email.html', {}) + return render_to_response(request, + 'mediagoblin/auth/resent_verification_email.html', {}) -- cgit v1.2.3 From 9150244afa45628dd752a67272129d30d6c72224 Mon Sep 17 00:00:00 2001 From: Elrond Date: Sun, 5 Jun 2011 15:49:08 +0200 Subject: Create redirect shortcut and use it around This is just replacing exc.HTTPFound(location=request.urlgen(...)) by redirect(request, ...). No magic. --- mediagoblin/auth/views.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index d54e673c..36d23e53 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -18,7 +18,7 @@ import uuid from webob import exc -from mediagoblin.util import render_to_response +from mediagoblin.util import render_to_response, redirect from mediagoblin.db.util import ObjectId from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms @@ -54,9 +54,7 @@ def register(request): send_verification_email(entry, request) - # Redirect to register_success - return exc.HTTPFound( - location=request.urlgen("mediagoblin.auth.register_success")) + return redirect(request, "mediagoblin.auth.register_success") return render_to_response(request, 'mediagoblin/auth/register.html', @@ -90,8 +88,7 @@ def login(request): if request.POST.get('next'): return exc.HTTPFound(location=request.POST['next']) else: - return exc.HTTPFound( - location=request.urlgen("index")) + return redirect(request, "index") else: # Prevent detecting who's on this system by testing login @@ -110,8 +107,7 @@ def logout(request): # Maybe deleting the user_id parameter would be enough? request.session.delete() - return exc.HTTPFound( - location=request.urlgen("index")) + return redirect(request, "index") def verify_email(request): @@ -164,8 +160,7 @@ def resend_activation(request): send_verification_email(request.user, request) - return exc.HTTPFound( - location=request.urlgen('mediagoblin.auth.resend_verification_success')) + return redirect(request, 'mediagoblin.auth.resend_verification_success') def resend_activation_success(request): -- cgit v1.2.3 From b8fbd8179960f430b1ed3d6418946375c9efafd5 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sun, 5 Jun 2011 15:33:07 -0500 Subject: New password check error message --- mediagoblin/auth/forms.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index db8aaceb..7bc0aeb1 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -27,7 +27,9 @@ class RegistrationForm(wtforms.Form): 'Password', [wtforms.validators.Required(), wtforms.validators.Length(min=6, max=30), - wtforms.validators.EqualTo('confirm_password')]) + wtforms.validators.EqualTo( + 'confirm_password', + 'Passwords must match.')]) confirm_password = wtforms.PasswordField( 'Confirm password', [wtforms.validators.Required()]) -- cgit v1.2.3 From 9038c9f9acc4cfa257a52def2b292e6142e7d86a Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sun, 5 Jun 2011 15:41:08 -0500 Subject: I have a strong preference for aligning all parameters in a function call. --- mediagoblin/auth/views.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 36d23e53..94a62225 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -56,13 +56,15 @@ def register(request): return redirect(request, "mediagoblin.auth.register_success") - return render_to_response(request, + return render_to_response( + request, 'mediagoblin/auth/register.html', {'register_form': register_form}) def register_success(request): - return render_to_response(request, + return render_to_response( + request, 'mediagoblin/auth/register_success.html', {}) @@ -96,7 +98,8 @@ def login(request): auth_lib.fake_login_attempt() login_failed = True - return render_to_response(request, + return render_to_response( + request, 'mediagoblin/auth/login.html', {'login_form': login_form, 'next': request.GET.get('next') or request.POST.get('next'), @@ -132,7 +135,8 @@ def verify_email(request): else: verification_successful = False - return render_to_response(request, + return render_to_response( + request, 'mediagoblin/auth/verify_email.html', {'user': user, 'verification_successful': verification_successful}) @@ -144,8 +148,8 @@ def verify_email_notice(request): When the user tries to do some action that requires their account to be verified beforehand, this view is called upon! """ - return render_to_response(request, - 'mediagoblin/auth/verification_needed.html', {}) + return render_to_response( + request, 'mediagoblin/auth/verification_needed.html', {}) def resend_activation(request): @@ -164,5 +168,5 @@ def resend_activation(request): def resend_activation_success(request): - return render_to_response(request, - 'mediagoblin/auth/resent_verification_email.html', {}) + return render_to_response( + request, 'mediagoblin/auth/resent_verification_email.html', {}) -- cgit v1.2.3 From 2262b2a9e1aad834bce8782216c3d8068a008618 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sun, 5 Jun 2011 15:58:35 -0500 Subject: Made a simple template rendering view and switched a bunch of code over to using it --- mediagoblin/auth/routing.py | 9 ++++++--- mediagoblin/auth/views.py | 22 ---------------------- 2 files changed, 6 insertions(+), 25 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index a8909fbb..46c585d2 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -20,7 +20,8 @@ auth_routes = [ Route('mediagoblin.auth.register', '/register/', controller='mediagoblin.auth.views:register'), Route('mediagoblin.auth.register_success', '/register/success/', - controller='mediagoblin.auth.views:register_success'), + template='mediagoblin/auth/register_success.html', + controller='mediagoblin.views:simple_template_render'), Route('mediagoblin.auth.login', '/login/', controller='mediagoblin.auth.views:login'), Route('mediagoblin.auth.logout', '/logout/', @@ -28,9 +29,11 @@ auth_routes = [ Route('mediagoblin.auth.verify_email', '/verify_email/', controller='mediagoblin.auth.views:verify_email'), Route('mediagoblin.auth.verify_email_notice', '/verification_required/', - controller='mediagoblin.auth.views:verify_email_notice'), + template='mediagoblin/auth/verification_needed.html', + controller='mediagoblin.views:simple_template_render'), Route('mediagoblin.auth.resend_verification', '/resend_verification/', controller='mediagoblin.auth.views:resend_activation'), Route('mediagoblin.auth.resend_verification_success', '/resend_verification_success/', - controller='mediagoblin.auth.views:resend_activation_success')] + template='mediagoblin/auth/resent_verification_email.html', + controller='mediagoblin.views:simple_template_render')] diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 94a62225..1d00f382 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -62,12 +62,6 @@ def register(request): {'register_form': register_form}) -def register_success(request): - return render_to_response( - request, - 'mediagoblin/auth/register_success.html', {}) - - def login(request): """ MediaGoblin login view. @@ -141,16 +135,6 @@ def verify_email(request): {'user': user, 'verification_successful': verification_successful}) -def verify_email_notice(request): - """ - Verify warning view. - - When the user tries to do some action that requires their account - to be verified beforehand, this view is called upon! - """ - return render_to_response( - request, 'mediagoblin/auth/verification_needed.html', {}) - def resend_activation(request): """ @@ -158,15 +142,9 @@ def resend_activation(request): Resend the activation email. """ - request.user['verification_key'] = unicode(uuid.uuid4()) request.user.save() send_verification_email(request.user, request) return redirect(request, 'mediagoblin.auth.resend_verification_success') - - -def resend_activation_success(request): - return render_to_response( - request, 'mediagoblin/auth/resent_verification_email.html', {}) -- cgit v1.2.3 From 2c3fd5c5bf6ac56638195863948e30a9d96394c9 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sun, 5 Jun 2011 17:31:18 -0500 Subject: Moved the verification url generation string template to a global variable --- mediagoblin/auth/lib.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index dc5f9941..dc37c230 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -89,6 +89,10 @@ def fake_login_attempt(): randplus_stored_hash == randplus_hashed_pass +EMAIL_VERIFICATION_TEMPLATE = ( + u"http://{host}{uri}?" + u"userid={userid}&token={verification_key}") + def send_verification_email(user, request): """ Send the verification email to users to activate their accounts. @@ -113,8 +117,8 @@ def send_verification_email(user, request): 'GNU MediaGoblin - Verify your email!', email_template.render( username=user['username'], - verification_url='http://{host}{uri}?userid={userid}&token={verification_key}'.format( - host=request.host, - uri=request.urlgen('mediagoblin.auth.verify_email'), - userid=unicode(user['_id']), - verification_key=user['verification_key']))) + verification_url=EMAIL_VERIFICATION_TEMPLATE.format( + host=request.host, + uri=request.urlgen('mediagoblin.auth.verify_email'), + userid=unicode(user['_id']), + verification_key=user['verification_key']))) -- cgit v1.2.3 From 23cc15c99837913d4c87c7829745f71067902d3b Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sun, 5 Jun 2011 17:35:20 -0500 Subject: Use render_template utility so we can test whether or not this email sends --- mediagoblin/auth/lib.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index dc37c230..f40e560f 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -19,7 +19,7 @@ import random import bcrypt -from mediagoblin.util import send_email +from mediagoblin.util import send_email, render_template from mediagoblin import globals as mgoblin_globals @@ -101,9 +101,14 @@ def send_verification_email(user, request): - user: a user object - request: the request """ - - email_template = request.template_env.get_template( - 'mediagoblin/auth/verification_email.txt') + rendered_email = render_template( + request, 'mediagoblin/auth/verification_email.txt', + {'username': user['username'], + 'verification_url': EMAIL_VERIFICATION_TEMPLATE.format( + host=request.host, + uri=request.urlgen('mediagoblin.auth.verify_email'), + userid=unicode(user['_id']), + verification_key=user['verification_key'])}) # TODO: There is no error handling in place send_email( @@ -115,10 +120,4 @@ def send_verification_email(user, request): # specific GNU MediaGoblin instance in the subject line. For # example "GNU MediaGoblin @ Wandborg - [...]". 'GNU MediaGoblin - Verify your email!', - email_template.render( - username=user['username'], - verification_url=EMAIL_VERIFICATION_TEMPLATE.format( - host=request.host, - uri=request.urlgen('mediagoblin.auth.verify_email'), - userid=unicode(user['_id']), - verification_key=user['verification_key']))) + rendered_email) -- cgit v1.2.3 From 6e7ce8d1af8c6fcf7d00992b1c8ef0e8c1602479 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sun, 12 Jun 2011 17:27:37 -0500 Subject: mediagoblin.globals->mediagoblin.mg_globals --- mediagoblin/auth/lib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index f40e560f..08bbdd16 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -20,7 +20,7 @@ import random import bcrypt from mediagoblin.util import send_email, render_template -from mediagoblin import globals as mgoblin_globals +from mediagoblin import mg_globals def bcrypt_check_password(raw_pass, stored_hash, extra_salt=None): @@ -112,7 +112,7 @@ def send_verification_email(user, request): # TODO: There is no error handling in place send_email( - mgoblin_globals.email_sender_address, + mg_globals.email_sender_address, [user['email']], # TODO # Due to the distributed nature of GNU MediaGoblin, we should -- cgit v1.2.3 From cfe46f3e68b62bba0cfb943dc45e9b88c3f7c25e Mon Sep 17 00:00:00 2001 From: Caleb Forbes Davis V Date: Mon, 4 Jul 2011 19:42:45 -0500 Subject: uses the messaging system to notify user of result of verification check Feature #424 - Use messaging system for email verifification check response * uses add_message in verify_email and routes to the user page, bypassing verify_email.html --- mediagoblin/auth/views.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 1d00f382..435ad803 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -18,6 +18,7 @@ import uuid from webob import exc +from mediagoblin import messages from mediagoblin.util import render_to_response, redirect from mediagoblin.db.util import ObjectId from mediagoblin.auth import lib as auth_lib @@ -124,16 +125,20 @@ def verify_email(request): if user and user['verification_key'] == unicode(request.GET['token']): user['status'] = u'active' user['email_verified'] = True - verification_successful = True user.save() + messages.add_message(request, + messages.SUCCESS, + 'Your email address has been verified. ' \ + 'You may now login!') else: - verification_successful = False + messages.add_message(request, + messages.ERROR, + 'The verification key or user id is incorrect') return render_to_response( request, - 'mediagoblin/auth/verify_email.html', - {'user': user, - 'verification_successful': verification_successful}) + 'mediagoblin/user_pages/user.html', + {'user': user}) def resend_activation(request): -- cgit v1.2.3 From e054ae9b3dfc518a34eb4a7395b177f0e8a31469 Mon Sep 17 00:00:00 2001 From: Caleb Forbes Davis V Date: Mon, 4 Jul 2011 20:04:00 -0500 Subject: allows using messaging instead of verify_email.html to pass tests * re-instated verification_successful flag * modified test_auth to verify nav to user_pages/user.html template --- mediagoblin/auth/views.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 435ad803..47707ca5 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -126,11 +126,13 @@ def verify_email(request): user['status'] = u'active' user['email_verified'] = True user.save() + verification_successful = True messages.add_message(request, messages.SUCCESS, 'Your email address has been verified. ' \ 'You may now login!') else: + verification_successful = False messages.add_message(request, messages.ERROR, 'The verification key or user id is incorrect') @@ -138,7 +140,8 @@ def verify_email(request): return render_to_response( request, 'mediagoblin/user_pages/user.html', - {'user': user}) + {'user': user, + 'verification_successful' : verification_successful}) def resend_activation(request): -- cgit v1.2.3 From fe80cb06c499723a4e557c10b993b754f4b60456 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 6 Jul 2011 22:52:08 -0500 Subject: Also encourages editing your profile and submitting images --- mediagoblin/auth/views.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 47707ca5..2450023f 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -127,10 +127,11 @@ def verify_email(request): user['email_verified'] = True user.save() verification_successful = True - messages.add_message(request, - messages.SUCCESS, - 'Your email address has been verified. ' \ - 'You may now login!') + messages.add_message( + request, + messages.SUCCESS, + ('Your email address has been verified. ' + 'You may now login, edit your profile, and submit images!')) else: verification_successful = False messages.add_message(request, -- cgit v1.2.3 From 13677ef97a24fea19fe8df1cce4812c18623d88f Mon Sep 17 00:00:00 2001 From: Rasmus Larsson Date: Sat, 9 Jul 2011 15:12:00 +0200 Subject: Added configuration variable to toggle registrations, if disabled the registration page redirects to index and no link to register is shown --- mediagoblin/auth/views.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 2450023f..a6ae1407 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -19,6 +19,7 @@ import uuid from webob import exc from mediagoblin import messages +from mediagoblin import mg_globals from mediagoblin.util import render_to_response, redirect from mediagoblin.db.util import ObjectId from mediagoblin.auth import lib as auth_lib @@ -30,6 +31,11 @@ def register(request): """ Your classic registration view! """ + + # Redirects to indexpage if registrations are disabled + if not mg_globals.app_config["allow_registration"]: + return redirect(request, "index") + register_form = auth_forms.RegistrationForm(request.POST) if request.method == 'POST' and register_form.validate(): -- cgit v1.2.3 From 13bb1d676e3363605d87acd34bdb6b701ec467dd Mon Sep 17 00:00:00 2001 From: Rasmus Larsson Date: Sat, 9 Jul 2011 15:19:55 +0200 Subject: Updated the loginpage to not show a link to register if registrations are disabled --- mediagoblin/auth/views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index a6ae1407..01bfc066 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -104,7 +104,8 @@ def login(request): 'mediagoblin/auth/login.html', {'login_form': login_form, 'next': request.GET.get('next') or request.POST.get('next'), - 'login_failed': login_failed}) + 'login_failed': login_failed, + 'allow_registration': mg_globals.app_config["allow_registration"]}) def logout(request): -- cgit v1.2.3 From 166dc91aca21048e235dec126c0518a807fead41 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sat, 9 Jul 2011 09:02:17 -0500 Subject: Add a warning to the user that registrations are disabled. --- mediagoblin/auth/views.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 01bfc066..7facc1bf 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -31,9 +31,12 @@ def register(request): """ Your classic registration view! """ - # Redirects to indexpage if registrations are disabled if not mg_globals.app_config["allow_registration"]: + messages.add_message( + request, + messages.WARNING, + ('Sorry, registration is disabled on this instance.')) return redirect(request, "index") register_form = auth_forms.RegistrationForm(request.POST) -- cgit v1.2.3 From 7b31a11c80afa4f7e819ca102553e5de5c2e4746 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sat, 9 Jul 2011 09:02:57 -0500 Subject: Removing trailing whitespace from this file --- mediagoblin/auth/views.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 7facc1bf..7fe507b1 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -61,7 +61,7 @@ def register(request): entry['pw_hash'] = auth_lib.bcrypt_gen_password_hash( request.POST['password']) entry.save(validate=True) - + send_verification_email(entry, request) return redirect(request, "mediagoblin.auth.register_success") @@ -114,7 +114,7 @@ def login(request): def logout(request): # Maybe deleting the user_id parameter would be enough? request.session.delete() - + return redirect(request, "index") @@ -138,16 +138,16 @@ def verify_email(request): user.save() verification_successful = True messages.add_message( - request, - messages.SUCCESS, + request, + messages.SUCCESS, ('Your email address has been verified. ' 'You may now login, edit your profile, and submit images!')) else: verification_successful = False - messages.add_message(request, - messages.ERROR, - 'The verification key or user id is incorrect') - + messages.add_message(request, + messages.ERROR, + 'The verification key or user id is incorrect') + return render_to_response( request, 'mediagoblin/user_pages/user.html', -- cgit v1.2.3 From 6ae8b541f957b49ae86051814097e769d20f29af Mon Sep 17 00:00:00 2001 From: Deb Date: Tue, 12 Jul 2011 21:21:35 -0400 Subject: removed email variables from globals module --- mediagoblin/auth/lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index 08bbdd16..6d1aec49 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -112,7 +112,7 @@ def send_verification_email(user, request): # TODO: There is no error handling in place send_email( - mg_globals.email_sender_address, + mg_globals.app_config['email_sender_address'], [user['email']], # TODO # Due to the distributed nature of GNU MediaGoblin, we should -- cgit v1.2.3 From 61927e6e802d5d138466a9f3c34c6faa91ec19b6 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Fri, 29 Jul 2011 08:09:13 -0500 Subject: resend_activation should give the user a message and redirect them to their user_home --- mediagoblin/auth/views.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 7fe507b1..6f3c5165 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -166,4 +166,10 @@ def resend_activation(request): send_verification_email(request.user, request) - return redirect(request, 'mediagoblin.auth.resend_verification_success') + messages.add_message( + request, + messages.INFO, + 'Resent your verification email.') + return redirect( + request, 'mediagoblin.user_pages.user_home', + user=request.user['username']) -- cgit v1.2.3 From 7074304c91bfc19e2a6365f3d9567ec5a2636f9d Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Fri, 29 Jul 2011 08:14:02 -0500 Subject: Remove the verification needed page --- mediagoblin/auth/routing.py | 3 --- 1 file changed, 3 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index 46c585d2..a50afb48 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -28,9 +28,6 @@ auth_routes = [ controller='mediagoblin.auth.views:logout'), Route('mediagoblin.auth.verify_email', '/verify_email/', controller='mediagoblin.auth.views:verify_email'), - Route('mediagoblin.auth.verify_email_notice', '/verification_required/', - template='mediagoblin/auth/verification_needed.html', - controller='mediagoblin.views:simple_template_render'), Route('mediagoblin.auth.resend_verification', '/resend_verification/', controller='mediagoblin.auth.views:resend_activation'), Route('mediagoblin.auth.resend_verification_success', -- cgit v1.2.3 From 0bc036209dab581ad60b97231473c832fca9e875 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Fri, 29 Jul 2011 08:22:26 -0500 Subject: Redirect to the user's profile after registration - Updated the view - Updated the tests - Fixed a weirdness in the registration view where the 'user' variable used to be called 'entry' --- mediagoblin/auth/routing.py | 3 --- mediagoblin/auth/views.py | 25 ++++++++++++++++--------- 2 files changed, 16 insertions(+), 12 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index a50afb48..9547b3ea 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -19,9 +19,6 @@ from routes.route import Route auth_routes = [ Route('mediagoblin.auth.register', '/register/', controller='mediagoblin.auth.views:register'), - Route('mediagoblin.auth.register_success', '/register/success/', - template='mediagoblin/auth/register_success.html', - controller='mediagoblin.views:simple_template_render'), Route('mediagoblin.auth.login', '/login/', controller='mediagoblin.auth.views:login'), Route('mediagoblin.auth.logout', '/logout/', diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 6f3c5165..cf07d668 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -55,16 +55,23 @@ def register(request): else: # Create the user - entry = request.db.User() - entry['username'] = request.POST['username'].lower() - entry['email'] = request.POST['email'] - entry['pw_hash'] = auth_lib.bcrypt_gen_password_hash( + user = request.db.User() + user['username'] = request.POST['username'].lower() + user['email'] = request.POST['email'] + user['pw_hash'] = auth_lib.bcrypt_gen_password_hash( request.POST['password']) - entry.save(validate=True) - - send_verification_email(entry, request) - - return redirect(request, "mediagoblin.auth.register_success") + user.save(validate=True) + + send_verification_email(user, request) + + messages.add_message( + request, + messages.INFO, + ('Registration successful! ' + 'You should get a registration email soon.')) + return redirect( + request, 'mediagoblin.user_pages.user_home', + user=user['username']) return render_to_response( request, -- cgit v1.2.3 From f73f4c4b8425fb49b95a453107e5717caeb38386 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Fri, 29 Jul 2011 08:43:59 -0500 Subject: Log in user after regitration --- mediagoblin/auth/views.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index cf07d668..e0d9c8f1 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -62,8 +62,14 @@ def register(request): request.POST['password']) user.save(validate=True) + # log the user in + request.session['user_id'] = unicode(user['_id']) + request.session.save() + + # send verification email send_verification_email(user, request) + # give the user a message and redirect messages.add_message( request, messages.INFO, -- cgit v1.2.3 From dce5c9cb9b28154edef85f5c9031f6a67be503ea Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Fri, 29 Jul 2011 08:44:47 -0500 Subject: Remove this superfluous "registration successful" message --- mediagoblin/auth/views.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index e0d9c8f1..fb5db870 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -69,12 +69,8 @@ def register(request): # send verification email send_verification_email(user, request) - # give the user a message and redirect - messages.add_message( - request, - messages.INFO, - ('Registration successful! ' - 'You should get a registration email soon.')) + # redirect the user to their homepage... there will be a + # message waiting for them to verify their email return redirect( request, 'mediagoblin.user_pages.user_home', user=user['username']) -- cgit v1.2.3 From 269943a645d16c51af0388c764c76721336369bc Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sun, 31 Jul 2011 15:09:52 -0500 Subject: We should redirect after verify_email to the user's homepage --- mediagoblin/auth/views.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index fb5db870..df7e2a88 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -145,23 +145,19 @@ def verify_email(request): user['status'] = u'active' user['email_verified'] = True user.save() - verification_successful = True messages.add_message( request, messages.SUCCESS, ('Your email address has been verified. ' 'You may now login, edit your profile, and submit images!')) else: - verification_successful = False messages.add_message(request, messages.ERROR, 'The verification key or user id is incorrect') - return render_to_response( - request, - 'mediagoblin/user_pages/user.html', - {'user': user, - 'verification_successful' : verification_successful}) + return redirect( + request, 'mediagoblin.user_pages.user_home', + user=request.user['username']) def resend_activation(request): -- cgit v1.2.3 From d88e1d15c7c4903a696830155527f70e33b88c72 Mon Sep 17 00:00:00 2001 From: Caleb Forbes Davis V Date: Mon, 8 Aug 2011 00:10:46 -0500 Subject: Bug #488 - email validation assumes active login - loads username from user object instead of session to remove dependency on active login --- mediagoblin/auth/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index df7e2a88..19dafed0 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -157,7 +157,7 @@ def verify_email(request): return redirect( request, 'mediagoblin.user_pages.user_home', - user=request.user['username']) + user = user['username']) def resend_activation(request): -- cgit v1.2.3 From 4b1adc132cf45507e2f910122992230d428c6856 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Mon, 8 Aug 2011 22:53:39 -0500 Subject: Marked relevant strings in python views/forms for translation via ugettext --- mediagoblin/auth/forms.py | 16 +++++++++------- mediagoblin/auth/views.py | 18 ++++++++++-------- 2 files changed, 19 insertions(+), 15 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index 7bc0aeb1..1b6bc7c2 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -16,34 +16,36 @@ import wtforms +from mediagoblin.util import pass_to_ugettext as _ + class RegistrationForm(wtforms.Form): username = wtforms.TextField( - 'Username', + _('Username'), [wtforms.validators.Required(), wtforms.validators.Length(min=3, max=30), wtforms.validators.Regexp(r'^\w+$')]) password = wtforms.PasswordField( - 'Password', + _('Password'), [wtforms.validators.Required(), wtforms.validators.Length(min=6, max=30), wtforms.validators.EqualTo( 'confirm_password', - 'Passwords must match.')]) + _('Passwords must match.'))]) confirm_password = wtforms.PasswordField( - 'Confirm password', + _('Confirm password'), [wtforms.validators.Required()]) email = wtforms.TextField( - 'Email address', + _('Email address'), [wtforms.validators.Required(), wtforms.validators.Email()]) class LoginForm(wtforms.Form): username = wtforms.TextField( - 'Username', + _('Username'), [wtforms.validators.Required(), wtforms.validators.Regexp(r'^\w+$')]) password = wtforms.PasswordField( - 'Password', + _('Password'), [wtforms.validators.Required()]) diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index df7e2a88..121a8c8e 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -21,6 +21,7 @@ from webob import exc from mediagoblin import messages from mediagoblin import mg_globals from mediagoblin.util import render_to_response, redirect +from mediagoblin.util import pass_to_ugettext as _ from mediagoblin.db.util import ObjectId from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms @@ -36,7 +37,7 @@ def register(request): messages.add_message( request, messages.WARNING, - ('Sorry, registration is disabled on this instance.')) + _('Sorry, registration is disabled on this instance.')) return redirect(request, "index") register_form = auth_forms.RegistrationForm(request.POST) @@ -51,7 +52,7 @@ def register(request): if users_with_username: register_form.username.errors.append( - u'Sorry, a user with that name already exists.') + _(u'Sorry, a user with that name already exists.')) else: # Create the user @@ -148,12 +149,13 @@ def verify_email(request): messages.add_message( request, messages.SUCCESS, - ('Your email address has been verified. ' - 'You may now login, edit your profile, and submit images!')) + _("Your email address has been verified. " + "You may now login, edit your profile, and submit images!")) else: - messages.add_message(request, - messages.ERROR, - 'The verification key or user id is incorrect') + messages.add_message( + request, + messages.ERROR, + _('The verification key or user id is incorrect')) return redirect( request, 'mediagoblin.user_pages.user_home', @@ -174,7 +176,7 @@ def resend_activation(request): messages.add_message( request, messages.INFO, - 'Resent your verification email.') + _('Resent your verification email.')) return redirect( request, 'mediagoblin.user_pages.user_home', user=request.user['username']) -- cgit v1.2.3 From 7960ac985f9b5a80063f21012d53793cb2d22dd9 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 10 Aug 2011 12:07:59 -0500 Subject: Converting all forms to use the "fake/null" gettext conversion function Gettext doesn't actually get run right in the form but we do need to wrap the strings in _() so stuff extracts :) --- mediagoblin/auth/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index 1b6bc7c2..917909c5 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -16,7 +16,7 @@ import wtforms -from mediagoblin.util import pass_to_ugettext as _ +from mediagoblin.util import fake_ugettext_passthrough as _ class RegistrationForm(wtforms.Form): -- cgit v1.2.3 From dc49cf600aba92331419a3566f768b061b8102e3 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Thu, 11 Aug 2011 20:15:55 -0500 Subject: Making the users_with_username function call in the register view slightly cleaner --- mediagoblin/auth/views.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 121a8c8e..dc90173e 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -45,10 +45,8 @@ def register(request): if request.method == 'POST' and register_form.validate(): # TODO: Make sure the user doesn't exist already - users_with_username = \ - request.db.User.find({ - 'username': request.POST['username'].lower() - }).count() + users_with_username = request.db.User.find( + {'username': request.POST['username'].lower()}).count() if users_with_username: register_form.username.errors.append( -- cgit v1.2.3 From 0bf099d7536b5f5f876fa21e4c72f132b7c757a8 Mon Sep 17 00:00:00 2001 From: Alejandro Villanueva Date: Tue, 14 Jun 2011 11:03:56 -0500 Subject: Checks if the email(lowercase) have been used before to register a user --- mediagoblin/auth/views.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index dc90173e..61164be8 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -47,10 +47,15 @@ def register(request): users_with_username = request.db.User.find( {'username': request.POST['username'].lower()}).count() + users_with_email = request.db.User.find( + {'email': request.POST['email'].lower()}).count() if users_with_username: register_form.username.errors.append( _(u'Sorry, a user with that name already exists.')) + elif users_with_email: + register_form.email.errors.append( + _(u'Sorry, that email address has already been taken.')) else: # Create the user -- cgit v1.2.3 From 873e4e9d2da8a3976de6c44838f517cfc314d620 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Thu, 11 Aug 2011 20:34:12 -0500 Subject: Also normalize user's emails to .lower() when we accept the user. --- mediagoblin/auth/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 61164be8..91599e47 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -61,7 +61,7 @@ def register(request): # Create the user user = request.db.User() user['username'] = request.POST['username'].lower() - user['email'] = request.POST['email'] + user['email'] = request.POST['email'].lower() user['pw_hash'] = auth_lib.bcrypt_gen_password_hash( request.POST['password']) user.save(validate=True) -- cgit v1.2.3 From 9f6ea47586f78370c42dc9b45782f398bebf7d2e Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Thu, 11 Aug 2011 20:37:21 -0500 Subject: If both the username and the email checks fail, warn about both at the same time --- mediagoblin/auth/views.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 91599e47..ce6b5dfc 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -50,14 +50,18 @@ def register(request): users_with_email = request.db.User.find( {'email': request.POST['email'].lower()}).count() + extra_validation_passes = True + if users_with_username: register_form.username.errors.append( _(u'Sorry, a user with that name already exists.')) - elif users_with_email: + extra_validation_passes = False + if users_with_email: register_form.email.errors.append( _(u'Sorry, that email address has already been taken.')) + extra_validation_passes = False - else: + if extra_validation_passes: # Create the user user = request.db.User() user['username'] = request.POST['username'].lower() -- cgit v1.2.3 From 788272f30034fb2f917496197e317226d21aad2e Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Thu, 11 Aug 2011 22:44:47 -0500 Subject: PEP-8ing the keyword argument passing here --- mediagoblin/auth/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 55f42141..9120196f 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -166,7 +166,7 @@ def verify_email(request): return redirect( request, 'mediagoblin.user_pages.user_home', - user = user['username']) + user=user['username']) def resend_activation(request): -- cgit v1.2.3 From de12b4e77358a496bced68cbdc23bf50f95c7ee0 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sat, 20 Aug 2011 15:57:24 -0500 Subject: Use render_404 EVERYWHERE! --- mediagoblin/auth/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 9120196f..4c4a34fd 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -20,7 +20,7 @@ from webob import exc from mediagoblin import messages from mediagoblin import mg_globals -from mediagoblin.util import render_to_response, redirect +from mediagoblin.util import render_to_response, redirect, render_404 from mediagoblin.util import pass_to_ugettext as _ from mediagoblin.db.util import ObjectId from mediagoblin.auth import lib as auth_lib @@ -144,7 +144,7 @@ def verify_email(request): """ # If we don't have userid and token parameters, we can't do anything; 404 if not request.GET.has_key('userid') or not request.GET.has_key('token'): - return exc.HTTPNotFound() + return render_404(request) user = request.db.User.find_one( {'_id': ObjectId(unicode(request.GET['userid']))}) -- cgit v1.2.3 From 08750772eaf140266d1be0aac5024f581664012b Mon Sep 17 00:00:00 2001 From: Mark Holmquist Date: Mon, 22 Aug 2011 02:57:40 -0700 Subject: + 'confirm' section for confirmation dialogues + implemented delete functionality * fixed several instances of 'must be an instance of unicode, not str' --- mediagoblin/auth/views.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 4c4a34fd..48c5937c 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -44,11 +44,12 @@ def register(request): if request.method == 'POST' and register_form.validate(): # TODO: Make sure the user doesn't exist already - + username = unicode(request.POST['username'].lower()) + email = unicode(request.POST['email'].lower()) users_with_username = request.db.User.find( - {'username': request.POST['username'].lower()}).count() + {'username': username}).count() users_with_email = request.db.User.find( - {'email': request.POST['email'].lower()}).count() + {'email': email}).count() extra_validation_passes = True @@ -64,8 +65,8 @@ def register(request): if extra_validation_passes: # Create the user user = request.db.User() - user['username'] = request.POST['username'].lower() - user['email'] = request.POST['email'].lower() + user['username'] = username + user['email'] = email user['pw_hash'] = auth_lib.bcrypt_gen_password_hash( request.POST['password']) user.save(validate=True) -- cgit v1.2.3 From 25ba955e20e9262f2599a21d234511b724569717 Mon Sep 17 00:00:00 2001 From: Alejandro Villanueva Date: Thu, 21 Jul 2011 11:55:41 -0500 Subject: Adding fotgot password functionality --- mediagoblin/auth/forms.py | 32 +++++++++++++++ mediagoblin/auth/lib.py | 40 ++++++++++++++++--- mediagoblin/auth/routing.py | 12 ++++++ mediagoblin/auth/views.py | 96 ++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 173 insertions(+), 7 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index 917909c5..1be74aa6 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -15,6 +15,7 @@ # along with this program. If not, see . import wtforms +import re from mediagoblin.util import fake_ugettext_passthrough as _ @@ -49,3 +50,34 @@ class LoginForm(wtforms.Form): password = wtforms.PasswordField( _('Password'), [wtforms.validators.Required()]) + + +class ForgotPassForm(wtforms.Form): + username = wtforms.TextField( + 'Username or email', + [wtforms.validators.Required()]) + + def validate_username(form,field): + if not (re.match(r'^\w+$',field.data) or + re.match(r'^.+@[^.].*\.[a-z]{2,10}$',field.data, re.IGNORECASE)): + raise wtforms.ValidationError(u'Incorrect input') + + +class ChangePassForm(wtforms.Form): + password = wtforms.PasswordField( + 'Password', + [wtforms.validators.Required(), + wtforms.validators.Length(min=6, max=30), + wtforms.validators.EqualTo( + 'confirm_password', + 'Passwords must match.')]) + confirm_password = wtforms.PasswordField( + 'Confirm password', + [wtforms.validators.Required()]) + userid = wtforms.HiddenField( + '', + [wtforms.validators.Required()]) + token = wtforms.HiddenField( + '', + [wtforms.validators.Required()]) + diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index 6d1aec49..df93b666 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -47,7 +47,7 @@ def bcrypt_check_password(raw_pass, stored_hash, extra_salt=None): # number (thx to zooko on this advice, which I hopefully # incorporated right.) # - # See also: + # See also: rand_salt = bcrypt.gensalt(5) randplus_stored_hash = bcrypt.hashpw(stored_hash, rand_salt) randplus_hashed_pass = bcrypt.hashpw(hashed_pass, rand_salt) @@ -99,7 +99,7 @@ def send_verification_email(user, request): Args: - user: a user object - - request: the request + - request: the request """ rendered_email = render_template( request, 'mediagoblin/auth/verification_email.txt', @@ -116,8 +116,38 @@ def send_verification_email(user, request): [user['email']], # TODO # Due to the distributed nature of GNU MediaGoblin, we should - # find a way to send some additional information about the - # specific GNU MediaGoblin instance in the subject line. For - # example "GNU MediaGoblin @ Wandborg - [...]". + # find a way to send some additional information about the + # specific GNU MediaGoblin instance in the subject line. For + # example "GNU MediaGoblin @ Wandborg - [...]". 'GNU MediaGoblin - Verify your email!', rendered_email) + + +EMAIL_FP_VERIFICATION_TEMPLATE = ( + u"http://{host}{uri}?" + u"userid={userid}&token={fp_verification_key}") + +def send_fp_verification_email(user,request): + """ + Send the verification email to users to change their password. + + Args: + - user: a user object + - request: the request + """ + rendered_email = render_template( + request, 'mediagoblin/auth/fp_verification_email.txt', + {'username': user['username'], + 'verification_url': EMAIL_FP_VERIFICATION_TEMPLATE.format( + host=request.host, + uri=request.urlgen('mediagoblin.auth.verify_forgot_password'), + userid=unicode(user['_id']), + fp_verification_key=user['fp_verification_key'])}) + + # TODO: There is no error handling in place + send_email( + mg_globals.email_sender_address, + [user['email']], + 'GNU MediaGoblin - Change forgotten password!', + rendered_email) + diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index 9547b3ea..14e87133 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -30,4 +30,16 @@ auth_routes = [ Route('mediagoblin.auth.resend_verification_success', '/resend_verification_success/', template='mediagoblin/auth/resent_verification_email.html', + controller='mediagoblin.views:simple_template_render'), + Route('mediagoblin.auth.forgot_password', '/forgotpass/', + controller='mediagoblin.auth.views:forgot_password'), + Route('mediagoblin.auth.verify_forgot_password', '/verifyforgotpass/', + controller='mediagoblin.auth.views:verify_forgot_password'), + Route('mediagoblin.auth.fp_changed_success', + '/fp_changed_success/', + template='mediagoblin/auth/fp_changed_success.html', + controller='mediagoblin.views:simple_template_render'), + Route('mediagoblin.auth.fp_email_sent', + '/fp_email_sent/', + template='mediagoblin/auth/fp_email_sent.html', controller='mediagoblin.views:simple_template_render')] diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 4c4a34fd..50276442 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -15,6 +15,7 @@ # along with this program. If not, see . import uuid +import datetime from webob import exc @@ -22,10 +23,11 @@ from mediagoblin import messages from mediagoblin import mg_globals from mediagoblin.util import render_to_response, redirect, render_404 from mediagoblin.util import pass_to_ugettext as _ -from mediagoblin.db.util import ObjectId +from mediagoblin.db.util import ObjectId, InvalidId from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms -from mediagoblin.auth.lib import send_verification_email +from mediagoblin.auth.lib import send_verification_email, \ + send_fp_verification_email def register(request): @@ -187,3 +189,93 @@ def resend_activation(request): return redirect( request, 'mediagoblin.user_pages.user_home', user=request.user['username']) + + +def forgot_password(request): + """ + Forgot password view + + Sends an email whit an url to renew forgoten password + """ + fp_form = auth_forms.ForgotPassForm(request.POST) + + if request.method == 'POST' and fp_form.validate(): + user = request.db.User.one( + {'$or': [{'username': request.POST['username']}, + {'email': request.POST['username']}]}) + + if not user: + fp_form.username.errors.append( + u"Sorry, the username doesn't exists") + else: + user['fp_verification_key'] = unicode(uuid.uuid4()) + user['fp_token_expire'] = datetime.datetime.now() + \ + datetime.timedelta(days=10) + user.save() + + send_fp_verification_email(user, request) + + return redirect(request, 'mediagoblin.auth.fp_email_sent') + + return render_to_response( + request, + 'mediagoblin/auth/forgot_password.html', + {'fp_form': fp_form}) + + +def verify_forgot_password(request): + if request.method == 'GET': + # If we don't have userid and token parameters, we can't do anything;404 + if (not request.GET.has_key('userid') or + not request.GET.has_key('token')): + return exc.HTTPNotFound('You must provide userid and token') + + # check if it's a valid Id + try: + user = request.db.User.find_one( + {'_id': ObjectId(unicode(request.GET['userid']))}) + except InvalidId: + return exc.HTTPNotFound('Invalid id') + + # check if we have a real user and correct token + if (user and + user['fp_verification_key'] == unicode(request.GET['token'])): + cp_form = auth_forms.ChangePassForm(request.GET) + + return render_to_response( + request, + 'mediagoblin/auth/change_fp.html', + {'cp_form': cp_form}) + # in case there is a valid id but no user whit that id in the db + else: + return exc.HTTPNotFound('User not found') + if request.method == 'POST': + # verification doing here to prevent POST values modification + try: + user = request.db.User.find_one( + {'_id': ObjectId(unicode(request.POST['userid']))}) + except InvalidId: + return exc.HTTPNotFound('Invalid id') + + cp_form = auth_forms.ChangePassForm(request.POST) + + # verification doing here to prevent POST values modification + # if token and id are correct they are able to change their password + if (user and + user['fp_verification_key'] == unicode(request.POST['token'])): + + if cp_form.validate(): + user['pw_hash'] = auth_lib.bcrypt_gen_password_hash( + request.POST['password']) + user['fp_verification_key'] = None + user.save() + + return redirect(request, + 'mediagoblin.auth.fp_changed_success') + else: + return render_to_response( + request, + 'mediagoblin/auth/change_fp.html', + {'cp_form': cp_form}) + else: + return exc.HTTPNotFound('User not found') -- cgit v1.2.3 From f85909c061a6cff211cf27f46879ad096ae7852f Mon Sep 17 00:00:00 2001 From: Caleb Forbes Davis V Date: Sun, 28 Aug 2011 21:41:42 -0500 Subject: needed to access email_sender_address through mg_globals.app_config instead of mg_globals.email_sender_address. --- mediagoblin/auth/lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index df93b666..31dc4b7f 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -146,7 +146,7 @@ def send_fp_verification_email(user,request): # TODO: There is no error handling in place send_email( - mg_globals.email_sender_address, + mg_globals.app_config['email_sender_address'], [user['email']], 'GNU MediaGoblin - Change forgotten password!', rendered_email) -- cgit v1.2.3 From 24966c43bddbd291c4a067568c50fafad8b6f295 Mon Sep 17 00:00:00 2001 From: Caleb Forbes Davis V Date: Sun, 28 Aug 2011 22:57:51 -0500 Subject: Avoids informing browser whether the username or email is a match - pretends to have sent the email with the URL to change the password regardless of whether or not the email was actually sent. This avoids leaking user information to the browser --- mediagoblin/auth/views.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 50276442..7ee89dfb 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -204,10 +204,7 @@ def forgot_password(request): {'$or': [{'username': request.POST['username']}, {'email': request.POST['username']}]}) - if not user: - fp_form.username.errors.append( - u"Sorry, the username doesn't exists") - else: + if user: user['fp_verification_key'] = unicode(uuid.uuid4()) user['fp_token_expire'] = datetime.datetime.now() + \ datetime.timedelta(days=10) @@ -215,7 +212,8 @@ def forgot_password(request): send_fp_verification_email(user, request) - return redirect(request, 'mediagoblin.auth.fp_email_sent') + # do not reveal whether or not there is a matching user, just move along + return redirect(request, 'mediagoblin.auth.fp_email_sent') return render_to_response( request, -- cgit v1.2.3 From e1105f5dcb7d6164fd318872f05c0c239b968a73 Mon Sep 17 00:00:00 2001 From: Caleb Forbes Davis V Date: Mon, 29 Aug 2011 00:00:59 -0500 Subject: Generalizes error model for change password verification - 404s instead of 'user not found' will limit leaking user profile information to the browser. - Also fixed the wording on the login page to make it clear you are changing the password, not sending yourself your old one! --- mediagoblin/auth/views.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 7ee89dfb..589d87cf 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -226,18 +226,19 @@ def verify_forgot_password(request): # If we don't have userid and token parameters, we can't do anything;404 if (not request.GET.has_key('userid') or not request.GET.has_key('token')): - return exc.HTTPNotFound('You must provide userid and token') + return render_404(request) # check if it's a valid Id try: user = request.db.User.find_one( {'_id': ObjectId(unicode(request.GET['userid']))}) except InvalidId: - return exc.HTTPNotFound('Invalid id') + return render_404(request) # check if we have a real user and correct token if (user and - user['fp_verification_key'] == unicode(request.GET['token'])): + user['fp_verification_key'] == unicode(request.GET['token']) and + datetime.datetime.now() < user['fp_token_expire']): cp_form = auth_forms.ChangePassForm(request.GET) return render_to_response( @@ -245,27 +246,30 @@ def verify_forgot_password(request): 'mediagoblin/auth/change_fp.html', {'cp_form': cp_form}) # in case there is a valid id but no user whit that id in the db + # or the token expired else: - return exc.HTTPNotFound('User not found') + return render_404(request) if request.method == 'POST': # verification doing here to prevent POST values modification try: user = request.db.User.find_one( {'_id': ObjectId(unicode(request.POST['userid']))}) except InvalidId: - return exc.HTTPNotFound('Invalid id') + return render_404(request) cp_form = auth_forms.ChangePassForm(request.POST) # verification doing here to prevent POST values modification # if token and id are correct they are able to change their password if (user and - user['fp_verification_key'] == unicode(request.POST['token'])): + user['fp_verification_key'] == unicode(request.POST['token']) and + datetime.datetime.now() < user['fp_token_expire']): if cp_form.validate(): user['pw_hash'] = auth_lib.bcrypt_gen_password_hash( request.POST['password']) user['fp_verification_key'] = None + user['fp_token_expire'] = None user.save() return redirect(request, @@ -276,4 +280,4 @@ def verify_forgot_password(request): 'mediagoblin/auth/change_fp.html', {'cp_form': cp_form}) else: - return exc.HTTPNotFound('User not found') + return render_404(request) -- cgit v1.2.3 From 04a7b06d613dd3ab90cde4eb268087e28d92017c Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Mon, 29 Aug 2011 10:43:11 -0500 Subject: Giving schendje some auth registration descriptions so he can style them! --- mediagoblin/auth/forms.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index 917909c5..d1f3c5dc 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -24,21 +24,29 @@ class RegistrationForm(wtforms.Form): _('Username'), [wtforms.validators.Required(), wtforms.validators.Length(min=3, max=30), - wtforms.validators.Regexp(r'^\w+$')]) + wtforms.validators.Regexp(r'^\w+$')], + description=_( + u"This is the name other users will identify you with.")) password = wtforms.PasswordField( _('Password'), [wtforms.validators.Required(), wtforms.validators.Length(min=6, max=30), wtforms.validators.EqualTo( 'confirm_password', - _('Passwords must match.'))]) + _('Passwords must match.'))], + description=_( + u"Try to use a strong password!")) confirm_password = wtforms.PasswordField( _('Confirm password'), - [wtforms.validators.Required()]) + [wtforms.validators.Required()], + description=_( + u"Type it again here to make sure there are no spelling mistakes.")) email = wtforms.TextField( _('Email address'), [wtforms.validators.Required(), - wtforms.validators.Email()]) + wtforms.validators.Email()], + description=_( + u"Your email will never be published.")) class LoginForm(wtforms.Form): -- cgit v1.2.3 From 12a100e4d8bdda7bd2353403a7e08e3a94669498 Mon Sep 17 00:00:00 2001 From: Will Kahn-Greene Date: Thu, 1 Sep 2011 20:49:54 -0400 Subject: 508. Updates copyright/license information --- mediagoblin/auth/__init__.py | 2 +- mediagoblin/auth/forms.py | 2 +- mediagoblin/auth/lib.py | 2 +- mediagoblin/auth/routing.py | 2 +- mediagoblin/auth/views.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/__init__.py b/mediagoblin/auth/__init__.py index c129cbf8..ba347c69 100644 --- a/mediagoblin/auth/__init__.py +++ b/mediagoblin/auth/__init__.py @@ -1,5 +1,5 @@ # GNU MediaGoblin -- federated, autonomous media hosting -# Copyright (C) 2011 Free Software Foundation, Inc +# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index d1f3c5dc..daf7b993 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -1,5 +1,5 @@ # GNU MediaGoblin -- federated, autonomous media hosting -# Copyright (C) 2011 Free Software Foundation, Inc +# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index 6d1aec49..89cfb6ff 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -1,5 +1,5 @@ # GNU MediaGoblin -- federated, autonomous media hosting -# Copyright (C) 2011 Free Software Foundation, Inc +# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index 9547b3ea..76c7ceed 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -1,5 +1,5 @@ # GNU MediaGoblin -- federated, autonomous media hosting -# Copyright (C) 2011 Free Software Foundation, Inc +# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 48c5937c..1b942280 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -1,5 +1,5 @@ # GNU MediaGoblin -- federated, autonomous media hosting -# Copyright (C) 2011 Free Software Foundation, Inc +# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by -- cgit v1.2.3 From 6be33a778098e38b4951dd358c5016e9fcd280e6 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sun, 4 Sep 2011 22:26:57 -0500 Subject: Removing description field cruft that mostly existed for testing purposes. :) --- mediagoblin/auth/forms.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index daf7b993..1dfaf095 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -24,18 +24,14 @@ class RegistrationForm(wtforms.Form): _('Username'), [wtforms.validators.Required(), wtforms.validators.Length(min=3, max=30), - wtforms.validators.Regexp(r'^\w+$')], - description=_( - u"This is the name other users will identify you with.")) + wtforms.validators.Regexp(r'^\w+$')]) password = wtforms.PasswordField( _('Password'), [wtforms.validators.Required(), wtforms.validators.Length(min=6, max=30), wtforms.validators.EqualTo( 'confirm_password', - _('Passwords must match.'))], - description=_( - u"Try to use a strong password!")) + _('Passwords must match.'))]) confirm_password = wtforms.PasswordField( _('Confirm password'), [wtforms.validators.Required()], @@ -44,9 +40,7 @@ class RegistrationForm(wtforms.Form): email = wtforms.TextField( _('Email address'), [wtforms.validators.Required(), - wtforms.validators.Email()], - description=_( - u"Your email will never be published.")) + wtforms.validators.Email()]) class LoginForm(wtforms.Form): -- cgit v1.2.3 From 8d1c9863b6541e811b0168cca29c3dc33f8b6cf1 Mon Sep 17 00:00:00 2001 From: Caleb Forbes Davis V Date: Mon, 5 Sep 2011 14:02:23 -0500 Subject: refactors verify_forgot_password --- mediagoblin/auth/views.py | 113 ++++++++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 58 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 589d87cf..7ffa7416 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -222,62 +222,59 @@ def forgot_password(request): def verify_forgot_password(request): - if request.method == 'GET': - # If we don't have userid and token parameters, we can't do anything;404 - if (not request.GET.has_key('userid') or - not request.GET.has_key('token')): - return render_404(request) - - # check if it's a valid Id - try: - user = request.db.User.find_one( - {'_id': ObjectId(unicode(request.GET['userid']))}) - except InvalidId: - return render_404(request) - - # check if we have a real user and correct token - if (user and - user['fp_verification_key'] == unicode(request.GET['token']) and - datetime.datetime.now() < user['fp_token_expire']): - cp_form = auth_forms.ChangePassForm(request.GET) - - return render_to_response( - request, - 'mediagoblin/auth/change_fp.html', - {'cp_form': cp_form}) - # in case there is a valid id but no user whit that id in the db - # or the token expired - else: - return render_404(request) - if request.method == 'POST': - # verification doing here to prevent POST values modification - try: - user = request.db.User.find_one( - {'_id': ObjectId(unicode(request.POST['userid']))}) - except InvalidId: - return render_404(request) - - cp_form = auth_forms.ChangePassForm(request.POST) - - # verification doing here to prevent POST values modification - # if token and id are correct they are able to change their password - if (user and - user['fp_verification_key'] == unicode(request.POST['token']) and - datetime.datetime.now() < user['fp_token_expire']): - - if cp_form.validate(): - user['pw_hash'] = auth_lib.bcrypt_gen_password_hash( - request.POST['password']) - user['fp_verification_key'] = None - user['fp_token_expire'] = None - user.save() - - return redirect(request, - 'mediagoblin.auth.fp_changed_success') - else: - return render_to_response( - request, - 'mediagoblin/auth/change_fp.html', - {'cp_form': cp_form}) + # get session variables, and specifically check for presence of token + mysession = _process_for_token(request) + if not mysession['token_complete']: + return render_404(request) + + session_token = mysession['vars']['token'] + session_userid = mysession['vars']['userid'] + session_vars = mysession['vars'] + + # check if it's a valid Id + try: + user = request.db.User.find_one( + {'_id': ObjectId(unicode(session_userid))}) + except InvalidId: + return render_404(request) + + # check if we have a real user and correct token + if (user and user['fp_verification_key'] == unicode(session_token) and + datetime.datetime.now() < user['fp_token_expire']): + cp_form = auth_forms.ChangePassForm(session_vars) + + if request.method == 'POST' and cp_form.validate(): + user['pw_hash'] = auth_lib.bcrypt_gen_password_hash( + request.POST['password']) + user['fp_verification_key'] = None + user['fp_token_expire'] = None + user.save() + + return redirect(request, 'mediagoblin.auth.fp_changed_success') else: - return render_404(request) + return render_to_response(request, + 'mediagoblin/auth/change_fp.html', + {'cp_form': cp_form}) + # in case there is a valid id but no user whit that id in the db + # or the token expired + else: + return render_404(request) + + +def _process_for_token(request): + """ + Checks for tokens in session without prior knowledge of request method + + For now, returns whether the userid and token session variables exist, and + the session variables in a hash. Perhaps an object is warranted? + """ + # retrieve the session variables + if request.method == 'GET': + session_vars = request.GET + else: + session_vars = request.POST + + mysession = {'vars': session_vars, + 'token_complete': session_vars.has_key('userid') and + session_vars.has_key('token')} + return mysession -- cgit v1.2.3 From 4bcaf9f32ab7e125a8db8deece4f292fed71e291 Mon Sep 17 00:00:00 2001 From: Caleb Forbes Davis V Date: Mon, 5 Sep 2011 18:57:06 -0500 Subject: for readability, and adds unit test for expired token --- mediagoblin/auth/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 7ffa7416..c18bfa34 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -224,7 +224,7 @@ def forgot_password(request): def verify_forgot_password(request): # get session variables, and specifically check for presence of token mysession = _process_for_token(request) - if not mysession['token_complete']: + if not mysession['has_userid_and_token']: return render_404(request) session_token = mysession['vars']['token'] @@ -275,6 +275,6 @@ def _process_for_token(request): session_vars = request.POST mysession = {'vars': session_vars, - 'token_complete': session_vars.has_key('userid') and + 'has_userid_and_token': session_vars.has_key('userid') and session_vars.has_key('token')} return mysession -- cgit v1.2.3 From 63bf10f9a635b012e07f65ca5ceccc6845551143 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 7 Sep 2011 19:37:25 -0500 Subject: Adjusting spacing between function arguments --- mediagoblin/auth/lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index 31dc4b7f..abe8ce33 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -127,7 +127,7 @@ EMAIL_FP_VERIFICATION_TEMPLATE = ( u"http://{host}{uri}?" u"userid={userid}&token={fp_verification_key}") -def send_fp_verification_email(user,request): +def send_fp_verification_email(user, request): """ Send the verification email to users to change their password. -- cgit v1.2.3 From daa26200c7e0ef9683af641385504e6b2de403ba Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 7 Sep 2011 19:40:00 -0500 Subject: Changing the forgot password urls so they all start under /auth/forgot_password/ --- mediagoblin/auth/routing.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index 14e87133..399ed8d2 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -31,15 +31,15 @@ auth_routes = [ '/resend_verification_success/', template='mediagoblin/auth/resent_verification_email.html', controller='mediagoblin.views:simple_template_render'), - Route('mediagoblin.auth.forgot_password', '/forgotpass/', + Route('mediagoblin.auth.forgot_password', '/forgot_password/', controller='mediagoblin.auth.views:forgot_password'), - Route('mediagoblin.auth.verify_forgot_password', '/verifyforgotpass/', + Route('mediagoblin.auth.verify_forgot_password', '/forgot_password/verify/', controller='mediagoblin.auth.views:verify_forgot_password'), Route('mediagoblin.auth.fp_changed_success', - '/fp_changed_success/', + '/forgot_password/changed_success/', template='mediagoblin/auth/fp_changed_success.html', controller='mediagoblin.views:simple_template_render'), Route('mediagoblin.auth.fp_email_sent', - '/fp_email_sent/', + '/forgot_password/email_sent/', template='mediagoblin/auth/fp_email_sent.html', controller='mediagoblin.views:simple_template_render')] -- cgit v1.2.3 From 34fddf47f0b4f7cfa9fbd865bd9eb8ae96913ce4 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 7 Sep 2011 19:42:56 -0500 Subject: Resent verification email template and view aren't used anymore. Removing! --- mediagoblin/auth/routing.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index 76c7ceed..edd21be7 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -26,8 +26,4 @@ auth_routes = [ Route('mediagoblin.auth.verify_email', '/verify_email/', controller='mediagoblin.auth.views:verify_email'), Route('mediagoblin.auth.resend_verification', '/resend_verification/', - controller='mediagoblin.auth.views:resend_activation'), - Route('mediagoblin.auth.resend_verification_success', - '/resend_verification_success/', - template='mediagoblin/auth/resent_verification_email.html', - controller='mediagoblin.views:simple_template_render')] + controller='mediagoblin.auth.views:resend_activation')] -- cgit v1.2.3 From d1a64326456d67d43ac99f28c2c45c7e9996be07 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 7 Sep 2011 23:23:44 -0500 Subject: Avoiding using '$or' query modifier since that's newer-mongo only. --- mediagoblin/auth/views.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index c18bfa34..666426e6 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -200,9 +200,12 @@ def forgot_password(request): fp_form = auth_forms.ForgotPassForm(request.POST) if request.method == 'POST' and fp_form.validate(): - user = request.db.User.one( - {'$or': [{'username': request.POST['username']}, - {'email': request.POST['username']}]}) + # '$or' not available till mongodb 1.5.3 + user = request.db.User.find_one( + {'username': request.POST['username']}) + if not user: + user = request.db.User.find_one( + {'email': request.POST['username']}) if user: user['fp_verification_key'] = unicode(uuid.uuid4()) -- cgit v1.2.3 From 2c9e8184a44336689b8d3e0d01b17b15dfbcb791 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 7 Sep 2011 23:25:46 -0500 Subject: Adjusting indentation a bit --- mediagoblin/auth/views.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 666426e6..098443b8 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -219,9 +219,9 @@ def forgot_password(request): return redirect(request, 'mediagoblin.auth.fp_email_sent') return render_to_response( - request, - 'mediagoblin/auth/forgot_password.html', - {'fp_form': fp_form}) + request, + 'mediagoblin/auth/forgot_password.html', + {'fp_form': fp_form}) def verify_forgot_password(request): @@ -277,7 +277,9 @@ def _process_for_token(request): else: session_vars = request.POST - mysession = {'vars': session_vars, - 'has_userid_and_token': session_vars.has_key('userid') and - session_vars.has_key('token')} + mysession = { + 'vars': session_vars, + 'has_userid_and_token': + session_vars.has_key('userid') and session_vars.has_key('token')} + return mysession -- cgit v1.2.3 From 73fffbb8b0b37d642f7dc996bbec8fdf7d4e3e8b Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 7 Sep 2011 23:32:15 -0500 Subject: Adding additional check that verification key exists, and updating indentation --- mediagoblin/auth/views.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 098443b8..dd693892 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -242,8 +242,10 @@ def verify_forgot_password(request): return render_404(request) # check if we have a real user and correct token - if (user and user['fp_verification_key'] == unicode(session_token) and - datetime.datetime.now() < user['fp_token_expire']): + if ((user and user['fp_verification_key'] and + user['fp_verification_key'] == unicode(session_token) and + datetime.datetime.now() < user['fp_token_expire'])): + cp_form = auth_forms.ChangePassForm(session_vars) if request.method == 'POST' and cp_form.validate(): @@ -255,9 +257,11 @@ def verify_forgot_password(request): return redirect(request, 'mediagoblin.auth.fp_changed_success') else: - return render_to_response(request, - 'mediagoblin/auth/change_fp.html', - {'cp_form': cp_form}) + return render_to_response( + request, + 'mediagoblin/auth/change_fp.html', + {'cp_form': cp_form}) + # in case there is a valid id but no user whit that id in the db # or the token expired else: -- cgit v1.2.3 From a85a21103bb5e3d4b5a6e454cce1d2011372c867 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 7 Sep 2011 23:45:14 -0500 Subject: If the user hasn't verified their email or account inactive give a special warning --- mediagoblin/auth/views.py | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index dd693892..1c010372 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -208,12 +208,27 @@ def forgot_password(request): {'email': request.POST['username']}) if user: - user['fp_verification_key'] = unicode(uuid.uuid4()) - user['fp_token_expire'] = datetime.datetime.now() + \ - datetime.timedelta(days=10) - user.save() + if user['email_verified'] and user['status'] == 'active': + user['fp_verification_key'] = unicode(uuid.uuid4()) + user['fp_token_expire'] = datetime.datetime.now() + \ + datetime.timedelta(days=10) + user.save() + + send_fp_verification_email(user, request) + else: + # special case... we can't send the email because the + # username is inactive / hasn't verified their email + messages.add_message( + request, + messages.WARNING, + _("Could not send password recovery email as " + "your username is inactive or your account's " + "email address has not been verified.")) + + return redirect( + request, 'mediagoblin.user_pages.user_home', + user=user['username']) - send_fp_verification_email(user, request) # do not reveal whether or not there is a matching user, just move along return redirect(request, 'mediagoblin.auth.fp_email_sent') @@ -244,7 +259,8 @@ def verify_forgot_password(request): # check if we have a real user and correct token if ((user and user['fp_verification_key'] and user['fp_verification_key'] == unicode(session_token) and - datetime.datetime.now() < user['fp_token_expire'])): + datetime.datetime.now() < user['fp_token_expire'] + and user['email_verified'] and user['status'] == 'active')): cp_form = auth_forms.ChangePassForm(session_vars) -- cgit v1.2.3 From daf029646e4f56798f65748b28f6f815602dc174 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 7 Sep 2011 23:46:41 -0500 Subject: Also nullify verification key after verifying in the email confirmation step --- mediagoblin/auth/views.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 1c010372..0cb3963c 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -154,7 +154,10 @@ def verify_email(request): if user and user['verification_key'] == unicode(request.GET['token']): user['status'] = u'active' user['email_verified'] = True + user[u'verification_key'] = None + user.save() + messages.add_message( request, messages.SUCCESS, -- cgit v1.2.3 From 4185e644f4209fbc21b3a066d17fefc9d68effef Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 7 Sep 2011 23:48:10 -0500 Subject: Keys in mongodb should be unicode, here... --- mediagoblin/auth/views.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 0cb3963c..5fabf40b 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -152,8 +152,8 @@ def verify_email(request): {'_id': ObjectId(unicode(request.GET['userid']))}) if user and user['verification_key'] == unicode(request.GET['token']): - user['status'] = u'active' - user['email_verified'] = True + user[u'status'] = u'active' + user[u'email_verified'] = True user[u'verification_key'] = None user.save() @@ -180,7 +180,7 @@ def resend_activation(request): Resend the activation email. """ - request.user['verification_key'] = unicode(uuid.uuid4()) + request.user[u'verification_key'] = unicode(uuid.uuid4()) request.user.save() send_verification_email(request.user, request) @@ -212,8 +212,8 @@ def forgot_password(request): if user: if user['email_verified'] and user['status'] == 'active': - user['fp_verification_key'] = unicode(uuid.uuid4()) - user['fp_token_expire'] = datetime.datetime.now() + \ + user[u'fp_verification_key'] = unicode(uuid.uuid4()) + user[u'fp_token_expire'] = datetime.datetime.now() + \ datetime.timedelta(days=10) user.save() @@ -268,10 +268,10 @@ def verify_forgot_password(request): cp_form = auth_forms.ChangePassForm(session_vars) if request.method == 'POST' and cp_form.validate(): - user['pw_hash'] = auth_lib.bcrypt_gen_password_hash( + user[u'pw_hash'] = auth_lib.bcrypt_gen_password_hash( request.POST['password']) - user['fp_verification_key'] = None - user['fp_token_expire'] = None + user[u'fp_verification_key'] = None + user[u'fp_token_expire'] = None user.save() return redirect(request, 'mediagoblin.auth.fp_changed_success') -- cgit v1.2.3 From 961fe381635d80595084428123bee2e6f29f7e62 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 7 Sep 2011 23:51:41 -0500 Subject: Adding a small docstring --- mediagoblin/auth/views.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 5fabf40b..ac3f621e 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -243,6 +243,10 @@ def forgot_password(request): def verify_forgot_password(request): + """ + Check the forgot-password verification and possibly let the user + change their password because of it. + """ # get session variables, and specifically check for presence of token mysession = _process_for_token(request) if not mysession['has_userid_and_token']: -- cgit v1.2.3 From f7ab66707c4d5ef5941e13131dbf9ce2a8c7a875 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Thu, 8 Sep 2011 08:10:27 -0500 Subject: Renaming request.[GET|POST] as formdata instead of session; that's more accurate. --- mediagoblin/auth/views.py | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index ac3f621e..000f7681 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -247,29 +247,29 @@ def verify_forgot_password(request): Check the forgot-password verification and possibly let the user change their password because of it. """ - # get session variables, and specifically check for presence of token - mysession = _process_for_token(request) - if not mysession['has_userid_and_token']: + # get form data variables, and specifically check for presence of token + formdata = _process_for_token(request) + if not formdata['has_userid_and_token']: return render_404(request) - session_token = mysession['vars']['token'] - session_userid = mysession['vars']['userid'] - session_vars = mysession['vars'] + formdata_token = formdata['vars']['token'] + formdata_userid = formdata['vars']['userid'] + formdata_vars = formdata['vars'] # check if it's a valid Id try: user = request.db.User.find_one( - {'_id': ObjectId(unicode(session_userid))}) + {'_id': ObjectId(unicode(formdata_userid))}) except InvalidId: return render_404(request) # check if we have a real user and correct token if ((user and user['fp_verification_key'] and - user['fp_verification_key'] == unicode(session_token) and + user['fp_verification_key'] == unicode(formdata_token) and datetime.datetime.now() < user['fp_token_expire'] and user['email_verified'] and user['status'] == 'active')): - cp_form = auth_forms.ChangePassForm(session_vars) + cp_form = auth_forms.ChangePassForm(formdata_vars) if request.method == 'POST' and cp_form.validate(): user[u'pw_hash'] = auth_lib.bcrypt_gen_password_hash( @@ -293,20 +293,20 @@ def verify_forgot_password(request): def _process_for_token(request): """ - Checks for tokens in session without prior knowledge of request method + Checks for tokens in formdata without prior knowledge of request method - For now, returns whether the userid and token session variables exist, and - the session variables in a hash. Perhaps an object is warranted? + For now, returns whether the userid and token formdata variables exist, and + the formdata variables in a hash. Perhaps an object is warranted? """ - # retrieve the session variables + # retrieve the formdata variables if request.method == 'GET': - session_vars = request.GET + formdata_vars = request.GET else: - session_vars = request.POST + formdata_vars = request.POST - mysession = { - 'vars': session_vars, + formdata = { + 'vars': formdata_vars, 'has_userid_and_token': - session_vars.has_key('userid') and session_vars.has_key('token')} + formdata_vars.has_key('userid') and formdata_vars.has_key('token')} - return mysession + return formdata -- cgit v1.2.3 From bf33272f03a28c86b91750fed354b75062f516e6 Mon Sep 17 00:00:00 2001 From: Elrond Date: Fri, 30 Sep 2011 22:27:47 +0200 Subject: Give debug message in email debug mode If the server is running in email debug mode (current default), users have often asked where the mail is. So tell them in the web browser that their mail is on the console. --- mediagoblin/auth/views.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index f67f0588..b6f38fec 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -30,6 +30,19 @@ from mediagoblin.auth.lib import send_verification_email, \ send_fp_verification_email +def email_debug_message(request): + """ + If the server is running in email debug mode (which is + the current default), give a debug message to the user + so that they have an idea where to find their email. + """ + if mg_globals.app_config['email_debug_mode']: + # DEBUG message, no need to translate + messages.add_message(request, messages.DEBUG, + u"This instance is running in email debug mode. " + u"The email will be on the console of the server process.") + + def register(request): """ Your classic registration view! @@ -78,6 +91,7 @@ def register(request): request.session.save() # send verification email + email_debug_message(request) send_verification_email(user, request) # redirect the user to their homepage... there will be a @@ -184,6 +198,7 @@ def resend_activation(request): request.user[u'verification_key'] = unicode(uuid.uuid4()) request.user.save() + email_debug_message(request) send_verification_email(request.user, request) messages.add_message( @@ -204,6 +219,11 @@ def forgot_password(request): fp_form = auth_forms.ForgotPassForm(request.POST) if request.method == 'POST' and fp_form.validate(): + + # Here, so it doesn't depend on the actual mail being sent + # and thus doesn't reveal, wether mail was sent. + email_debug_message(request) + # '$or' not available till mongodb 1.5.3 user = request.db.User.find_one( {'username': request.POST['username']}) -- cgit v1.2.3 From ae3bc7fabf8e0abb5f3d8b6534ca451890bbe90b Mon Sep 17 00:00:00 2001 From: Aaron Williamson Date: Sat, 1 Oct 2011 09:31:42 -0400 Subject: Moved common, translation, template, and url code out of util.py and into tools/[file].py --- mediagoblin/auth/forms.py | 2 +- mediagoblin/auth/lib.py | 3 ++- mediagoblin/auth/views.py | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index 6339b4a3..a932ad26 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -17,7 +17,7 @@ import wtforms import re -from mediagoblin.util import fake_ugettext_passthrough as _ +from mediagoblin.tools.translate import fake_ugettext_passthrough as _ class RegistrationForm(wtforms.Form): diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index d7d351a5..bf5a2399 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -19,7 +19,8 @@ import random import bcrypt -from mediagoblin.util import send_email, render_template +from mediagoblin.util import send_email +from mediagoblin.tools.template import render_template from mediagoblin import mg_globals diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index f67f0588..9bfa93cf 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -22,7 +22,7 @@ from webob import exc from mediagoblin import messages from mediagoblin import mg_globals from mediagoblin.util import render_to_response, redirect, render_404 -from mediagoblin.util import pass_to_ugettext as _ +from mediagoblin.tools.translate import pass_to_ugettext as _ from mediagoblin.db.util import ObjectId, InvalidId from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms -- cgit v1.2.3 From 152a3bfaa36d58e44979f217c5799531f780250f Mon Sep 17 00:00:00 2001 From: Aaron Williamson Date: Sat, 1 Oct 2011 18:05:44 -0400 Subject: Finished splitting util.py into separate files. --- mediagoblin/auth/lib.py | 2 +- mediagoblin/auth/views.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index bf5a2399..4c57ef88 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -19,7 +19,7 @@ import random import bcrypt -from mediagoblin.util import send_email +from mediagoblin.tools.mail import send_email from mediagoblin.tools.template import render_template from mediagoblin import mg_globals diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 9bfa93cf..88c91565 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -21,7 +21,7 @@ from webob import exc from mediagoblin import messages from mediagoblin import mg_globals -from mediagoblin.util import render_to_response, redirect, render_404 +from mediagoblin.tools.response import render_to_response, redirect, render_404 from mediagoblin.tools.translate import pass_to_ugettext as _ from mediagoblin.db.util import ObjectId, InvalidId from mediagoblin.auth import lib as auth_lib -- cgit v1.2.3 From 243c3843bd574129caa7663e25d1a843b2d2dd30 Mon Sep 17 00:00:00 2001 From: Nathan Yergler Date: Sat, 1 Oct 2011 15:10:02 -0700 Subject: Whitespace and formatting cleanup. * Removed trailing whitespace * Line length < 80 where possible * Honor conventions on number of blank lines * Honor conventions about spaces around :, = --- mediagoblin/auth/forms.py | 8 ++++---- mediagoblin/auth/lib.py | 3 ++- mediagoblin/auth/routing.py | 3 ++- mediagoblin/auth/views.py | 3 +-- 4 files changed, 9 insertions(+), 8 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index 6339b4a3..aadb5888 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -59,9 +59,10 @@ class ForgotPassForm(wtforms.Form): 'Username or email', [wtforms.validators.Required()]) - def validate_username(form,field): - if not (re.match(r'^\w+$',field.data) or - re.match(r'^.+@[^.].*\.[a-z]{2,10}$',field.data, re.IGNORECASE)): + def validate_username(form, field): + if not (re.match(r'^\w+$', field.data) or + re.match(r'^.+@[^.].*\.[a-z]{2,10}$', field.data, + re.IGNORECASE)): raise wtforms.ValidationError(u'Incorrect input') @@ -82,4 +83,3 @@ class ChangePassForm(wtforms.Form): token = wtforms.HiddenField( '', [wtforms.validators.Required()]) - diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index d7d351a5..0ecccbb5 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -93,6 +93,7 @@ EMAIL_VERIFICATION_TEMPLATE = ( u"http://{host}{uri}?" u"userid={userid}&token={verification_key}") + def send_verification_email(user, request): """ Send the verification email to users to activate their accounts. @@ -127,6 +128,7 @@ EMAIL_FP_VERIFICATION_TEMPLATE = ( u"http://{host}{uri}?" u"userid={userid}&token={fp_verification_key}") + def send_fp_verification_email(user, request): """ Send the verification email to users to change their password. @@ -150,4 +152,3 @@ def send_fp_verification_email(user, request): [user['email']], 'GNU MediaGoblin - Change forgotten password!', rendered_email) - diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index 912d89fa..365ccfaa 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -33,7 +33,8 @@ auth_routes = [ controller='mediagoblin.views:simple_template_render'), Route('mediagoblin.auth.forgot_password', '/forgot_password/', controller='mediagoblin.auth.views:forgot_password'), - Route('mediagoblin.auth.verify_forgot_password', '/forgot_password/verify/', + Route('mediagoblin.auth.verify_forgot_password', + '/forgot_password/verify/', controller='mediagoblin.auth.views:verify_forgot_password'), Route('mediagoblin.auth.fp_changed_success', '/forgot_password/changed_success/', diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index f67f0588..afcfcf1e 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -233,8 +233,7 @@ def forgot_password(request): request, 'mediagoblin.user_pages.user_home', user=user['username']) - - # do not reveal whether or not there is a matching user, just move along + # do not reveal whether or not there is a matching user return redirect(request, 'mediagoblin.auth.fp_email_sent') return render_to_response( -- cgit v1.2.3 From 285ffeddf3542201b83072d3be544c85e9c487c2 Mon Sep 17 00:00:00 2001 From: Nathan Yergler Date: Sat, 1 Oct 2011 15:10:41 -0700 Subject: has_key is deprecated, converting uses to use "in" operator. --- mediagoblin/auth/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index afcfcf1e..adf2c315 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -146,7 +146,7 @@ def verify_email(request): you are lucky :) """ # If we don't have userid and token parameters, we can't do anything; 404 - if not request.GET.has_key('userid') or not request.GET.has_key('token'): + if not 'userid' in request.GET or not 'token' in request.GET: return render_404(request) user = request.db.User.find_one( @@ -307,6 +307,6 @@ def _process_for_token(request): formdata = { 'vars': formdata_vars, 'has_userid_and_token': - formdata_vars.has_key('userid') and formdata_vars.has_key('token')} + 'userid' in formdata_vars and 'token' in formdata_vars} return formdata -- cgit v1.2.3 From 84a7e7706c8b1239f8fd52c604afbb10c776ac04 Mon Sep 17 00:00:00 2001 From: Aaron Williamson Date: Sat, 1 Oct 2011 19:49:56 -0400 Subject: Display and error and redirect to login page if unauthenticated user tries to access resend_verification. --- mediagoblin/auth/views.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index b6f38fec..d91a1f25 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -21,7 +21,7 @@ from webob import exc from mediagoblin import messages from mediagoblin import mg_globals -from mediagoblin.util import render_to_response, redirect, render_404 +from mediagoblin.util import render_to_response, redirect, render_404, setup_user_in_request from mediagoblin.util import pass_to_ugettext as _ from mediagoblin.db.util import ObjectId, InvalidId from mediagoblin.auth import lib as auth_lib @@ -195,9 +195,18 @@ def resend_activation(request): Resend the activation email. """ + + if not request.GET.has_key('userid') or not request.GET.has_key('token'): + messages.add_message( + request, + messages.ERROR, + _('You must be logged in so we know who to send the email to!')) + + return redirect(request, "/auth/login") + request.user[u'verification_key'] = unicode(uuid.uuid4()) request.user.save() - + email_debug_message(request) send_verification_email(request.user, request) -- cgit v1.2.3 From 3b74ce94ff90e0bd5b214891becb62a6fc503434 Mon Sep 17 00:00:00 2001 From: Aaron Williamson Date: Mon, 3 Oct 2011 19:59:28 -0400 Subject: Check request.user to determine if user is logged in. --- mediagoblin/auth/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index d91a1f25..fdc5aec8 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -196,7 +196,7 @@ def resend_activation(request): Resend the activation email. """ - if not request.GET.has_key('userid') or not request.GET.has_key('token'): + if request.user is None: messages.add_message( request, messages.ERROR, -- cgit v1.2.3 From 7903a14f986b5bf37a45d5ec3b156c21a1cada72 Mon Sep 17 00:00:00 2001 From: Aaron Williamson Date: Mon, 3 Oct 2011 20:25:11 -0400 Subject: Make sure user isn't already verified before resending verification. --- mediagoblin/auth/views.py | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 798fae25..dc4c540b 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -196,6 +196,14 @@ def resend_activation(request): Resend the activation email. """ + if request.user["email_verified"]: + messages.add_message( + request, + messages.ERROR, + _("You've already verified your email address!")) + + return redirect(request, "mediagoblin.user_pages.user_home", user=request.user['username']) + if request.user is None: messages.add_message( request, -- cgit v1.2.3 From 2fe6991660cd1a20f9117b0cdc88431085eb7490 Mon Sep 17 00:00:00 2001 From: Aaron Williamson Date: Mon, 3 Oct 2011 20:28:48 -0400 Subject: Reverse order of sanity checks: check email_verified after making sure there's a user in the request. --- mediagoblin/auth/views.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index dc4c540b..d8c441ef 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -196,21 +196,21 @@ def resend_activation(request): Resend the activation email. """ - if request.user["email_verified"]: + if request.user is None: messages.add_message( request, messages.ERROR, - _("You've already verified your email address!")) + _('You must be logged in so we know who to send the email to!')) - return redirect(request, "mediagoblin.user_pages.user_home", user=request.user['username']) + return redirect(request, "/auth/login") - if request.user is None: + if request.user["email_verified"]: messages.add_message( request, messages.ERROR, - _('You must be logged in so we know who to send the email to!')) + _("You've already verified your email address!")) - return redirect(request, "/auth/login") + return redirect(request, "mediagoblin.user_pages.user_home", user=request.user['username']) request.user[u'verification_key'] = unicode(uuid.uuid4()) request.user.save() -- cgit v1.2.3 From eabe6b678a98fd06d9cd8463935a3b842f41485c Mon Sep 17 00:00:00 2001 From: Elrond Date: Sun, 13 Nov 2011 19:25:06 +0100 Subject: Dot-Notation for "_id" Note: Migrations can't use "Dot Notation"! Migrations run on pymongo, not mongokit. So they can't use the "Dot Notation". This isn't really a big issue, as migrations are anyway quite mongo specific. --- mediagoblin/auth/lib.py | 4 ++-- mediagoblin/auth/views.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index 653424cc..cf4a2b83 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -109,7 +109,7 @@ def send_verification_email(user, request): 'verification_url': EMAIL_VERIFICATION_TEMPLATE.format( host=request.host, uri=request.urlgen('mediagoblin.auth.verify_email'), - userid=unicode(user['_id']), + userid=unicode(user._id), verification_key=user['verification_key'])}) # TODO: There is no error handling in place @@ -144,7 +144,7 @@ def send_fp_verification_email(user, request): 'verification_url': EMAIL_FP_VERIFICATION_TEMPLATE.format( host=request.host, uri=request.urlgen('mediagoblin.auth.verify_forgot_password'), - userid=unicode(user['_id']), + userid=unicode(user._id), fp_verification_key=user['fp_verification_key'])}) # TODO: There is no error handling in place diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 8888d23c..8412b81c 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -87,7 +87,7 @@ def register(request): user.save(validate=True) # log the user in - request.session['user_id'] = unicode(user['_id']) + request.session['user_id'] = unicode(user._id) request.session.save() # send verification email @@ -122,7 +122,7 @@ def login(request): if user and user.check_login(request.POST['password']): # set up login in session - request.session['user_id'] = unicode(user['_id']) + request.session['user_id'] = unicode(user._id) request.session.save() if request.POST.get('next'): -- cgit v1.2.3 From 5ab3855e1f8fd94058ccea76ef2d5a1d795cc93a Mon Sep 17 00:00:00 2001 From: Jef van Schendel Date: Sun, 20 Nov 2011 01:46:21 +0100 Subject: Slight change to error wording --- mediagoblin/auth/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 8412b81c..54cb1ab5 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -74,7 +74,7 @@ def register(request): extra_validation_passes = False if users_with_email: register_form.email.errors.append( - _(u'Sorry, that email address has already been taken.')) + _(u'Sorry, a user with that email address already exists.')) extra_validation_passes = False if extra_validation_passes: -- cgit v1.2.3 From 5dbeda8a0f2953aed13521b6e87376327e8302e0 Mon Sep 17 00:00:00 2001 From: Elrond Date: Sun, 20 Nov 2011 20:15:21 +0100 Subject: Fix redirect to logical path redirects should in nearly all cases go to a logical path like 'mediagoblin.auth.login' and not to an absolute path like "/auth/login". --- mediagoblin/auth/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index b3a70d46..d01861d1 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -202,7 +202,7 @@ def resend_activation(request): messages.ERROR, _('You must be logged in so we know who to send the email to!')) - return redirect(request, "/auth/login") + return redirect(request, 'mediagoblin.auth.login') if request.user["email_verified"]: messages.add_message( -- cgit v1.2.3 From 0d6e5dddeb38f6af7972485ae186532449719243 Mon Sep 17 00:00:00 2001 From: Jef van Schendel Date: Fri, 2 Dec 2011 23:48:40 +0100 Subject: Add show-password checkbox and make it work --- mediagoblin/auth/forms.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index dcb6766c..4cd3e9d8 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -29,15 +29,7 @@ class RegistrationForm(wtforms.Form): password = wtforms.PasswordField( _('Password'), [wtforms.validators.Required(), - wtforms.validators.Length(min=6, max=30), - wtforms.validators.EqualTo( - 'confirm_password', - _('Passwords must match.'))]) - confirm_password = wtforms.PasswordField( - _('Confirm password'), - [wtforms.validators.Required()], - description=_( - u"Type it again here to make sure there are no spelling mistakes.")) + wtforms.validators.Length(min=6, max=30)]) email = wtforms.TextField( _('Email address'), [wtforms.validators.Required(), -- cgit v1.2.3 From 5a4e3ff1e2a0f2ed451bc191c1d44bcd694b8e75 Mon Sep 17 00:00:00 2001 From: Elrond Date: Mon, 14 Nov 2011 15:39:57 +0100 Subject: Dot-Notation for Users.username --- mediagoblin/auth/lib.py | 4 ++-- mediagoblin/auth/views.py | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index cf4a2b83..ee1ce12d 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -105,7 +105,7 @@ def send_verification_email(user, request): """ rendered_email = render_template( request, 'mediagoblin/auth/verification_email.txt', - {'username': user['username'], + {'username': user.username, 'verification_url': EMAIL_VERIFICATION_TEMPLATE.format( host=request.host, uri=request.urlgen('mediagoblin.auth.verify_email'), @@ -140,7 +140,7 @@ def send_fp_verification_email(user, request): """ rendered_email = render_template( request, 'mediagoblin/auth/fp_verification_email.txt', - {'username': user['username'], + {'username': user.username, 'verification_url': EMAIL_FP_VERIFICATION_TEMPLATE.format( host=request.host, uri=request.urlgen('mediagoblin.auth.verify_forgot_password'), diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index d01861d1..dab95b17 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -80,7 +80,7 @@ def register(request): if extra_validation_passes: # Create the user user = request.db.User() - user['username'] = username + user.username = username user['email'] = email user['pw_hash'] = auth_lib.bcrypt_gen_password_hash( request.POST['password']) @@ -98,7 +98,7 @@ def register(request): # message waiting for them to verify their email return redirect( request, 'mediagoblin.user_pages.user_home', - user=user['username']) + user=user.username) return render_to_response( request, @@ -186,7 +186,7 @@ def verify_email(request): return redirect( request, 'mediagoblin.user_pages.user_home', - user=user['username']) + user=user.username) def resend_activation(request): @@ -224,7 +224,7 @@ def resend_activation(request): _('Resent your verification email.')) return redirect( request, 'mediagoblin.user_pages.user_home', - user=request.user['username']) + user=request.user.username) def forgot_password(request): @@ -268,7 +268,7 @@ def forgot_password(request): return redirect( request, 'mediagoblin.user_pages.user_home', - user=user['username']) + user=user.username) # do not reveal whether or not there is a matching user return redirect(request, 'mediagoblin.auth.fp_email_sent') -- cgit v1.2.3 From 809cbfc5ab3c999f357c0b4e7b6c89e8a36dc6d2 Mon Sep 17 00:00:00 2001 From: Elrond Date: Mon, 14 Nov 2011 17:22:33 +0100 Subject: Dot-Notation for Users.email --- mediagoblin/auth/lib.py | 4 ++-- mediagoblin/auth/views.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index ee1ce12d..24992094 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -115,7 +115,7 @@ def send_verification_email(user, request): # TODO: There is no error handling in place send_email( mg_globals.app_config['email_sender_address'], - [user['email']], + [user.email], # TODO # Due to the distributed nature of GNU MediaGoblin, we should # find a way to send some additional information about the @@ -150,6 +150,6 @@ def send_fp_verification_email(user, request): # TODO: There is no error handling in place send_email( mg_globals.app_config['email_sender_address'], - [user['email']], + [user.email], 'GNU MediaGoblin - Change forgotten password!', rendered_email) diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index dab95b17..f8e84285 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -81,7 +81,7 @@ def register(request): # Create the user user = request.db.User() user.username = username - user['email'] = email + user.email = email user['pw_hash'] = auth_lib.bcrypt_gen_password_hash( request.POST['password']) user.save(validate=True) -- cgit v1.2.3 From 9047b254f340c16f33183f0d6d68e6c4a5a3c8de Mon Sep 17 00:00:00 2001 From: Elrond Date: Mon, 14 Nov 2011 18:49:21 +0100 Subject: Dot-Notation for Users.pw_hash --- mediagoblin/auth/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index f8e84285..63bf9a91 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -82,7 +82,7 @@ def register(request): user = request.db.User() user.username = username user.email = email - user['pw_hash'] = auth_lib.bcrypt_gen_password_hash( + user.pw_hash = auth_lib.bcrypt_gen_password_hash( request.POST['password']) user.save(validate=True) @@ -309,7 +309,7 @@ def verify_forgot_password(request): cp_form = auth_forms.ChangePassForm(formdata_vars) if request.method == 'POST' and cp_form.validate(): - user[u'pw_hash'] = auth_lib.bcrypt_gen_password_hash( + user.pw_hash = auth_lib.bcrypt_gen_password_hash( request.POST['password']) user[u'fp_verification_key'] = None user[u'fp_token_expire'] = None -- cgit v1.2.3 From 4facc7a0a21a57023f0d3707f1a3483ca7a560c8 Mon Sep 17 00:00:00 2001 From: Elrond Date: Mon, 14 Nov 2011 18:54:52 +0100 Subject: Dot-Notation for Users.email_verified --- mediagoblin/auth/views.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 63bf9a91..2d29d0a5 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -168,7 +168,7 @@ def verify_email(request): if user and user['verification_key'] == unicode(request.GET['token']): user[u'status'] = u'active' - user[u'email_verified'] = True + user.email_verified = True user[u'verification_key'] = None user.save() @@ -249,7 +249,7 @@ def forgot_password(request): {'email': request.POST['username']}) if user: - if user['email_verified'] and user['status'] == 'active': + if user.email_verified and user['status'] == 'active': user[u'fp_verification_key'] = unicode(uuid.uuid4()) user[u'fp_token_expire'] = datetime.datetime.now() + \ datetime.timedelta(days=10) @@ -304,7 +304,7 @@ def verify_forgot_password(request): if ((user and user['fp_verification_key'] and user['fp_verification_key'] == unicode(formdata_token) and datetime.datetime.now() < user['fp_token_expire'] - and user['email_verified'] and user['status'] == 'active')): + and user.email_verified and user['status'] == 'active')): cp_form = auth_forms.ChangePassForm(formdata_vars) -- cgit v1.2.3 From 7a3d00ec217cc3fd44788b9d8c63ab9f7b1d05a7 Mon Sep 17 00:00:00 2001 From: Elrond Date: Mon, 14 Nov 2011 19:01:26 +0100 Subject: Dot-Notation for Users.status --- mediagoblin/auth/views.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 2d29d0a5..caf9835a 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -167,7 +167,7 @@ def verify_email(request): {'_id': ObjectId(unicode(request.GET['userid']))}) if user and user['verification_key'] == unicode(request.GET['token']): - user[u'status'] = u'active' + user.status = u'active' user.email_verified = True user[u'verification_key'] = None @@ -249,7 +249,7 @@ def forgot_password(request): {'email': request.POST['username']}) if user: - if user.email_verified and user['status'] == 'active': + if user.email_verified and user.status == 'active': user[u'fp_verification_key'] = unicode(uuid.uuid4()) user[u'fp_token_expire'] = datetime.datetime.now() + \ datetime.timedelta(days=10) @@ -304,7 +304,7 @@ def verify_forgot_password(request): if ((user and user['fp_verification_key'] and user['fp_verification_key'] == unicode(formdata_token) and datetime.datetime.now() < user['fp_token_expire'] - and user.email_verified and user['status'] == 'active')): + and user.email_verified and user.status == 'active')): cp_form = auth_forms.ChangePassForm(formdata_vars) -- cgit v1.2.3 From 00bb95502e01f8c8fcaa5652889a5ed423051d7c Mon Sep 17 00:00:00 2001 From: Elrond Date: Mon, 14 Nov 2011 19:04:13 +0100 Subject: Dot-Notation for Users.verification_key --- mediagoblin/auth/lib.py | 2 +- mediagoblin/auth/views.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index 24992094..d03f7af0 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -110,7 +110,7 @@ def send_verification_email(user, request): host=request.host, uri=request.urlgen('mediagoblin.auth.verify_email'), userid=unicode(user._id), - verification_key=user['verification_key'])}) + verification_key=user.verification_key)}) # TODO: There is no error handling in place send_email( diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index caf9835a..d7e8d1bf 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -166,10 +166,10 @@ def verify_email(request): user = request.db.User.find_one( {'_id': ObjectId(unicode(request.GET['userid']))}) - if user and user['verification_key'] == unicode(request.GET['token']): + if user and user.verification_key == unicode(request.GET['token']): user.status = u'active' user.email_verified = True - user[u'verification_key'] = None + user.verification_key = None user.save() @@ -212,7 +212,7 @@ def resend_activation(request): return redirect(request, "mediagoblin.user_pages.user_home", user=request.user['username']) - request.user[u'verification_key'] = unicode(uuid.uuid4()) + request.user.verification_key = unicode(uuid.uuid4()) request.user.save() email_debug_message(request) -- cgit v1.2.3 From dc39e4555c9e104ae9d7b38f231a848fe106d1a0 Mon Sep 17 00:00:00 2001 From: Elrond Date: Mon, 14 Nov 2011 19:21:33 +0100 Subject: Dot-Notation for Users.fp_verification_key --- mediagoblin/auth/lib.py | 2 +- mediagoblin/auth/views.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index d03f7af0..c0af3b5b 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -145,7 +145,7 @@ def send_fp_verification_email(user, request): host=request.host, uri=request.urlgen('mediagoblin.auth.verify_forgot_password'), userid=unicode(user._id), - fp_verification_key=user['fp_verification_key'])}) + fp_verification_key=user.fp_verification_key)}) # TODO: There is no error handling in place send_email( diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index d7e8d1bf..633ceef4 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -250,7 +250,7 @@ def forgot_password(request): if user: if user.email_verified and user.status == 'active': - user[u'fp_verification_key'] = unicode(uuid.uuid4()) + user.fp_verification_key = unicode(uuid.uuid4()) user[u'fp_token_expire'] = datetime.datetime.now() + \ datetime.timedelta(days=10) user.save() @@ -301,8 +301,8 @@ def verify_forgot_password(request): return render_404(request) # check if we have a real user and correct token - if ((user and user['fp_verification_key'] and - user['fp_verification_key'] == unicode(formdata_token) and + if ((user and user.fp_verification_key and + user.fp_verification_key == unicode(formdata_token) and datetime.datetime.now() < user['fp_token_expire'] and user.email_verified and user.status == 'active')): @@ -311,7 +311,7 @@ def verify_forgot_password(request): if request.method == 'POST' and cp_form.validate(): user.pw_hash = auth_lib.bcrypt_gen_password_hash( request.POST['password']) - user[u'fp_verification_key'] = None + user.fp_verification_key = None user[u'fp_token_expire'] = None user.save() -- cgit v1.2.3 From 2d540fed8b511c76819a836da3d62875d20b6547 Mon Sep 17 00:00:00 2001 From: Elrond Date: Mon, 14 Nov 2011 19:24:15 +0100 Subject: Dot-Notation for Users.fp_token_expire --- mediagoblin/auth/views.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 633ceef4..919aa3cd 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -251,7 +251,7 @@ def forgot_password(request): if user: if user.email_verified and user.status == 'active': user.fp_verification_key = unicode(uuid.uuid4()) - user[u'fp_token_expire'] = datetime.datetime.now() + \ + user.fp_token_expire = datetime.datetime.now() + \ datetime.timedelta(days=10) user.save() @@ -303,7 +303,7 @@ def verify_forgot_password(request): # check if we have a real user and correct token if ((user and user.fp_verification_key and user.fp_verification_key == unicode(formdata_token) and - datetime.datetime.now() < user['fp_token_expire'] + datetime.datetime.now() < user.fp_token_expire and user.email_verified and user.status == 'active')): cp_form = auth_forms.ChangePassForm(formdata_vars) @@ -312,7 +312,7 @@ def verify_forgot_password(request): user.pw_hash = auth_lib.bcrypt_gen_password_hash( request.POST['password']) user.fp_verification_key = None - user[u'fp_token_expire'] = None + user.fp_token_expire = None user.save() return redirect(request, 'mediagoblin.auth.fp_changed_success') -- cgit v1.2.3 From 479e8a833ba502c976574af77181f60a2a660aec Mon Sep 17 00:00:00 2001 From: Elrond Date: Sun, 25 Dec 2011 20:11:09 +0100 Subject: Move verification key generation to view Instead of creating the email verication key on the db model as a default for the field, create it in the registration view. Now all verification key generation is only in auth/views.py! --- mediagoblin/auth/views.py | 1 + 1 file changed, 1 insertion(+) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 919aa3cd..66178371 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -84,6 +84,7 @@ def register(request): user.email = email user.pw_hash = auth_lib.bcrypt_gen_password_hash( request.POST['password']) + user.verification_key = unicode(uuid.uuid4()) user.save(validate=True) # log the user in -- cgit v1.2.3 From 4e9d467fc0b3dfc55db15e84d5d988cefa400fa1 Mon Sep 17 00:00:00 2001 From: Jef van Schendel Date: Thu, 29 Dec 2011 22:54:31 +0100 Subject: Isolate JavaScript; add new show_password.js to forgot-password-page as well --- mediagoblin/auth/forms.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index 4cd3e9d8..5a707c7b 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -62,13 +62,7 @@ class ChangePassForm(wtforms.Form): password = wtforms.PasswordField( 'Password', [wtforms.validators.Required(), - wtforms.validators.Length(min=6, max=30), - wtforms.validators.EqualTo( - 'confirm_password', - 'Passwords must match.')]) - confirm_password = wtforms.PasswordField( - 'Confirm password', - [wtforms.validators.Required()]) + wtforms.validators.Length(min=6, max=30)]) userid = wtforms.HiddenField( '', [wtforms.validators.Required()]) -- cgit v1.2.3 From 992e4f80324e5e2d0079fd70cce9d4ad962f7047 Mon Sep 17 00:00:00 2001 From: Jef van Schendel Date: Fri, 30 Dec 2011 21:29:15 +0100 Subject: Change forgotten password process: different redirect, added/changed messages --- mediagoblin/auth/views.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 66178371..f707ecbe 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -232,16 +232,12 @@ def forgot_password(request): """ Forgot password view - Sends an email whit an url to renew forgoten password + Sends an email with an url to renew forgotten password """ fp_form = auth_forms.ForgotPassForm(request.POST) if request.method == 'POST' and fp_form.validate(): - # Here, so it doesn't depend on the actual mail being sent - # and thus doesn't reveal, wether mail was sent. - email_debug_message(request) - # '$or' not available till mongodb 1.5.3 user = request.db.User.find_one( {'username': request.POST['username']}) @@ -257,6 +253,14 @@ def forgot_password(request): user.save() send_fp_verification_email(user, request) + + messages.add_message( + request, + messages.INFO, + _("An email has been sent with instructions on how to " + "change your password.")) + email_debug_message(request) + else: # special case... we can't send the email because the # username is inactive / hasn't verified their email @@ -270,9 +274,13 @@ def forgot_password(request): return redirect( request, 'mediagoblin.user_pages.user_home', user=user.username) - - # do not reveal whether or not there is a matching user - return redirect(request, 'mediagoblin.auth.fp_email_sent') + return redirect(request, 'mediagoblin.auth.login') + else: + messages.add_message( + request, + messages.WARNING, + _("Couldn't find someone with that username or email.")) + return redirect(request, 'mediagoblin.auth.forgot_password') return render_to_response( request, -- cgit v1.2.3 From d8db95e4b72ae30c368aeba41993004b95bc7412 Mon Sep 17 00:00:00 2001 From: Jef van Schendel Date: Sun, 1 Jan 2012 19:00:56 +0100 Subject: Remove fp_email_sent.html and refs to it --- mediagoblin/auth/routing.py | 4 ---- 1 file changed, 4 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index 365ccfaa..699ecbe1 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -39,8 +39,4 @@ auth_routes = [ Route('mediagoblin.auth.fp_changed_success', '/forgot_password/changed_success/', template='mediagoblin/auth/fp_changed_success.html', - controller='mediagoblin.views:simple_template_render'), - Route('mediagoblin.auth.fp_email_sent', - '/forgot_password/email_sent/', - template='mediagoblin/auth/fp_email_sent.html', controller='mediagoblin.views:simple_template_render')] -- cgit v1.2.3 From 35149b11247846506b31ef3cd6647b659b18f352 Mon Sep 17 00:00:00 2001 From: Jef van Schendel Date: Sun, 1 Jan 2012 19:13:23 +0100 Subject: Remove fp_changed_success.html, use log in page + notification message instead --- mediagoblin/auth/routing.py | 6 +----- mediagoblin/auth/views.py | 6 +++++- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index 699ecbe1..ea9388c5 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -35,8 +35,4 @@ auth_routes = [ controller='mediagoblin.auth.views:forgot_password'), Route('mediagoblin.auth.verify_forgot_password', '/forgot_password/verify/', - controller='mediagoblin.auth.views:verify_forgot_password'), - Route('mediagoblin.auth.fp_changed_success', - '/forgot_password/changed_success/', - template='mediagoblin/auth/fp_changed_success.html', - controller='mediagoblin.views:simple_template_render')] + controller='mediagoblin.auth.views:verify_forgot_password')] diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index f707ecbe..88dc40ad 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -324,7 +324,11 @@ def verify_forgot_password(request): user.fp_token_expire = None user.save() - return redirect(request, 'mediagoblin.auth.fp_changed_success') + messages.add_message( + request, + messages.INFO, + _("You can now log in using your new password.")) + return redirect(request, 'mediagoblin.auth.login') else: return render_to_response( request, -- cgit v1.2.3 From 0ab21f981a8a170f5bf4e83f7d56d3ed8fdae467 Mon Sep 17 00:00:00 2001 From: Elrond Date: Sun, 25 Dec 2011 20:04:41 +0100 Subject: Dot-Notation: Some random places --- mediagoblin/auth/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 88dc40ad..c04a49a7 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -205,7 +205,7 @@ def resend_activation(request): return redirect(request, 'mediagoblin.auth.login') - if request.user["email_verified"]: + if request.user.email_verified: messages.add_message( request, messages.ERROR, -- cgit v1.2.3 From cf29e8a824e0ef4612f1144f079c80c1d20b89e5 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Thu, 2 Feb 2012 09:44:13 -0600 Subject: It's 2012 all up in here --- mediagoblin/auth/__init__.py | 2 +- mediagoblin/auth/forms.py | 2 +- mediagoblin/auth/lib.py | 2 +- mediagoblin/auth/routing.py | 2 +- mediagoblin/auth/views.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/__init__.py b/mediagoblin/auth/__init__.py index ba347c69..621845ba 100644 --- a/mediagoblin/auth/__init__.py +++ b/mediagoblin/auth/__init__.py @@ -1,5 +1,5 @@ # GNU MediaGoblin -- federated, autonomous media hosting -# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS. +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index 5a707c7b..1b3e214c 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -1,5 +1,5 @@ # GNU MediaGoblin -- federated, autonomous media hosting -# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS. +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index c0af3b5b..1136a252 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -1,5 +1,5 @@ # GNU MediaGoblin -- federated, autonomous media hosting -# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS. +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index ea9388c5..15d8fc3c 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -1,5 +1,5 @@ # GNU MediaGoblin -- federated, autonomous media hosting -# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS. +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index c04a49a7..9af89c2a 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -1,5 +1,5 @@ # GNU MediaGoblin -- federated, autonomous media hosting -# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS. +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by -- cgit v1.2.3 From 53280164e2ebb5856a6f25d14f27439855f99dbb Mon Sep 17 00:00:00 2001 From: Elrond Date: Mon, 13 Feb 2012 23:11:49 +0100 Subject: 47: Only lowercase host part of email According to most documentation it seems that the local part of an email adress is/can be case sensitive. While the host part is not. So we lowercase only the host part of the given adress. See: http://issues.mediagoblin.org/ticket/47 --- mediagoblin/auth/views.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 9af89c2a..e18469b9 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -60,7 +60,9 @@ def register(request): if request.method == 'POST' and register_form.validate(): # TODO: Make sure the user doesn't exist already username = unicode(request.POST['username'].lower()) - email = unicode(request.POST['email'].lower()) + em_user, em_dom = unicode(request.POST['email']).split("@", 1) + em_dom = em_dom.lower() + email = em_user + "@" + em_dom users_with_username = request.db.User.find( {'username': username}).count() users_with_email = request.db.User.find( -- cgit v1.2.3 From 84812db59dcc7ba476191678a8bb0e1829f3f607 Mon Sep 17 00:00:00 2001 From: Elrond Date: Sat, 28 Jan 2012 00:24:09 +0100 Subject: Change user search from .one to .fine_one. When searching for a user by username, there can either be no result or one result. There is a unique constraint on the db. .one in mongokit raises an error for more than one result. But that can't happen anyway. So no problem. .one in sqlalchemy raises an error for more than one, but that's not a problem anyway. It also raises an error for no result. But no result is handled by the code anyway, so no need to raise an exception. .find_one doesn't raise an exception for more than one result (no problem anyway) and just returns None for no result. The later is handled by the code. --- mediagoblin/auth/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index e18469b9..46c937b0 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -120,7 +120,7 @@ def login(request): login_failed = False if request.method == 'POST' and login_form.validate(): - user = request.db.User.one( + user = request.db.User.find_one( {'username': request.POST['username'].lower()}) if user and user.check_login(request.POST['password']): -- cgit v1.2.3 From 20a3e278bc237a4e23606cc2fc2f800f6a8dbc25 Mon Sep 17 00:00:00 2001 From: Derek Moore Date: Mon, 12 Mar 2012 16:02:42 -0700 Subject: Changes for 293. Tests pass, encode UTF8 on password on registration (and also for subsequent logins once the user is created) is working. --- mediagoblin/auth/lib.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index 1136a252..ddb58fe6 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -42,7 +42,7 @@ def bcrypt_check_password(raw_pass, stored_hash, extra_salt=None): if extra_salt: raw_pass = u"%s:%s" % (extra_salt, raw_pass) - hashed_pass = bcrypt.hashpw(raw_pass, stored_hash) + hashed_pass = bcrypt.hashpw(raw_pass.encode('utf-8'), stored_hash) # Reduce risk of timing attacks by hashing again with a random # number (thx to zooko on this advice, which I hopefully @@ -68,7 +68,8 @@ def bcrypt_gen_password_hash(raw_pass, extra_salt=None): if extra_salt: raw_pass = u"%s:%s" % (extra_salt, raw_pass) - return unicode(bcrypt.hashpw(raw_pass, bcrypt.gensalt())) + return unicode( + bcrypt.hashpw(raw_pass.encode('utf-8'), bcrypt.gensalt())) def fake_login_attempt(): -- cgit v1.2.3 From 952b97d5a0671e1b4a68692a3b5f8a696cd2ca5f Mon Sep 17 00:00:00 2001 From: Jakob Kramer Date: Sun, 25 Mar 2012 21:51:09 +0200 Subject: set username default server-side --- mediagoblin/auth/views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 46c937b0..71a5f379 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -236,7 +236,8 @@ def forgot_password(request): Sends an email with an url to renew forgotten password """ - fp_form = auth_forms.ForgotPassForm(request.POST) + fp_form = auth_forms.ForgotPassForm(request.POST, + username=request.GET.get('username')) if request.method == 'POST' and fp_form.validate(): -- cgit v1.2.3 From f646e2e11bebac8254d76101a134a7474fcd703e Mon Sep 17 00:00:00 2001 From: Jakob Kramer Date: Sun, 25 Mar 2012 22:24:14 +0200 Subject: use _ function on some now untranslatable strings --- mediagoblin/auth/forms.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index 1b3e214c..0b2bf959 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -48,14 +48,14 @@ class LoginForm(wtforms.Form): class ForgotPassForm(wtforms.Form): username = wtforms.TextField( - 'Username or email', + _('Username or email'), [wtforms.validators.Required()]) def validate_username(form, field): if not (re.match(r'^\w+$', field.data) or re.match(r'^.+@[^.].*\.[a-z]{2,10}$', field.data, re.IGNORECASE)): - raise wtforms.ValidationError(u'Incorrect input') + raise wtforms.ValidationError(_(u'Incorrect input')) class ChangePassForm(wtforms.Form): -- cgit v1.2.3 From a855e92a985a9bdc9c5062cad268eba3d8e19f84 Mon Sep 17 00:00:00 2001 From: Will Kahn-Greene Date: Sun, 3 Jun 2012 15:53:34 -0400 Subject: Fix problems from pyflakes output --- mediagoblin/auth/lib.py | 1 - 1 file changed, 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index ddb58fe6..c5b046d2 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -14,7 +14,6 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -import os import random import bcrypt -- cgit v1.2.3 From 111a609df526bd3690fc03e623eaf5826f33f4d2 Mon Sep 17 00:00:00 2001 From: Joar Wandborg Date: Sat, 29 Sep 2012 21:07:15 +0200 Subject: Replaced all request.POST with request.form, ... - Fixed error handling in OAuth plugin - Changed request.POST file fields to request.files --- mediagoblin/auth/views.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 71a5f379..5b77c122 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -55,12 +55,12 @@ def register(request): _('Sorry, registration is disabled on this instance.')) return redirect(request, "index") - register_form = auth_forms.RegistrationForm(request.POST) + register_form = auth_forms.RegistrationForm(request.form) if request.method == 'POST' and register_form.validate(): # TODO: Make sure the user doesn't exist already - username = unicode(request.POST['username'].lower()) - em_user, em_dom = unicode(request.POST['email']).split("@", 1) + username = unicode(request.form['username'].lower()) + em_user, em_dom = unicode(request.form['email']).split("@", 1) em_dom = em_dom.lower() email = em_user + "@" + em_dom users_with_username = request.db.User.find( @@ -85,7 +85,7 @@ def register(request): user.username = username user.email = email user.pw_hash = auth_lib.bcrypt_gen_password_hash( - request.POST['password']) + request.form['password']) user.verification_key = unicode(uuid.uuid4()) user.save(validate=True) @@ -115,21 +115,21 @@ def login(request): If you provide the POST with 'next', it'll redirect to that view. """ - login_form = auth_forms.LoginForm(request.POST) + login_form = auth_forms.LoginForm(request.form) login_failed = False if request.method == 'POST' and login_form.validate(): user = request.db.User.find_one( - {'username': request.POST['username'].lower()}) + {'username': request.form['username'].lower()}) - if user and user.check_login(request.POST['password']): + if user and user.check_login(request.form['password']): # set up login in session request.session['user_id'] = unicode(user._id) request.session.save() - if request.POST.get('next'): - return exc.HTTPFound(location=request.POST['next']) + if request.form.get('next'): + return exc.HTTPFound(location=request.form['next']) else: return redirect(request, "index") @@ -143,7 +143,7 @@ def login(request): request, 'mediagoblin/auth/login.html', {'login_form': login_form, - 'next': request.GET.get('next') or request.POST.get('next'), + 'next': request.GET.get('next') or request.form.get('next'), 'login_failed': login_failed, 'allow_registration': mg_globals.app_config["allow_registration"]}) @@ -236,17 +236,17 @@ def forgot_password(request): Sends an email with an url to renew forgotten password """ - fp_form = auth_forms.ForgotPassForm(request.POST, + fp_form = auth_forms.ForgotPassForm(request.form, username=request.GET.get('username')) if request.method == 'POST' and fp_form.validate(): # '$or' not available till mongodb 1.5.3 user = request.db.User.find_one( - {'username': request.POST['username']}) + {'username': request.form['username']}) if not user: user = request.db.User.find_one( - {'email': request.POST['username']}) + {'email': request.form['username']}) if user: if user.email_verified and user.status == 'active': @@ -322,7 +322,7 @@ def verify_forgot_password(request): if request.method == 'POST' and cp_form.validate(): user.pw_hash = auth_lib.bcrypt_gen_password_hash( - request.POST['password']) + request.form['password']) user.fp_verification_key = None user.fp_token_expire = None user.save() @@ -355,7 +355,7 @@ def _process_for_token(request): if request.method == 'GET': formdata_vars = request.GET else: - formdata_vars = request.POST + formdata_vars = request.form formdata = { 'vars': formdata_vars, -- cgit v1.2.3 From 7742dcc1fbda04c3a1c76a057a1a93a8f504502e Mon Sep 17 00:00:00 2001 From: Joar Wandborg Date: Sun, 14 Oct 2012 13:46:31 +0200 Subject: Switched most stuff over from Routes Removed the Routes routing functionality and replaced it with werkzeug.routes. Most views are functional. Known issues: - Translation integration with the request object is not yet figured out. This breaks 404 pages. --- mediagoblin/auth/routing.py | 55 +++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 22 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index 15d8fc3c..58faa5a3 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -14,25 +14,36 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from routes.route import Route - -auth_routes = [ - Route('mediagoblin.auth.register', '/register/', - controller='mediagoblin.auth.views:register'), - Route('mediagoblin.auth.login', '/login/', - controller='mediagoblin.auth.views:login'), - Route('mediagoblin.auth.logout', '/logout/', - controller='mediagoblin.auth.views:logout'), - Route('mediagoblin.auth.verify_email', '/verify_email/', - controller='mediagoblin.auth.views:verify_email'), - Route('mediagoblin.auth.resend_verification', '/resend_verification/', - controller='mediagoblin.auth.views:resend_activation'), - Route('mediagoblin.auth.resend_verification_success', - '/resend_verification_success/', - template='mediagoblin/auth/resent_verification_email.html', - controller='mediagoblin.views:simple_template_render'), - Route('mediagoblin.auth.forgot_password', '/forgot_password/', - controller='mediagoblin.auth.views:forgot_password'), - Route('mediagoblin.auth.verify_forgot_password', - '/forgot_password/verify/', - controller='mediagoblin.auth.views:verify_forgot_password')] +from routes.route import add_route +from mediagoblin.routing import add_route + +add_route('mediagoblin.auth.logout', + '/auth/logout/', 'mediagoblin.auth.views:logout') + + +add_route('mediagoblin.auth.register', '/register/', + 'mediagoblin.auth.views:register') + +add_route('mediagoblin.auth.login', '/login/', + 'mediagoblin.auth.views:login') + +add_route('mediagoblin.auth.logout', '/logout/', + 'mediagoblin.auth.views:logout') + +add_route('mediagoblin.auth.verify_email', '/verify_email/', + 'mediagoblin.auth.views:verify_email') + +add_route('mediagoblin.auth.resend_verification', '/resend_verification/', + 'mediagoblin.auth.views:resend_activation') + +add_route('mediagoblin.auth.resend_verification_success', + '/resend_verification_success/', + template='mediagoblin/auth/resent_verification_email.html', + 'mediagoblin.views:simple_template_render') + +add_route('mediagoblin.auth.forgot_password', '/forgot_password/', + 'mediagoblin.auth.views:forgot_password') + +add_route('mediagoblin.auth.verify_forgot_password', + '/forgot_password/verify/', + 'mediagoblin.auth.views:verify_forgot_password') -- cgit v1.2.3 From 1ec7ff2adbb1821c5318b4e0a18194f441d7a87e Mon Sep 17 00:00:00 2001 From: Joar Wandborg Date: Sun, 14 Oct 2012 20:05:44 +0200 Subject: Fixed 404 page under werkzeug.routing - Removed ?lang= feature due to incompatibility with werkzeug routes in the current state of the architecture. --- mediagoblin/auth/routing.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index 58faa5a3..ee4b957a 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -14,7 +14,6 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from routes.route import add_route from mediagoblin.routing import add_route add_route('mediagoblin.auth.logout', @@ -36,9 +35,10 @@ add_route('mediagoblin.auth.verify_email', '/verify_email/', add_route('mediagoblin.auth.resend_verification', '/resend_verification/', 'mediagoblin.auth.views:resend_activation') +# XXX: Does this work? add_route('mediagoblin.auth.resend_verification_success', '/resend_verification_success/', - template='mediagoblin/auth/resent_verification_email.html', + # template='mediagoblin/auth/resent_verification_email.html', 'mediagoblin.views:simple_template_render') add_route('mediagoblin.auth.forgot_password', '/forgot_password/', -- cgit v1.2.3 From 0d857844b12b033ee8ecdbcfa474781f835bee59 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sun, 14 Oct 2012 16:26:23 -0500 Subject: Added rudimentary route "mounting" w/ werkzeug routes; fixed auth routes auth routes fixes: - mounted the auth routes at /auth/ - removed crufty old verification email route --- mediagoblin/auth/routing.py | 50 ++++++++++++++++----------------------------- 1 file changed, 18 insertions(+), 32 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index ee4b957a..145761ea 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -14,36 +14,22 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from mediagoblin.routing import add_route -add_route('mediagoblin.auth.logout', - '/auth/logout/', 'mediagoblin.auth.views:logout') - - -add_route('mediagoblin.auth.register', '/register/', - 'mediagoblin.auth.views:register') - -add_route('mediagoblin.auth.login', '/login/', - 'mediagoblin.auth.views:login') - -add_route('mediagoblin.auth.logout', '/logout/', - 'mediagoblin.auth.views:logout') - -add_route('mediagoblin.auth.verify_email', '/verify_email/', - 'mediagoblin.auth.views:verify_email') - -add_route('mediagoblin.auth.resend_verification', '/resend_verification/', - 'mediagoblin.auth.views:resend_activation') - -# XXX: Does this work? -add_route('mediagoblin.auth.resend_verification_success', - '/resend_verification_success/', - # template='mediagoblin/auth/resent_verification_email.html', - 'mediagoblin.views:simple_template_render') - -add_route('mediagoblin.auth.forgot_password', '/forgot_password/', - 'mediagoblin.auth.views:forgot_password') - -add_route('mediagoblin.auth.verify_forgot_password', - '/forgot_password/verify/', - 'mediagoblin.auth.views:verify_forgot_password') +auth_routes = [ + ('mediagoblin.auth.logout', + '/logout/', 'mediagoblin.auth.views:logout'), + ('mediagoblin.auth.register', '/register/', + 'mediagoblin.auth.views:register'), + ('mediagoblin.auth.login', '/login/', + 'mediagoblin.auth.views:login'), + ('mediagoblin.auth.logout', '/logout/', + 'mediagoblin.auth.views:logout'), + ('mediagoblin.auth.verify_email', '/verify_email/', + 'mediagoblin.auth.views:verify_email'), + ('mediagoblin.auth.resend_verification', '/resend_verification/', + 'mediagoblin.auth.views:resend_activation'), + ('mediagoblin.auth.forgot_password', '/forgot_password/', + 'mediagoblin.auth.views:forgot_password'), + ('mediagoblin.auth.verify_forgot_password', + '/forgot_password/verify/', + 'mediagoblin.auth.views:verify_forgot_password')] -- cgit v1.2.3 From d56e82635f85f7a8a7d184a3eae539c09a7b001d Mon Sep 17 00:00:00 2001 From: Joar Wandborg Date: Mon, 15 Oct 2012 00:12:58 +0200 Subject: Fixed OAuth access_token duplicate route Changed route name to "[...]list_connections" --- mediagoblin/auth/routing.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index 145761ea..2a6abb47 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -16,8 +16,6 @@ auth_routes = [ - ('mediagoblin.auth.logout', - '/logout/', 'mediagoblin.auth.views:logout'), ('mediagoblin.auth.register', '/register/', 'mediagoblin.auth.views:register'), ('mediagoblin.auth.login', '/login/', -- cgit v1.2.3 From 5c2b84869fe3f4bfe41a31ff3968bb13c6d7f868 Mon Sep 17 00:00:00 2001 From: Sebastian Spaeth Date: Fri, 30 Nov 2012 10:49:06 +0100 Subject: Move DBModel._id -> DBModel.id We were refering to model._id in most of the code base as this is what Mongo uses. However, each use of _id required a) fixup of queries: e.g. what we did in our find() and find_one() functions moving all '_id' to 'id'. It also required using AliasFields to make the ._id attribute available. This all means lots of superfluous fixing and transitioning in a SQL world. It will also not work in the long run. Much newer code already refers to the objects by model.id (e.g. in the oauth plugin), which will break with Mongo. So let's be honest, rip out the _id mongoism and live with .id as the one canonical way to address objects. This commit modifies all users and providers of model._id to use model.id instead. This patch works with or without Mongo removed first, but will break Mongo usage (even more than before) I have not bothered to fixup db.mongo.* and db.sql.convert (which converts from Mongo to SQL) Signed-off-by: Sebastian Spaeth --- mediagoblin/auth/lib.py | 4 ++-- mediagoblin/auth/views.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index c5b046d2..8829995a 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -109,7 +109,7 @@ def send_verification_email(user, request): 'verification_url': EMAIL_VERIFICATION_TEMPLATE.format( host=request.host, uri=request.urlgen('mediagoblin.auth.verify_email'), - userid=unicode(user._id), + userid=unicode(user.id), verification_key=user.verification_key)}) # TODO: There is no error handling in place @@ -144,7 +144,7 @@ def send_fp_verification_email(user, request): 'verification_url': EMAIL_FP_VERIFICATION_TEMPLATE.format( host=request.host, uri=request.urlgen('mediagoblin.auth.verify_forgot_password'), - userid=unicode(user._id), + userid=unicode(user.id), fp_verification_key=user.fp_verification_key)}) # TODO: There is no error handling in place diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 5b77c122..31f50fa6 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -90,7 +90,7 @@ def register(request): user.save(validate=True) # log the user in - request.session['user_id'] = unicode(user._id) + request.session['user_id'] = unicode(user.id) request.session.save() # send verification email @@ -125,7 +125,7 @@ def login(request): if user and user.check_login(request.form['password']): # set up login in session - request.session['user_id'] = unicode(user._id) + request.session['user_id'] = unicode(user.id) request.session.save() if request.form.get('next'): @@ -167,7 +167,7 @@ def verify_email(request): return render_404(request) user = request.db.User.find_one( - {'_id': ObjectId(unicode(request.GET['userid']))}) + {'id': ObjectId(unicode(request.GET['userid']))}) if user and user.verification_key == unicode(request.GET['token']): user.status = u'active' @@ -308,7 +308,7 @@ def verify_forgot_password(request): # check if it's a valid Id try: user = request.db.User.find_one( - {'_id': ObjectId(unicode(formdata_userid))}) + {'id': ObjectId(unicode(formdata_userid))}) except InvalidId: return render_404(request) -- cgit v1.2.3 From 950124e640913e150088d8644506aceaadd7ef49 Mon Sep 17 00:00:00 2001 From: Sebastian Spaeth Date: Fri, 16 Nov 2012 11:05:08 +0100 Subject: webob.HTTPFound --> MG.tools.redirect Transition away from webob. Signed-off-by: Sebastian Spaeth --- mediagoblin/auth/views.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 31f50fa6..b95ea18d 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -17,8 +17,6 @@ import uuid import datetime -from webob import exc - from mediagoblin import messages from mediagoblin import mg_globals from mediagoblin.tools.response import render_to_response, redirect, render_404 @@ -129,7 +127,7 @@ def login(request): request.session.save() if request.form.get('next'): - return exc.HTTPFound(location=request.form['next']) + return redirect(request, location=request.form['next']) else: return redirect(request, "index") -- cgit v1.2.3 From 70f8b2d04632a897c03779cee65f4c5227655d39 Mon Sep 17 00:00:00 2001 From: Sebastian Spaeth Date: Fri, 21 Dec 2012 10:35:05 +0100 Subject: Remove mongolisms from auth.views Remove find find_one etc and use sqlalchemy syntax --- mediagoblin/auth/views.py | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index b95ea18d..7e1ad440 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -17,11 +17,10 @@ import uuid import datetime -from mediagoblin import messages -from mediagoblin import mg_globals +from mediagoblin import messages, mg_globals +from mediagoblin.db.sql.models import User from mediagoblin.tools.response import render_to_response, redirect, render_404 from mediagoblin.tools.translate import pass_to_ugettext as _ -from mediagoblin.db.util import ObjectId, InvalidId from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms from mediagoblin.auth.lib import send_verification_email, \ @@ -61,10 +60,8 @@ def register(request): em_user, em_dom = unicode(request.form['email']).split("@", 1) em_dom = em_dom.lower() email = em_user + "@" + em_dom - users_with_username = request.db.User.find( - {'username': username}).count() - users_with_email = request.db.User.find( - {'email': email}).count() + users_with_username = User.query.filter_by(username=username).count() + users_with_email = User.query.filter_by(email=email).count() extra_validation_passes = True @@ -79,7 +76,7 @@ def register(request): if extra_validation_passes: # Create the user - user = request.db.User() + user = User() user.username = username user.email = email user.pw_hash = auth_lib.bcrypt_gen_password_hash( @@ -118,8 +115,7 @@ def login(request): login_failed = False if request.method == 'POST' and login_form.validate(): - user = request.db.User.find_one( - {'username': request.form['username'].lower()}) + user = User.query.filter_by(username=request.form['username'].lower()).first() if user and user.check_login(request.form['password']): # set up login in session @@ -164,8 +160,7 @@ def verify_email(request): if not 'userid' in request.GET or not 'token' in request.GET: return render_404(request) - user = request.db.User.find_one( - {'id': ObjectId(unicode(request.GET['userid']))}) + user = User.query.filter_by(id=request.args['userid']).first() if user and user.verification_key == unicode(request.GET['token']): user.status = u'active' @@ -240,11 +235,9 @@ def forgot_password(request): if request.method == 'POST' and fp_form.validate(): # '$or' not available till mongodb 1.5.3 - user = request.db.User.find_one( - {'username': request.form['username']}) + user = User.query.filter_by(username=request.form['username']).first() if not user: - user = request.db.User.find_one( - {'email': request.form['username']}) + user = User.query.filter_by(email=request.form['username']).first() if user: if user.email_verified and user.status == 'active': @@ -303,11 +296,9 @@ def verify_forgot_password(request): formdata_userid = formdata['vars']['userid'] formdata_vars = formdata['vars'] - # check if it's a valid Id - try: - user = request.db.User.find_one( - {'id': ObjectId(unicode(formdata_userid))}) - except InvalidId: + # check if it's a valid user id + user = User.query.filter_by(id=formdata_userid).first() + if not user: return render_404(request) # check if we have a real user and correct token @@ -336,7 +327,7 @@ def verify_forgot_password(request): 'mediagoblin/auth/change_fp.html', {'cp_form': cp_form}) - # in case there is a valid id but no user whit that id in the db + # in case there is a valid id but no user with that id in the db # or the token expired else: return render_404(request) -- cgit v1.2.3 From b39d1f2351352fca21666137fa137eb64926a036 Mon Sep 17 00:00:00 2001 From: Elrond Date: Sun, 23 Dec 2012 21:01:13 +0100 Subject: Mongo removal: Remove the validate=True arg to obj.save() all callers were forced to use validate=True anyway. So remove this useless stuff. --- mediagoblin/auth/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 7e1ad440..efd3e018 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -82,7 +82,7 @@ def register(request): user.pw_hash = auth_lib.bcrypt_gen_password_hash( request.form['password']) user.verification_key = unicode(uuid.uuid4()) - user.save(validate=True) + user.save() # log the user in request.session['user_id'] = unicode(user.id) -- cgit v1.2.3 From b0c8328e547288028e7e43f0ceb1fa9f7c8dac4a Mon Sep 17 00:00:00 2001 From: Sebastian Spaeth Date: Fri, 30 Nov 2012 10:10:35 +0100 Subject: Move db.sql.models* to db.models* --- mediagoblin/auth/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index efd3e018..43354135 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -18,7 +18,7 @@ import uuid import datetime from mediagoblin import messages, mg_globals -from mediagoblin.db.sql.models import User +from mediagoblin.db.models import User from mediagoblin.tools.response import render_to_response, redirect, render_404 from mediagoblin.tools.translate import pass_to_ugettext as _ from mediagoblin.auth import lib as auth_lib -- cgit v1.2.3 From a89df96132a897b1ac31da8719cd6dc0d621cc13 Mon Sep 17 00:00:00 2001 From: Sebastian Spaeth Date: Mon, 7 Jan 2013 10:17:52 +0100 Subject: Restructure ForgotPassword view 1) Remove mongo limitations (no 'or' when querying for either username or email). 2) Lost password function revealed if an user name or email address is registered, which can be considered a data leak. Leaking user names is OK, they are public anyway, but don't reveal lookup success in case the lookup happened by email address. Simply respond: "If you have an account here, we have send you your email"? 3) username and email search was case sensitive. Made username search case insensitive (they are always stored lowercase in the db). Keep email-address search case sensitive for now. This might need further discussion 4) Remove a whole bunch of indention in the style of: if no error: ... if no error: ... if no error: actually do something in the regular case by restructuring the function. 5) Outsource the sanity checking for username and email fields into the validator function. This way, we get automatic case sanity checking and sanitizing for all required fields. 6) Require 5-char password and fix tests Originally, the Change password form required a password between 6-30 chars while the registration and login form did not require anything special. This commit introduces a common minimum limit for all forms which breaks the test suite which uses a 5 char password by default. :-). As 5 chars seem sensible enough to enforce (people should be picking much longer ones anyway), just reduce the limit to 5 chars, thereby making all tests pass. Signed-off-by: Sebastian Spaeth --- mediagoblin/auth/forms.py | 51 ++++++++++++++------ mediagoblin/auth/views.py | 117 ++++++++++++++++++++++++---------------------- 2 files changed, 98 insertions(+), 70 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index 0b2bf959..7cae951a 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -17,52 +17,75 @@ import wtforms import re +from mediagoblin.tools.mail import normalize_email from mediagoblin.tools.translate import fake_ugettext_passthrough as _ +def normalize_user_or_email_field(allow_email=True, allow_user=True): + """Check if we were passed a field that matches a username and/or email pattern + + This is useful for fields that can take either a username or email + address. Use the parameters if you want to only allow a username for + instance""" + message = _(u'Invalid User name or email address.') + nomail_msg = _(u"This field does not take email addresses.") + nouser_msg = _(u"This field requires an email address.") + + def _normalize_field(form, field): + email = u'@' in field.data + if email: # normalize email address casing + if not allow_email: + raise wtforms.ValidationError(nomail_msg) + wtforms.validators.Email()(form, field) + field.data = normalize_email(field.data) + else: # lower case user names + if not allow_user: + raise wtforms.ValidationError(nouser_msg) + wtforms.validators.Length(min=3, max=30)(form, field) + wtforms.validators.Regexp(r'^\w+$')(form, field) + field.data = field.data.lower() + if field.data is None: # should not happen, but be cautious anyway + raise wtforms.ValidationError(message) + return _normalize_field + class RegistrationForm(wtforms.Form): username = wtforms.TextField( _('Username'), [wtforms.validators.Required(), - wtforms.validators.Length(min=3, max=30), - wtforms.validators.Regexp(r'^\w+$')]) + normalize_user_or_email_field(allow_email=False)]) password = wtforms.PasswordField( _('Password'), [wtforms.validators.Required(), - wtforms.validators.Length(min=6, max=30)]) + wtforms.validators.Length(min=5, max=1024)]) email = wtforms.TextField( _('Email address'), [wtforms.validators.Required(), - wtforms.validators.Email()]) + normalize_user_or_email_field(allow_user=False)]) class LoginForm(wtforms.Form): username = wtforms.TextField( _('Username'), [wtforms.validators.Required(), - wtforms.validators.Regexp(r'^\w+$')]) + normalize_user_or_email_field(allow_email=False)]) password = wtforms.PasswordField( _('Password'), - [wtforms.validators.Required()]) + [wtforms.validators.Required(), + wtforms.validators.Length(min=5, max=1024)]) class ForgotPassForm(wtforms.Form): username = wtforms.TextField( _('Username or email'), - [wtforms.validators.Required()]) - - def validate_username(form, field): - if not (re.match(r'^\w+$', field.data) or - re.match(r'^.+@[^.].*\.[a-z]{2,10}$', field.data, - re.IGNORECASE)): - raise wtforms.ValidationError(_(u'Incorrect input')) + [wtforms.validators.Required(), + normalize_user_or_email_field()]) class ChangePassForm(wtforms.Form): password = wtforms.PasswordField( 'Password', [wtforms.validators.Required(), - wtforms.validators.Length(min=6, max=30)]) + wtforms.validators.Length(min=5, max=1024)]) userid = wtforms.HiddenField( '', [wtforms.validators.Required()]) diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 43354135..8c2a95ed 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -41,8 +41,10 @@ def email_debug_message(request): def register(request): - """ - Your classic registration view! + """The registration view. + + Note that usernames will always be lowercased. Email domains are lowercased while + the first part remains case-sensitive. """ # Redirects to indexpage if registrations are disabled if not mg_globals.app_config["allow_registration"]: @@ -56,12 +58,8 @@ def register(request): if request.method == 'POST' and register_form.validate(): # TODO: Make sure the user doesn't exist already - username = unicode(request.form['username'].lower()) - em_user, em_dom = unicode(request.form['email']).split("@", 1) - em_dom = em_dom.lower() - email = em_user + "@" + em_dom - users_with_username = User.query.filter_by(username=username).count() - users_with_email = User.query.filter_by(email=email).count() + users_with_username = User.query.filter_by(username=register_form.data['username']).count() + users_with_email = User.query.filter_by(email=register_form.data['email']).count() extra_validation_passes = True @@ -77,8 +75,8 @@ def register(request): if extra_validation_passes: # Create the user user = User() - user.username = username - user.email = email + user.username = register_form.data['username'] + user.email = register_form.data['email'] user.pw_hash = auth_lib.bcrypt_gen_password_hash( request.form['password']) user.verification_key = unicode(uuid.uuid4()) @@ -115,7 +113,7 @@ def login(request): login_failed = False if request.method == 'POST' and login_form.validate(): - user = User.query.filter_by(username=request.form['username'].lower()).first() + user = User.query.filter_by(username=login_form.data['username']).first() if user and user.check_login(request.form['password']): # set up login in session @@ -227,59 +225,66 @@ def forgot_password(request): """ Forgot password view - Sends an email with an url to renew forgotten password + Sends an email with an url to renew forgotten password. + Use GET querystring parameter 'username' to pre-populate the input field """ fp_form = auth_forms.ForgotPassForm(request.form, - username=request.GET.get('username')) - - if request.method == 'POST' and fp_form.validate(): + username=request.args.get('username')) + + if not (request.method == 'POST' and fp_form.validate()): + # Either GET request, or invalid form submitted. Display the template + return render_to_response(request, + 'mediagoblin/auth/forgot_password.html', {'fp_form': fp_form}) + + # If we are here: method == POST and form is valid. username casing + # has been sanitized. Store if a user was found by email. We should + # not reveal if the operation was successful then as we don't want to + # leak if an email address exists in the system. + found_by_email = '@' in request.form['username'] + + if found_by_email: + user = User.query.filter_by( + email = request.form['username']).first() + # Don't reveal success in case the lookup happened by email address. + success_message=_("If that email address (case sensitive!) is " + "registered an email has been sent with instructions " + "on how to change your password.") + + else: # found by username + user = User.query.filter_by( + username = request.form['username']).first() + + if user is None: + messages.add_message(request, + messages.WARNING, + _("Couldn't find someone with that username.")) + return redirect(request, 'mediagoblin.auth.forgot_password') - # '$or' not available till mongodb 1.5.3 - user = User.query.filter_by(username=request.form['username']).first() - if not user: - user = User.query.filter_by(email=request.form['username']).first() + success_message=_("An email has been sent with instructions " + "on how to change your password.") - if user: - if user.email_verified and user.status == 'active': - user.fp_verification_key = unicode(uuid.uuid4()) - user.fp_token_expire = datetime.datetime.now() + \ - datetime.timedelta(days=10) - user.save() + if user and not(user.email_verified and user.status == 'active'): + # Don't send reminder because user is inactive or has no verified email + messages.add_message(request, + messages.WARNING, + _("Could not send password recovery email as your username is in" + "active or your account's email address has not been verified.")) - send_fp_verification_email(user, request) + return redirect(request, 'mediagoblin.user_pages.user_home', + user=user.username) - messages.add_message( - request, - messages.INFO, - _("An email has been sent with instructions on how to " - "change your password.")) - email_debug_message(request) + # SUCCESS. Send reminder and return to login page + if user: + user.fp_verification_key = unicode(uuid.uuid4()) + user.fp_token_expire = datetime.datetime.now() + \ + datetime.timedelta(days=10) + user.save() - else: - # special case... we can't send the email because the - # username is inactive / hasn't verified their email - messages.add_message( - request, - messages.WARNING, - _("Could not send password recovery email as " - "your username is inactive or your account's " - "email address has not been verified.")) - - return redirect( - request, 'mediagoblin.user_pages.user_home', - user=user.username) - return redirect(request, 'mediagoblin.auth.login') - else: - messages.add_message( - request, - messages.WARNING, - _("Couldn't find someone with that username or email.")) - return redirect(request, 'mediagoblin.auth.forgot_password') + email_debug_message(request) + send_fp_verification_email(user, request) - return render_to_response( - request, - 'mediagoblin/auth/forgot_password.html', - {'fp_form': fp_form}) + messages.add_message(request, messages.INFO, success_message) + return redirect(request, 'mediagoblin.auth.login') def verify_forgot_password(request): -- cgit v1.2.3 From 69b5623552a86a7cad92571e937384836cf6165c Mon Sep 17 00:00:00 2001 From: Sebastian Spaeth Date: Mon, 21 Jan 2013 16:27:19 +0100 Subject: Also set login_failed in case of form errors If we send a POST request to the login page which contained form errors (e.g. a too short password), the variable "login_failed" was not set to true. This condition was tested by the test suite however, so we should make sure that login_failed is set even if the form failed to validate. Signed-off-by: Sebastian Spaeth --- mediagoblin/auth/views.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 8c2a95ed..d8ad7b51 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -112,20 +112,21 @@ def login(request): login_failed = False - if request.method == 'POST' and login_form.validate(): - user = User.query.filter_by(username=login_form.data['username']).first() + if request.method == 'POST': + if login_form.validate(): + user = User.query.filter_by(username=login_form.data['username']).first() - if user and user.check_login(request.form['password']): - # set up login in session - request.session['user_id'] = unicode(user.id) - request.session.save() + if user and user.check_login(request.form['password']): + # set up login in session + request.session['user_id'] = unicode(user.id) + request.session.save() - if request.form.get('next'): - return redirect(request, location=request.form['next']) - else: - return redirect(request, "index") + if request.form.get('next'): + return redirect(request, location=request.form['next']) + else: + return redirect(request, "index") - else: + # Some failure during login occured if we are here! # Prevent detecting who's on this system by testing login # attempt timings auth_lib.fake_login_attempt() -- cgit v1.2.3 From bedc215b449ab6c2b120330d158831b2dde5ff10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A1s=20Veres-Szentkir=C3=A1lyi?= Date: Thu, 21 Feb 2013 10:51:13 +0100 Subject: removed unused import re --- mediagoblin/auth/forms.py | 1 - 1 file changed, 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index 7cae951a..8f091d21 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -15,7 +15,6 @@ # along with this program. If not, see . import wtforms -import re from mediagoblin.tools.mail import normalize_email from mediagoblin.tools.translate import fake_ugettext_passthrough as _ -- cgit v1.2.3 From dfa6994d4d81370482d386488bc3b285279f4d8c Mon Sep 17 00:00:00 2001 From: Hans Lo Date: Thu, 28 Mar 2013 00:52:24 -0400 Subject: auth: whitespace cleanup in views.py --- mediagoblin/auth/views.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index d8ad7b51..99fe0b68 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -196,7 +196,7 @@ def resend_activation(request): request, messages.ERROR, _('You must be logged in so we know who to send the email to!')) - + return redirect(request, 'mediagoblin.auth.login') if request.user.email_verified: @@ -204,12 +204,12 @@ def resend_activation(request): request, messages.ERROR, _("You've already verified your email address!")) - + return redirect(request, "mediagoblin.user_pages.user_home", user=request.user['username']) request.user.verification_key = unicode(uuid.uuid4()) request.user.save() - + email_debug_message(request) send_verification_email(request.user, request) -- cgit v1.2.3 From 9d140cb8429166bfb2cb8937ad820f906767747b Mon Sep 17 00:00:00 2001 From: Hans Lo Date: Thu, 28 Mar 2013 04:13:23 -0400 Subject: Use WTForms data field in auth/views.py --- mediagoblin/auth/views.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 99fe0b68..354b48c1 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -78,7 +78,7 @@ def register(request): user.username = register_form.data['username'] user.email = register_form.data['email'] user.pw_hash = auth_lib.bcrypt_gen_password_hash( - request.form['password']) + register_form.password.data) user.verification_key = unicode(uuid.uuid4()) user.save() @@ -116,7 +116,7 @@ def login(request): if login_form.validate(): user = User.query.filter_by(username=login_form.data['username']).first() - if user and user.check_login(request.form['password']): + if user and user.check_login(login_form.password.data): # set up login in session request.session['user_id'] = unicode(user.id) request.session.save() @@ -241,11 +241,11 @@ def forgot_password(request): # has been sanitized. Store if a user was found by email. We should # not reveal if the operation was successful then as we don't want to # leak if an email address exists in the system. - found_by_email = '@' in request.form['username'] + found_by_email = '@' in fp_form.username.data if found_by_email: user = User.query.filter_by( - email = request.form['username']).first() + email = fp_form.username.data).first() # Don't reveal success in case the lookup happened by email address. success_message=_("If that email address (case sensitive!) is " "registered an email has been sent with instructions " @@ -253,7 +253,7 @@ def forgot_password(request): else: # found by username user = User.query.filter_by( - username = request.form['username']).first() + username = fp_form.username.data).first() if user is None: messages.add_message(request, @@ -317,7 +317,7 @@ def verify_forgot_password(request): if request.method == 'POST' and cp_form.validate(): user.pw_hash = auth_lib.bcrypt_gen_password_hash( - request.form['password']) + cp_form.password.data) user.fp_verification_key = None user.fp_token_expire = None user.save() -- cgit v1.2.3 From b2c8dbcf8507811fe931a48722ed9c8b530bcdae Mon Sep 17 00:00:00 2001 From: Jessica T Date: Fri, 12 Apr 2013 22:07:44 +0100 Subject: Allows you to use your username or email to login --- mediagoblin/auth/forms.py | 4 ++-- mediagoblin/auth/views.py | 12 ++++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index 8f091d21..5484c178 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -64,9 +64,9 @@ class RegistrationForm(wtforms.Form): class LoginForm(wtforms.Form): username = wtforms.TextField( - _('Username'), + _('Username or Email'), [wtforms.validators.Required(), - normalize_user_or_email_field(allow_email=False)]) + normalize_user_or_email_field()]) password = wtforms.PasswordField( _('Password'), [wtforms.validators.Required(), diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 354b48c1..dc408911 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -25,7 +25,7 @@ from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms from mediagoblin.auth.lib import send_verification_email, \ send_fp_verification_email - +from sqlalchemy import or_ def email_debug_message(request): """ @@ -113,8 +113,16 @@ def login(request): login_failed = False if request.method == 'POST': + + username = login_form.data['username'] + if login_form.validate(): - user = User.query.filter_by(username=login_form.data['username']).first() + user = User.query.filter( + or_( + User.username == username, + User.email == username, + + )).first() if user and user.check_login(login_form.password.data): # set up login in session -- cgit v1.2.3 From 665b9c420aa1a7c768e44a8639b6fc185823e202 Mon Sep 17 00:00:00 2001 From: Aditi Mittal Date: Mon, 22 Apr 2013 19:18:45 +0530 Subject: Fix-bug-667-Use-lazy_pass_to_ugettext-for-forms. --- mediagoblin/auth/forms.py | 2 +- mediagoblin/auth/views.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index 5484c178..33e1f45c 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -17,7 +17,7 @@ import wtforms from mediagoblin.tools.mail import normalize_email -from mediagoblin.tools.translate import fake_ugettext_passthrough as _ +from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ def normalize_user_or_email_field(allow_email=True, allow_user=True): """Check if we were passed a field that matches a username and/or email pattern diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index dc408911..627df177 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -20,7 +20,7 @@ import datetime from mediagoblin import messages, mg_globals from mediagoblin.db.models import User from mediagoblin.tools.response import render_to_response, redirect, render_404 -from mediagoblin.tools.translate import pass_to_ugettext as _ +from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms from mediagoblin.auth.lib import send_verification_email, \ -- cgit v1.2.3 From a789b713f534156d923cf6cc9070559ac8b6c616 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 24 Apr 2013 14:39:16 -0500 Subject: Switching non-forms back to using normal pass_to_ugettext --- mediagoblin/auth/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 627df177..dc408911 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -20,7 +20,7 @@ import datetime from mediagoblin import messages, mg_globals from mediagoblin.db.models import User from mediagoblin.tools.response import render_to_response, redirect, render_404 -from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ +from mediagoblin.tools.translate import pass_to_ugettext as _ from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms from mediagoblin.auth.lib import send_verification_email, \ -- cgit v1.2.3 From 7cb7653c64fbbe1407843074056f6a3b0228015d Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Thu, 23 May 2013 14:29:19 -0700 Subject: moved normalize_user_or_email_field to auth/tools.py from auth/forms.py --- mediagoblin/auth/forms.py | 28 +------------------------- mediagoblin/auth/tools.py | 50 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 27 deletions(-) create mode 100644 mediagoblin/auth/tools.py (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index 33e1f45c..599b2576 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -18,33 +18,7 @@ import wtforms from mediagoblin.tools.mail import normalize_email from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ - -def normalize_user_or_email_field(allow_email=True, allow_user=True): - """Check if we were passed a field that matches a username and/or email pattern - - This is useful for fields that can take either a username or email - address. Use the parameters if you want to only allow a username for - instance""" - message = _(u'Invalid User name or email address.') - nomail_msg = _(u"This field does not take email addresses.") - nouser_msg = _(u"This field requires an email address.") - - def _normalize_field(form, field): - email = u'@' in field.data - if email: # normalize email address casing - if not allow_email: - raise wtforms.ValidationError(nomail_msg) - wtforms.validators.Email()(form, field) - field.data = normalize_email(field.data) - else: # lower case user names - if not allow_user: - raise wtforms.ValidationError(nouser_msg) - wtforms.validators.Length(min=3, max=30)(form, field) - wtforms.validators.Regexp(r'^\w+$')(form, field) - field.data = field.data.lower() - if field.data is None: # should not happen, but be cautious anyway - raise wtforms.ValidationError(message) - return _normalize_field +from mediagoblin.auth.tools import normalize_user_or_email_field class RegistrationForm(wtforms.Form): diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py new file mode 100644 index 00000000..1b30a7d9 --- /dev/null +++ b/mediagoblin/auth/tools.py @@ -0,0 +1,50 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import wtforms + +from mediagoblin.tools.mail import normalize_email +from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ + + +def normalize_user_or_email_field(allow_email=True, allow_user=True): + """ + Check if we were passed a field that matches a username and/or email + pattern. + + This is useful for fields that can take either a username or email + address. Use the parameters if you want to only allow a username for + instance""" + message = _(u'Invalid User name or email address.') + nomail_msg = _(u"This field does not take email addresses.") + nouser_msg = _(u"This field requires an email address.") + + def _normalize_field(form, field): + email = u'@' in field.data + if email: # normalize email address casing + if not allow_email: + raise wtforms.ValidationError(nomail_msg) + wtforms.validators.Email()(form, field) + field.data = normalize_email(field.data) + else: # lower case user names + if not allow_user: + raise wtforms.ValidationError(nouser_msg) + wtforms.validators.Length(min=3, max=30)(form, field) + wtforms.validators.Regexp(r'^\w+$')(form, field) + field.data = field.data.lower() + if field.data is None: # should not happen, but be cautious anyway + raise wtforms.ValidationError(message) + return _normalize_field -- cgit v1.2.3 From 41258916f28a2df28d3feb907ea358f227c65e21 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Thu, 23 May 2013 14:56:32 -0700 Subject: removed unused import --- mediagoblin/auth/forms.py | 1 - 1 file changed, 1 deletion(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index 599b2576..0a391d67 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -16,7 +16,6 @@ import wtforms -from mediagoblin.tools.mail import normalize_email from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ from mediagoblin.auth.tools import normalize_user_or_email_field -- cgit v1.2.3 From 97aebda7ded46181af1c5e9560be8251d4c56d36 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Fri, 24 May 2013 12:26:45 -0700 Subject: moved send_verification_email to auth/tools --- mediagoblin/auth/lib.py | 35 ----------------------------------- mediagoblin/auth/tools.py | 39 ++++++++++++++++++++++++++++++++++++++- mediagoblin/auth/views.py | 6 +++--- 3 files changed, 41 insertions(+), 39 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index 8829995a..bfc36b28 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -90,41 +90,6 @@ def fake_login_attempt(): randplus_stored_hash == randplus_hashed_pass -EMAIL_VERIFICATION_TEMPLATE = ( - u"http://{host}{uri}?" - u"userid={userid}&token={verification_key}") - - -def send_verification_email(user, request): - """ - Send the verification email to users to activate their accounts. - - Args: - - user: a user object - - request: the request - """ - rendered_email = render_template( - request, 'mediagoblin/auth/verification_email.txt', - {'username': user.username, - 'verification_url': EMAIL_VERIFICATION_TEMPLATE.format( - host=request.host, - uri=request.urlgen('mediagoblin.auth.verify_email'), - userid=unicode(user.id), - verification_key=user.verification_key)}) - - # TODO: There is no error handling in place - send_email( - mg_globals.app_config['email_sender_address'], - [user.email], - # TODO - # Due to the distributed nature of GNU MediaGoblin, we should - # find a way to send some additional information about the - # specific GNU MediaGoblin instance in the subject line. For - # example "GNU MediaGoblin @ Wandborg - [...]". - 'GNU MediaGoblin - Verify your email!', - rendered_email) - - EMAIL_FP_VERIFICATION_TEMPLATE = ( u"http://{host}{uri}?" u"userid={userid}&token={fp_verification_key}") diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index 1b30a7d9..52095d8a 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -16,7 +16,9 @@ import wtforms -from mediagoblin.tools.mail import normalize_email +from mediagoblin import mg_globals +from mediagoblin.tools.mail import normalize_email, send_email +from mediagoblin.tools.template import render_template from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ @@ -48,3 +50,38 @@ def normalize_user_or_email_field(allow_email=True, allow_user=True): if field.data is None: # should not happen, but be cautious anyway raise wtforms.ValidationError(message) return _normalize_field + + +EMAIL_VERIFICATION_TEMPLATE = ( + u"http://{host}{uri}?" + u"userid={userid}&token={verification_key}") + + +def send_verification_email(user, request): + """ + Send the verification email to users to activate their accounts. + + Args: + - user: a user object + - request: the request + """ + rendered_email = render_template( + request, 'mediagoblin/auth/verification_email.txt', + {'username': user.username, + 'verification_url': EMAIL_VERIFICATION_TEMPLATE.format( + host=request.host, + uri=request.urlgen('mediagoblin.auth.verify_email'), + userid=unicode(user.id), + verification_key=user.verification_key)}) + + # TODO: There is no error handling in place + send_email( + mg_globals.app_config['email_sender_address'], + [user.email], + # TODO + # Due to the distributed nature of GNU MediaGoblin, we should + # find a way to send some additional information about the + # specific GNU MediaGoblin instance in the subject line. For + # example "GNU MediaGoblin @ Wandborg - [...]". + 'GNU MediaGoblin - Verify your email!', + rendered_email) diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index dc408911..94354933 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -23,8 +23,8 @@ from mediagoblin.tools.response import render_to_response, redirect, render_404 from mediagoblin.tools.translate import pass_to_ugettext as _ from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms -from mediagoblin.auth.lib import send_verification_email, \ - send_fp_verification_email +from mediagoblin.auth.lib import send_fp_verification_email +from mediagoblin.auth.tools import send_verification_email from sqlalchemy import or_ def email_debug_message(request): @@ -113,7 +113,7 @@ def login(request): login_failed = False if request.method == 'POST': - + username = login_form.data['username'] if login_form.validate(): -- cgit v1.2.3 From 02b6892c290671ac956144a212785d98ae579ef4 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Fri, 24 May 2013 12:48:29 -0700 Subject: moved email_debug_message to gmg/tools/mail --- mediagoblin/auth/views.py | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 94354933..6a8e9a4c 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -21,24 +21,13 @@ from mediagoblin import messages, mg_globals from mediagoblin.db.models import User from mediagoblin.tools.response import render_to_response, redirect, render_404 from mediagoblin.tools.translate import pass_to_ugettext as _ +from mediagoblin.tools.mail import email_debug_message from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms from mediagoblin.auth.lib import send_fp_verification_email from mediagoblin.auth.tools import send_verification_email from sqlalchemy import or_ -def email_debug_message(request): - """ - If the server is running in email debug mode (which is - the current default), give a debug message to the user - so that they have an idea where to find their email. - """ - if mg_globals.app_config['email_debug_mode']: - # DEBUG message, no need to translate - messages.add_message(request, messages.DEBUG, - u"This instance is running in email debug mode. " - u"The email will be on the console of the server process.") - def register(request): """The registration view. -- cgit v1.2.3 From 75fc93686d0763ced6a5769e99e570a4c8fd3273 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Sat, 25 May 2013 07:59:03 -0700 Subject: created a check_login_simple function cherry-picked from rodney757, fixed few conflicts due to out of order cherry-picking. Thanks to rodney757 for making my idea even better. --- mediagoblin/auth/tools.py | 23 +++++++++++++++++++++++ mediagoblin/auth/views.py | 17 ++++------------- 2 files changed, 27 insertions(+), 13 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index 52095d8a..bb7d2683 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -14,13 +14,20 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import logging + import wtforms +from sqlalchemy import or_ from mediagoblin import mg_globals +from mediagoblin.auth import lib as auth_lib +from mediagoblin.db.models import User from mediagoblin.tools.mail import normalize_email, send_email from mediagoblin.tools.template import render_template from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ +_log = logging.getLogger(__name__) + def normalize_user_or_email_field(allow_email=True, allow_user=True): """ @@ -85,3 +92,19 @@ def send_verification_email(user, request): # example "GNU MediaGoblin @ Wandborg - [...]". 'GNU MediaGoblin - Verify your email!', rendered_email) + + +def check_login_simple(username, password, username_might_be_email=False): + search = (User.username == username) + if username_might_be_email and ('@' in username): + search = or_(search, User.email == username) + user = User.query.filter(search).first() + if not user: + _log.info("User %r not found", username) + auth_lib.fake_login_attempt() + return None + if not auth_lib.bcrypt_check_password(password, user.pw_hash): + _log.warn("Wrong password for %r", username) + return None + _log.info("Logging %r in", username) + return user diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 6a8e9a4c..2485e79e 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -25,8 +25,8 @@ from mediagoblin.tools.mail import email_debug_message from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms from mediagoblin.auth.lib import send_fp_verification_email -from mediagoblin.auth.tools import send_verification_email -from sqlalchemy import or_ +from mediagoblin.auth.tools import (send_verification_email, + check_login_simple) def register(request): @@ -106,14 +106,9 @@ def login(request): username = login_form.data['username'] if login_form.validate(): - user = User.query.filter( - or_( - User.username == username, - User.email == username, + user = check_login_simple(username, login_form.password.data, True) - )).first() - - if user and user.check_login(login_form.password.data): + if user: # set up login in session request.session['user_id'] = unicode(user.id) request.session.save() @@ -123,10 +118,6 @@ def login(request): else: return redirect(request, "index") - # Some failure during login occured if we are here! - # Prevent detecting who's on this system by testing login - # attempt timings - auth_lib.fake_login_attempt() login_failed = True return render_to_response( -- cgit v1.2.3 From f9e032212dff4d54de644cb5537bc0bef6d24c7f Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Fri, 24 May 2013 12:52:14 -0700 Subject: added a register_user function cherry picked from rodney757 and fixed for out of order picking. --- mediagoblin/auth/tools.py | 51 ++++++++++++++++++++++++++++++++++++++++++++++- mediagoblin/auth/views.py | 35 +++----------------------------- 2 files changed, 53 insertions(+), 33 deletions(-) (limited to 'mediagoblin/auth') diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index bb7d2683..db6b6e37 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -14,6 +14,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import uuid import logging import wtforms @@ -22,7 +23,8 @@ from sqlalchemy import or_ from mediagoblin import mg_globals from mediagoblin.auth import lib as auth_lib from mediagoblin.db.models import User -from mediagoblin.tools.mail import normalize_email, send_email +from mediagoblin.tools.mail import (normalize_email, send_email, + email_debug_message) from mediagoblin.tools.template import render_template from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ @@ -94,6 +96,53 @@ def send_verification_email(user, request): rendered_email) +def basic_extra_validation(register_form, *args): + users_with_username = User.query.filter_by( + username=register_form.data['username']).count() + users_with_email = User.query.filter_by( + email=register_form.data['email']).count() + + extra_validation_passes = True + + if users_with_username: + register_form.username.errors.append( + _(u'Sorry, a user with that name already exists.')) + extra_validation_passes = False + if users_with_email: + register_form.email.errors.append( + _(u'Sorry, a user with that email address already exists.')) + extra_validation_passes = False + + return extra_validation_passes + + +def register_user(request, register_form): + """ Handle user registration """ + extra_validation_passes = basic_extra_validation(register_form) + + if extra_validation_passes: + # Create the user + user = User() + user.username = register_form.data['username'] + user.email = register_form.data['email'] + user.pw_hash = auth_lib.bcrypt_gen_password_hash( + register_form.password.data) + user.verification_key = unicode(uuid.uuid4()) + user.save() + + # log the user in + request.session['user_id'] = unicode(user.id) + request.session.save() + + # send verification email + email_debug_message(request) + send_verification_email(user, request) + + return user + + return None + + def check_login_simple(username, password, username_might_be_email=False): search = (User.username == username) if username_might_be_email and ('@' in username): diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 2485e79e..bb7bda77 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -25,7 +25,7 @@ from mediagoblin.tools.mail import email_debug_message from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms from mediagoblin.auth.lib import send_fp_verification_email -from mediagoblin.auth.tools import (send_verification_email, +from mediagoblin.auth.tools import (send_verification_email, register_user, check_login_simple) @@ -47,38 +47,9 @@ def register(request): if request.method == 'POST' and register_form.validate(): # TODO: Make sure the user doesn't exist already - users_with_username = User.query.filter_by(username=register_form.data['username']).count() - users_with_email = User.query.filter_by(email=register_form.data['email']).count() - - extra_validation_passes = True - - if users_with_username: - register_form.username.errors.append( - _(u'Sorry, a user with that name already exists.')) - extra_validation_passes = False - if users_with_email: - register_form.email.errors.append( - _(u'Sorry, a user with that email address already exists.')) - extra_validation_passes = False - - if extra_validation_passes: - # Create the user - user = User() - user.username = register_form.data['username'] - user.email = register_form.data['email'] - user.pw_hash = auth_lib.bcrypt_gen_password_hash( - register_form.password.data) - user.verification_key = unicode(uuid.uuid4()) - user.save() - - # log the user in - request.session['user_id'] = unicode(user.id) - request.session.save() - - # send verification email - email_debug_message(request) - send_verification_email(user, request) + user = register_user(request, register_form) + if user: # redirect the user to their homepage... there will be a # message waiting for them to verify their email return redirect( -- cgit v1.2.3