Merge remote-tracking branch 'gitorious/master'
This commit is contained in:
commit
ec8f66bd65
@ -152,7 +152,7 @@ Running the test suite
|
||||
|
||||
Run::
|
||||
|
||||
./bin/nosetests
|
||||
CELERY_CONFIG_MODULE=mediagoblin.celery_setup.from_tests ./bin/nosetests
|
||||
|
||||
|
||||
Running a shell
|
||||
|
@ -139,12 +139,13 @@ def paste_app_factory(global_config, **app_config):
|
||||
raise ImproperlyConfigured(
|
||||
"One of direct_remote_path or direct_remote_paths must be provided")
|
||||
|
||||
if asbool(os.environ.get('CELERY_ALWAYS_EAGER')):
|
||||
setup_celery_from_config(
|
||||
app_config, global_config,
|
||||
force_celery_always_eager=True)
|
||||
else:
|
||||
setup_celery_from_config(app_config, global_config)
|
||||
if not asbool(app_config.get('celery_setup_elsewhere')):
|
||||
if asbool(os.environ.get('CELERY_ALWAYS_EAGER')):
|
||||
setup_celery_from_config(
|
||||
app_config, global_config,
|
||||
force_celery_always_eager=True)
|
||||
else:
|
||||
setup_celery_from_config(app_config, global_config)
|
||||
|
||||
mgoblin_app = MediaGoblinApp(
|
||||
connection, db,
|
||||
|
@ -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()])
|
||||
|
@ -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
|
||||
|
||||
|
||||
@ -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.
|
||||
@ -97,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(
|
||||
@ -111,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='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'])))
|
||||
rendered_email)
|
||||
|
@ -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')]
|
||||
|
@ -16,8 +16,9 @@
|
||||
|
||||
import uuid
|
||||
|
||||
from webob import Response, exc
|
||||
from webob import exc
|
||||
|
||||
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
|
||||
@ -53,25 +54,12 @@ 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")
|
||||
|
||||
# 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}))
|
||||
return render_to_response(
|
||||
request,
|
||||
'mediagoblin/auth/register.html',
|
||||
{'register_form': register_form})
|
||||
|
||||
|
||||
def login(request):
|
||||
@ -96,8 +84,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
|
||||
@ -105,23 +92,19 @@ def login(request):
|
||||
auth_lib.fake_login_attempt()
|
||||
login_failed = True
|
||||
|
||||
# render
|
||||
template = request.template_env.get_template(
|
||||
'mediagoblin/auth/login.html')
|
||||
return Response(
|
||||
template.render(
|
||||
{'request': request,
|
||||
'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):
|
||||
# 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):
|
||||
@ -146,27 +129,11 @@ 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,
|
||||
'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}))
|
||||
return render_to_response(
|
||||
request,
|
||||
'mediagoblin/auth/verify_email.html',
|
||||
{'user': user,
|
||||
'verification_successful': verification_successful})
|
||||
|
||||
|
||||
def resend_activation(request):
|
||||
@ -175,19 +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 exc.HTTPFound(
|
||||
location=request.urlgen('mediagoblin.auth.resend_verification_success'))
|
||||
|
||||
|
||||
def resend_activation_success(request):
|
||||
template = request.template_env.get_template(
|
||||
'mediagoblin/auth/resent_verification_email.html')
|
||||
return Response(
|
||||
template.render(
|
||||
{'request': request}))
|
||||
return redirect(request, 'mediagoblin.auth.resend_verification_success')
|
||||
|
43
mediagoblin/celery_setup/from_tests.py
Normal file
43
mediagoblin/celery_setup/from_tests.py
Normal file
@ -0,0 +1,43 @@
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
|
||||
from mediagoblin.tests.tools import TEST_APP_CONFIG
|
||||
from mediagoblin import util
|
||||
from mediagoblin.celery_setup import setup_celery_from_config
|
||||
from mediagoblin.globals import setup_globals
|
||||
|
||||
|
||||
OUR_MODULENAME = 'mediagoblin.celery_setup.from_tests'
|
||||
|
||||
|
||||
def setup_self(setup_globals_func=setup_globals):
|
||||
"""
|
||||
Set up celery for testing's sake, which just needs to set up
|
||||
celery and celery only.
|
||||
"""
|
||||
mgoblin_conf = util.read_config_file(TEST_APP_CONFIG)
|
||||
mgoblin_section = mgoblin_conf['app:mediagoblin']
|
||||
|
||||
setup_celery_from_config(
|
||||
mgoblin_section, mgoblin_conf,
|
||||
settings_module=OUR_MODULENAME,
|
||||
set_environ=False)
|
||||
|
||||
|
||||
if os.environ.get('CELERY_CONFIG_MODULE') == OUR_MODULENAME:
|
||||
setup_self()
|
@ -18,6 +18,7 @@
|
||||
from bson.errors import InvalidId
|
||||
from webob import exc
|
||||
|
||||
from mediagoblin.util import redirect
|
||||
from mediagoblin.db.util import ObjectId
|
||||
|
||||
|
||||
@ -38,9 +39,8 @@ def require_active_login(controller):
|
||||
def new_controller_func(request, *args, **kwargs):
|
||||
if request.user and \
|
||||
request.user.get('status') == u'needs_email_verification':
|
||||
return exc.HTTPFound(
|
||||
location = request.urlgen(
|
||||
'mediagoblin.auth.verify_email_notice'))
|
||||
return redirect(request,
|
||||
'mediagoblin.auth.verify_email_notice')
|
||||
elif not request.user or request.user.get('status') != u'active':
|
||||
return exc.HTTPFound(
|
||||
location="%s?next=%s" % (
|
||||
|
@ -14,9 +14,9 @@
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from routes.route import Route
|
||||
|
||||
edit_routes = [
|
||||
Route('mediagoblin.edit.edit_media', "/{user}/{media}/",
|
||||
controller="mediagoblin.edit.views:edit_media"),
|
||||
# Media editing view handled in user_pages/routing.py
|
||||
]
|
||||
|
@ -15,8 +15,9 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from webob import Response, exc
|
||||
from webob import exc
|
||||
|
||||
from mediagoblin.util import render_to_response, redirect
|
||||
from mediagoblin.edit import forms
|
||||
from mediagoblin.edit.lib import may_edit_media
|
||||
from mediagoblin.decorators import require_active_login, get_user_media_entry
|
||||
@ -48,17 +49,13 @@ def edit_media(request, media):
|
||||
media['title'] = request.POST['title']
|
||||
media['description'] = request.POST['description']
|
||||
media['slug'] = request.POST['slug']
|
||||
media.save()
|
||||
|
||||
# redirect
|
||||
return exc.HTTPFound(
|
||||
location=request.urlgen("mediagoblin.user_pages.media_home",
|
||||
user=media.uploader()['username'], media=media['_id']))
|
||||
return redirect(request, "mediagoblin.user_pages.media_home",
|
||||
user=media.uploader()['username'], media=media['slug'])
|
||||
|
||||
# render
|
||||
template = request.template_env.get_template(
|
||||
'mediagoblin/edit/edit.html')
|
||||
return Response(
|
||||
template.render(
|
||||
{'request': request,
|
||||
'media': media,
|
||||
'form': form}))
|
||||
return render_to_response(
|
||||
request,
|
||||
'mediagoblin/edit/edit.html',
|
||||
{'media': media,
|
||||
'form': form})
|
||||
|
@ -20,5 +20,5 @@ submit_routes = [
|
||||
Route('mediagoblin.submit.start', '/',
|
||||
controller='mediagoblin.submit.views:submit_start'),
|
||||
Route('mediagoblin.submit.success', '/success/',
|
||||
controller='mediagoblin.submit.views:submit_success'),
|
||||
]
|
||||
template='mediagoblin/submit/success.html',
|
||||
controller='mediagoblin.views:simple_template_render')]
|
||||
|
@ -17,9 +17,9 @@
|
||||
from os.path import splitext
|
||||
from cgi import FieldStorage
|
||||
|
||||
from webob import Response, exc
|
||||
from werkzeug.utils import secure_filename
|
||||
|
||||
from mediagoblin.util import render_to_response, redirect
|
||||
from mediagoblin.decorators import require_active_login
|
||||
from mediagoblin.submit import forms as submit_forms
|
||||
from mediagoblin.process_media import process_media_initial
|
||||
@ -75,23 +75,14 @@ def submit_start(request):
|
||||
# queue it for processing
|
||||
process_media_initial.delay(unicode(entry['_id']))
|
||||
|
||||
# redirect
|
||||
return exc.HTTPFound(
|
||||
location=request.urlgen("mediagoblin.submit.success"))
|
||||
return redirect(request, "mediagoblin.submit.success")
|
||||
|
||||
# render
|
||||
template = request.template_env.get_template(
|
||||
'mediagoblin/submit/start.html')
|
||||
return Response(
|
||||
template.render(
|
||||
{'request': request,
|
||||
'submit_form': submit_form}))
|
||||
return render_to_response(
|
||||
request,
|
||||
'mediagoblin/submit/start.html',
|
||||
{'submit_form': submit_form})
|
||||
|
||||
|
||||
def submit_success(request):
|
||||
# render
|
||||
template = request.template_env.get_template(
|
||||
'mediagoblin/submit/success.html')
|
||||
return Response(
|
||||
template.render(
|
||||
{'request': request}))
|
||||
return render_to_response(
|
||||
request, 'mediagoblin/submit/success.html', {})
|
||||
|
@ -33,7 +33,8 @@
|
||||
<input type="submit" value="submit" class="button"/>
|
||||
</div>
|
||||
{% if next %}
|
||||
<input type="hidden" name="next" value="{{ next }}" class="button" />
|
||||
<input type="hidden" name="next" value="{{ next }}" class="button"
|
||||
style="display: none;"/>
|
||||
{% endif %}
|
||||
<p>Don't have an account yet? <a href="{{ request.urlgen('mediagoblin.auth.register') }}">Create one here!</a></p>
|
||||
</div>
|
||||
|
46
mediagoblin/tests/mgoblin_test_app.ini
Normal file
46
mediagoblin/tests/mgoblin_test_app.ini
Normal file
@ -0,0 +1,46 @@
|
||||
[DEFAULT]
|
||||
debug = true
|
||||
|
||||
[composite:main]
|
||||
use = egg:Paste#urlmap
|
||||
/ = mediagoblin
|
||||
/mgoblin_media/ = publicstore_serve
|
||||
/mgoblin_static/ = mediagoblin_static
|
||||
|
||||
[app:mediagoblin]
|
||||
use = egg:mediagoblin#app
|
||||
filter-with = beaker
|
||||
queuestore_base_dir = %(here)s/test_user_dev/media/queue
|
||||
publicstore_base_dir = %(here)s/test_user_dev/media/public
|
||||
publicstore_base_url = /mgoblin_media/
|
||||
direct_remote_path = /mgoblin_static/
|
||||
email_sender_address = "notice@mediagoblin.example.org"
|
||||
email_debug_mode = true
|
||||
db_name = __mediagoblin_tests__
|
||||
# Celery shouldn't be set up by the paste app factory as it's set up
|
||||
# elsewhere
|
||||
celery_setup_elsewhere = true
|
||||
|
||||
[app:publicstore_serve]
|
||||
use = egg:Paste#static
|
||||
document_root = %(here)s/user_dev/media/public
|
||||
|
||||
[app:mediagoblin_static]
|
||||
use = egg:Paste#static
|
||||
document_root = %(here)s/mediagoblin/static/
|
||||
|
||||
[filter:beaker]
|
||||
use = egg:Beaker#beaker_session
|
||||
cache_dir = %(here)s/test_user_dev/beaker
|
||||
beaker.session.key = mediagoblin
|
||||
# beaker.session.secret = somesupersecret
|
||||
beaker.session.data_dir = %(here)s/test_user_dev/beaker/sessions/data
|
||||
beaker.session.lock_dir = %(here)s/test_user_dev/beaker/sessions/lock
|
||||
|
||||
[celery]
|
||||
celery_always_eager = true
|
||||
|
||||
[server:main]
|
||||
use = egg:Paste#http
|
||||
host = 127.0.0.1
|
||||
port = 6543
|
@ -14,8 +14,14 @@
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import urlparse
|
||||
|
||||
from nose.tools import assert_equal
|
||||
|
||||
from mediagoblin.auth import lib as auth_lib
|
||||
from mediagoblin.tests.tools import setup_fresh_app
|
||||
from mediagoblin import globals as mgoblin_globals
|
||||
from mediagoblin import util
|
||||
|
||||
|
||||
########################
|
||||
@ -57,3 +63,169 @@ def test_bcrypt_gen_password_hash():
|
||||
pw, hashed_pw, '3><7R45417')
|
||||
assert not auth_lib.bcrypt_check_password(
|
||||
'notthepassword', hashed_pw, '3><7R45417')
|
||||
|
||||
|
||||
@setup_fresh_app
|
||||
def test_register_views(test_app):
|
||||
"""
|
||||
Massive test function that all our registration-related views all work.
|
||||
"""
|
||||
# Test doing a simple GET on the page
|
||||
# -----------------------------------
|
||||
|
||||
test_app.get('/auth/register/')
|
||||
# Make sure it rendered with the appropriate template
|
||||
assert util.TEMPLATE_TEST_CONTEXT.has_key(
|
||||
'mediagoblin/auth/register.html')
|
||||
|
||||
# Try to register without providing anything, should error
|
||||
# --------------------------------------------------------
|
||||
|
||||
util.clear_test_template_context()
|
||||
test_app.post(
|
||||
'/auth/register/', {})
|
||||
context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
|
||||
form = context['register_form']
|
||||
assert form.username.errors == [u'This field is required.']
|
||||
assert form.password.errors == [u'This field is required.']
|
||||
assert form.confirm_password.errors == [u'This field is required.']
|
||||
assert form.email.errors == [u'This field is required.']
|
||||
|
||||
# Try to register with fields that are known to be invalid
|
||||
# --------------------------------------------------------
|
||||
|
||||
## too short
|
||||
util.clear_test_template_context()
|
||||
test_app.post(
|
||||
'/auth/register/', {
|
||||
'username': 'l',
|
||||
'password': 'o',
|
||||
'confirm_password': 'o',
|
||||
'email': 'l'})
|
||||
context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
|
||||
form = context['register_form']
|
||||
|
||||
assert form.username.errors == [
|
||||
u'Field must be between 3 and 30 characters long.']
|
||||
assert form.password.errors == [
|
||||
u'Field must be between 6 and 30 characters long.']
|
||||
|
||||
## bad form
|
||||
util.clear_test_template_context()
|
||||
test_app.post(
|
||||
'/auth/register/', {
|
||||
'username': '@_@',
|
||||
'email': 'lollerskates'})
|
||||
context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
|
||||
form = context['register_form']
|
||||
|
||||
assert form.username.errors == [
|
||||
u'Invalid input.']
|
||||
assert form.email.errors == [
|
||||
u'Invalid email address.']
|
||||
|
||||
## mismatching passwords
|
||||
util.clear_test_template_context()
|
||||
test_app.post(
|
||||
'/auth/register/', {
|
||||
'password': 'herpderp',
|
||||
'confirm_password': 'derpherp'})
|
||||
context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
|
||||
form = context['register_form']
|
||||
|
||||
assert form.password.errors == [
|
||||
u'Passwords must match.']
|
||||
|
||||
## At this point there should be no users in the database ;)
|
||||
assert not mgoblin_globals.database.User.find().count()
|
||||
|
||||
# Successful register
|
||||
# -------------------
|
||||
util.clear_test_template_context()
|
||||
response = test_app.post(
|
||||
'/auth/register/', {
|
||||
'username': 'happygirl',
|
||||
'password': 'iamsohappy',
|
||||
'confirm_password': 'iamsohappy',
|
||||
'email': 'happygrrl@example.org'})
|
||||
response.follow()
|
||||
|
||||
## Did we redirect to the proper page? Use the right template?
|
||||
assert_equal(
|
||||
urlparse.urlsplit(response.location)[2],
|
||||
'/auth/register/success/')
|
||||
assert util.TEMPLATE_TEST_CONTEXT.has_key(
|
||||
'mediagoblin/auth/register_success.html')
|
||||
|
||||
## Make sure user is in place
|
||||
new_user = mgoblin_globals.database.User.find_one(
|
||||
{'username': 'happygirl'})
|
||||
assert new_user
|
||||
assert new_user['status'] == u'needs_email_verification'
|
||||
assert new_user['email_verified'] == False
|
||||
|
||||
## Make sure we get email confirmation, and try verifying
|
||||
assert len(util.EMAIL_TEST_INBOX) == 1
|
||||
message = util.EMAIL_TEST_INBOX.pop()
|
||||
assert message['To'] == 'happygrrl@example.org'
|
||||
email_context = util.TEMPLATE_TEST_CONTEXT[
|
||||
'mediagoblin/auth/verification_email.txt']
|
||||
assert email_context['verification_url'] in message.get_payload(decode=True)
|
||||
|
||||
path = urlparse.urlsplit(email_context['verification_url'])[2]
|
||||
get_params = urlparse.urlsplit(email_context['verification_url'])[3]
|
||||
assert path == u'/auth/verify_email/'
|
||||
parsed_get_params = urlparse.parse_qs(get_params)
|
||||
|
||||
### user should have these same parameters
|
||||
assert parsed_get_params['userid'] == [
|
||||
unicode(new_user['_id'])]
|
||||
assert parsed_get_params['token'] == [
|
||||
new_user['verification_key']]
|
||||
|
||||
## Try verifying with bs verification key, shouldn't work
|
||||
util.clear_test_template_context()
|
||||
test_app.get(
|
||||
"/auth/verify_email/?userid=%s&token=total_bs" % unicode(
|
||||
new_user['_id']))
|
||||
context = util.TEMPLATE_TEST_CONTEXT[
|
||||
'mediagoblin/auth/verify_email.html']
|
||||
assert context['verification_successful'] == False
|
||||
new_user = mgoblin_globals.database.User.find_one(
|
||||
{'username': 'happygirl'})
|
||||
assert new_user
|
||||
assert new_user['status'] == u'needs_email_verification'
|
||||
assert new_user['email_verified'] == False
|
||||
|
||||
## Verify the email activation works
|
||||
util.clear_test_template_context()
|
||||
test_app.get("%s?%s" % (path, get_params))
|
||||
context = util.TEMPLATE_TEST_CONTEXT[
|
||||
'mediagoblin/auth/verify_email.html']
|
||||
assert context['verification_successful'] == True
|
||||
new_user = mgoblin_globals.database.User.find_one(
|
||||
{'username': 'happygirl'})
|
||||
assert new_user
|
||||
assert new_user['status'] == u'active'
|
||||
assert new_user['email_verified'] == True
|
||||
|
||||
## TODO: Try logging in
|
||||
|
||||
# Uniqueness checks
|
||||
# -----------------
|
||||
## We shouldn't be able to register with that user twice
|
||||
util.clear_test_template_context()
|
||||
response = test_app.post(
|
||||
'/auth/register/', {
|
||||
'username': 'happygirl',
|
||||
'password': 'iamsohappy2',
|
||||
'confirm_password': 'iamsohappy2',
|
||||
'email': 'happygrrl2@example.org'})
|
||||
|
||||
context = util.TEMPLATE_TEST_CONTEXT[
|
||||
'mediagoblin/auth/register.html']
|
||||
form = context['register_form']
|
||||
assert form.username.errors == [
|
||||
u'Sorry, a user with that name already exists.']
|
||||
|
||||
## TODO: Also check for double instances of an email address?
|
||||
|
38
mediagoblin/tests/test_tests.py
Normal file
38
mediagoblin/tests/test_tests.py
Normal file
@ -0,0 +1,38 @@
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
from mediagoblin.tests.tools import get_test_app
|
||||
|
||||
from mediagoblin import globals as mgoblin_globals
|
||||
|
||||
|
||||
def test_get_test_app_wipes_db():
|
||||
"""
|
||||
Make sure we get a fresh database on every wipe :)
|
||||
"""
|
||||
get_test_app()
|
||||
assert mgoblin_globals.database.User.find().count() == 0
|
||||
|
||||
new_user = mgoblin_globals.database.User()
|
||||
new_user['username'] = u'lolcat'
|
||||
new_user['email'] = u'lol@cats.example.org'
|
||||
new_user['pw_hash'] = u'pretend_this_is_a_hash'
|
||||
new_user.save()
|
||||
assert mgoblin_globals.database.User.find().count() == 1
|
||||
|
||||
get_test_app()
|
||||
|
||||
assert mgoblin_globals.database.User.find().count() == 0
|
109
mediagoblin/tests/tools.py
Normal file
109
mediagoblin/tests/tools.py
Normal file
@ -0,0 +1,109 @@
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
import pkg_resources
|
||||
import os, shutil
|
||||
|
||||
from paste.deploy import appconfig, loadapp
|
||||
from webtest import TestApp
|
||||
|
||||
from mediagoblin import util
|
||||
from mediagoblin.decorators import _make_safe
|
||||
from mediagoblin.db.open import setup_connection_and_db_from_config
|
||||
|
||||
|
||||
MEDIAGOBLIN_TEST_DB_NAME = '__mediagoblinunittests__'
|
||||
TEST_APP_CONFIG = pkg_resources.resource_filename(
|
||||
'mediagoblin.tests', 'mgoblin_test_app.ini')
|
||||
TEST_USER_DEV = pkg_resources.resource_filename(
|
||||
'mediagoblin.tests', 'test_user_dev')
|
||||
MGOBLIN_APP = None
|
||||
|
||||
USER_DEV_DIRECTORIES_TO_SETUP = [
|
||||
'media/public', 'media/queue',
|
||||
'beaker/sessions/data', 'beaker/sessions/lock']
|
||||
|
||||
|
||||
class BadCeleryEnviron(Exception): pass
|
||||
|
||||
|
||||
def get_test_app(dump_old_app=True):
|
||||
if not os.environ.get('CELERY_CONFIG_MODULE') == \
|
||||
'mediagoblin.celery_setup.from_tests':
|
||||
raise BadCeleryEnviron(
|
||||
u"Sorry, you *absolutely* must run nosetests with the\n"
|
||||
u"mediagoblin.celery_setup.from_tests module. Like so:\n"
|
||||
u"$ CELERY_CONFIG_MODULE=mediagoblin.celery_setup.from_tests ./bin/nosetests")
|
||||
|
||||
# Just return the old app if that exists and it's okay to set up
|
||||
# and return
|
||||
if MGOBLIN_APP and not dump_old_app:
|
||||
return MGOBLIN_APP
|
||||
|
||||
# Remove and reinstall user_dev directories
|
||||
if os.path.exists(TEST_USER_DEV):
|
||||
shutil.rmtree(TEST_USER_DEV)
|
||||
|
||||
for directory in USER_DEV_DIRECTORIES_TO_SETUP:
|
||||
full_dir = os.path.join(TEST_USER_DEV, directory)
|
||||
os.makedirs(full_dir)
|
||||
|
||||
# Get app config
|
||||
config = appconfig(
|
||||
'config:' + os.path.basename(TEST_APP_CONFIG),
|
||||
relative_to=os.path.dirname(TEST_APP_CONFIG),
|
||||
name='mediagoblin')
|
||||
|
||||
# Wipe database
|
||||
# @@: For now we're dropping collections, but we could also just
|
||||
# collection.remove() ?
|
||||
connection, db = setup_connection_and_db_from_config(
|
||||
config.local_conf)
|
||||
|
||||
collections_to_wipe = [
|
||||
collection
|
||||
for collection in db.collection_names()
|
||||
if not collection.startswith('system.')]
|
||||
|
||||
for collection in collections_to_wipe:
|
||||
db.drop_collection(collection)
|
||||
|
||||
# Don't need these anymore...
|
||||
del(connection)
|
||||
del(db)
|
||||
|
||||
# TODO: Drop and recreate indexes
|
||||
|
||||
# setup app and return
|
||||
test_app = loadapp(
|
||||
'config:' + TEST_APP_CONFIG)
|
||||
|
||||
return TestApp(test_app)
|
||||
|
||||
|
||||
def setup_fresh_app(func):
|
||||
"""
|
||||
Decorator to setup a fresh test application for this function.
|
||||
|
||||
Cleans out test buckets and passes in a new, fresh test_app.
|
||||
"""
|
||||
def wrapper(*args, **kwargs):
|
||||
test_app = get_test_app()
|
||||
util.clear_test_buckets()
|
||||
return func(test_app, *args, **kwargs)
|
||||
|
||||
return _make_safe(wrapper, func)
|
@ -22,5 +22,7 @@ user_routes = [
|
||||
Route('mediagoblin.user_pages.media_home', '/{user}/m/{media}/',
|
||||
requirements=dict(m_id="[0-9a-fA-F]{24}"),
|
||||
controller="mediagoblin.user_pages.views:media_home"),
|
||||
Route('mediagoblin.edit.edit_media', "/{user}/m/{media}/edit/",
|
||||
controller="mediagoblin.edit.views:edit_media"),
|
||||
Route('mediagoblin.user_pages.atom_feed', '/{user}/atom/',
|
||||
controller="mediagoblin.user_pages.views:atom_feed")]
|
||||
|
@ -14,9 +14,9 @@
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from webob import Response, exc
|
||||
from webob import exc
|
||||
from mediagoblin.db.util import DESCENDING
|
||||
from mediagoblin.util import Pagination
|
||||
from mediagoblin.util import Pagination, render_to_response
|
||||
|
||||
from mediagoblin.decorators import uses_pagination, get_user_media_entry
|
||||
|
||||
@ -42,26 +42,22 @@ def user_home(request, page):
|
||||
if media_entries == None:
|
||||
return exc.HTTPNotFound()
|
||||
|
||||
template = request.template_env.get_template(
|
||||
'mediagoblin/user_pages/user.html')
|
||||
|
||||
return Response(
|
||||
template.render(
|
||||
{'request': request,
|
||||
'user': user,
|
||||
'media_entries': media_entries,
|
||||
'pagination': pagination}))
|
||||
return render_to_response(
|
||||
request,
|
||||
'mediagoblin/user_pages/user.html',
|
||||
{'user': user,
|
||||
'media_entries': media_entries,
|
||||
'pagination': pagination})
|
||||
|
||||
|
||||
@get_user_media_entry
|
||||
def media_home(request, media):
|
||||
"""'Homepage' of a MediaEntry()"""
|
||||
template = request.template_env.get_template(
|
||||
'mediagoblin/user_pages/media.html')
|
||||
return Response(
|
||||
template.render(
|
||||
{'request': request,
|
||||
'media': media}))
|
||||
return render_to_response(
|
||||
request,
|
||||
'mediagoblin/user_pages/media.html',
|
||||
{'media': media})
|
||||
|
||||
|
||||
ATOM_DEFAULT_NR_OF_UPDATED_ITEMS = 5
|
||||
|
||||
|
@ -18,18 +18,23 @@ from email.MIMEText import MIMEText
|
||||
import gettext
|
||||
import pkg_resources
|
||||
import smtplib
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
import jinja2
|
||||
from mediagoblin.db.util import ObjectId
|
||||
import translitcodec
|
||||
|
||||
from mediagoblin import globals as mgoblin_globals
|
||||
|
||||
import urllib
|
||||
from math import ceil
|
||||
import copy
|
||||
|
||||
from babel.localedata import exists
|
||||
import jinja2
|
||||
import translitcodec
|
||||
from paste.deploy.loadwsgi import NicerConfigParser
|
||||
from webob import Response, exc
|
||||
|
||||
from mediagoblin import globals as mgoblin_globals
|
||||
from mediagoblin.db.util import ObjectId
|
||||
|
||||
|
||||
TESTS_ENABLED = False
|
||||
def _activate_testing():
|
||||
"""
|
||||
@ -39,6 +44,26 @@ def _activate_testing():
|
||||
TESTS_ENABLED = True
|
||||
|
||||
|
||||
def clear_test_buckets():
|
||||
"""
|
||||
We store some things for testing purposes that should be cleared
|
||||
when we want a "clean slate" of information for our next round of
|
||||
tests. Call this function to wipe all that stuff clean.
|
||||
|
||||
Also wipes out some other things we might redefine during testing,
|
||||
like the jinja envs.
|
||||
"""
|
||||
global SETUP_JINJA_ENVS
|
||||
SETUP_JINJA_ENVS = {}
|
||||
|
||||
global EMAIL_TEST_INBOX
|
||||
global EMAIL_TEST_MBOX_INBOX
|
||||
EMAIL_TEST_INBOX = []
|
||||
EMAIL_TEST_MBOX_INBOX = []
|
||||
|
||||
clear_test_template_context()
|
||||
|
||||
|
||||
def get_jinja_loader(user_template_path=None):
|
||||
"""
|
||||
Set up the Jinja template loaders, possibly allowing for user
|
||||
@ -55,6 +80,9 @@ def get_jinja_loader(user_template_path=None):
|
||||
return jinja2.PackageLoader('mediagoblin', 'templates')
|
||||
|
||||
|
||||
SETUP_JINJA_ENVS = {}
|
||||
|
||||
|
||||
def get_jinja_env(template_loader, locale):
|
||||
"""
|
||||
Set up the Jinja environment,
|
||||
@ -64,6 +92,11 @@ def get_jinja_env(template_loader, locale):
|
||||
"""
|
||||
setup_gettext(locale)
|
||||
|
||||
# If we have a jinja environment set up with this locale, just
|
||||
# return that one.
|
||||
if SETUP_JINJA_ENVS.has_key(locale):
|
||||
return SETUP_JINJA_ENVS[locale]
|
||||
|
||||
template_env = jinja2.Environment(
|
||||
loader=template_loader, autoescape=True,
|
||||
extensions=['jinja2.ext.i18n'])
|
||||
@ -72,9 +105,49 @@ def get_jinja_env(template_loader, locale):
|
||||
mgoblin_globals.translations.gettext,
|
||||
mgoblin_globals.translations.ngettext)
|
||||
|
||||
if exists(locale):
|
||||
SETUP_JINJA_ENVS[locale] = template_env
|
||||
|
||||
return template_env
|
||||
|
||||
|
||||
# We'll store context information here when doing unit tests
|
||||
TEMPLATE_TEST_CONTEXT = {}
|
||||
|
||||
|
||||
def render_template(request, template_path, context):
|
||||
"""
|
||||
Render a template with context.
|
||||
|
||||
Always inserts the request into the context, so you don't have to.
|
||||
Also stores the context if we're doing unit tests. Helpful!
|
||||
"""
|
||||
template = request.template_env.get_template(
|
||||
template_path)
|
||||
context['request'] = request
|
||||
rendered = template.render(context)
|
||||
|
||||
if TESTS_ENABLED:
|
||||
TEMPLATE_TEST_CONTEXT[template_path] = context
|
||||
|
||||
return rendered
|
||||
|
||||
|
||||
def clear_test_template_context():
|
||||
global TEMPLATE_TEST_CONTEXT
|
||||
TEMPLATE_TEST_CONTEXT = {}
|
||||
|
||||
|
||||
def render_to_response(request, template, context):
|
||||
"""Much like Django's shortcut.render()"""
|
||||
return Response(render_template(request, template, context))
|
||||
|
||||
|
||||
def redirect(request, *args, **kwargs):
|
||||
"""Returns a HTTPFound(), takes a request and then urlgen params"""
|
||||
return exc.HTTPFound(location=request.urlgen(*args, **kwargs))
|
||||
|
||||
|
||||
def setup_user_in_request(request):
|
||||
"""
|
||||
Examine a request and tack on a request.user parameter if that's
|
||||
@ -278,6 +351,30 @@ def get_locale_from_request(request):
|
||||
return locale_to_lower_upper(target_lang)
|
||||
|
||||
|
||||
def read_config_file(conf_file):
|
||||
"""
|
||||
Read a paste deploy style config file and process it.
|
||||
"""
|
||||
if not os.path.exists(conf_file):
|
||||
raise IOError(
|
||||
"MEDIAGOBLIN_CONFIG not set or file does not exist")
|
||||
|
||||
parser = NicerConfigParser(conf_file)
|
||||
parser.read(conf_file)
|
||||
parser._defaults.setdefault(
|
||||
'here', os.path.dirname(os.path.abspath(conf_file)))
|
||||
parser._defaults.setdefault(
|
||||
'__file__', os.path.abspath(conf_file))
|
||||
|
||||
mgoblin_conf = dict(
|
||||
[(section_name, dict(parser.items(section_name)))
|
||||
for section_name in parser.sections()])
|
||||
|
||||
return mgoblin_conf
|
||||
|
||||
|
||||
SETUP_GETTEXTS = {}
|
||||
|
||||
def setup_gettext(locale):
|
||||
"""
|
||||
Setup the gettext instance based on this locale
|
||||
@ -288,8 +385,13 @@ def setup_gettext(locale):
|
||||
|
||||
# TODO: fallback nicely on translations from pt_PT to pt if not
|
||||
# available, etc.
|
||||
this_gettext = gettext.translation(
|
||||
'mediagoblin', TRANSLATIONS_PATH, [locale], fallback=True)
|
||||
if SETUP_GETTEXTS.has_key(locale):
|
||||
this_gettext = SETUP_GETTEXTS[locale]
|
||||
else:
|
||||
this_gettext = gettext.translation(
|
||||
'mediagoblin', TRANSLATIONS_PATH, [locale], fallback=True)
|
||||
if exists(locale):
|
||||
SETUP_GETTEXTS[locale] = this_gettext
|
||||
|
||||
mgoblin_globals.setup_globals(
|
||||
translations=this_gettext)
|
||||
|
@ -14,16 +14,23 @@
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from webob import Response
|
||||
from mediagoblin.util import render_to_response
|
||||
from mediagoblin.db.util import DESCENDING
|
||||
|
||||
def root_view(request):
|
||||
media_entries = request.db.MediaEntry.find(
|
||||
{u'state': u'processed'}).sort('created', DESCENDING)
|
||||
|
||||
template = request.template_env.get_template(
|
||||
'mediagoblin/root.html')
|
||||
return Response(
|
||||
template.render(
|
||||
{'request': request,
|
||||
'media_entries': media_entries}))
|
||||
return render_to_response(
|
||||
request, 'mediagoblin/root.html',
|
||||
{'media_entries': media_entries})
|
||||
|
||||
|
||||
def simple_template_render(request):
|
||||
"""
|
||||
A view for absolutely simple template rendering.
|
||||
Just make sure 'template' is in the matchdict!
|
||||
"""
|
||||
template_name = request.matchdict['template']
|
||||
return render_to_response(
|
||||
request, template_name, {})
|
||||
|
Loading…
x
Reference in New Issue
Block a user