Merge remote-tracking branch 'gitorious/master'
This commit is contained in:
commit
ec8f66bd65
@ -152,7 +152,7 @@ Running the test suite
|
|||||||
|
|
||||||
Run::
|
Run::
|
||||||
|
|
||||||
./bin/nosetests
|
CELERY_CONFIG_MODULE=mediagoblin.celery_setup.from_tests ./bin/nosetests
|
||||||
|
|
||||||
|
|
||||||
Running a shell
|
Running a shell
|
||||||
|
@ -139,12 +139,13 @@ def paste_app_factory(global_config, **app_config):
|
|||||||
raise ImproperlyConfigured(
|
raise ImproperlyConfigured(
|
||||||
"One of direct_remote_path or direct_remote_paths must be provided")
|
"One of direct_remote_path or direct_remote_paths must be provided")
|
||||||
|
|
||||||
if asbool(os.environ.get('CELERY_ALWAYS_EAGER')):
|
if not asbool(app_config.get('celery_setup_elsewhere')):
|
||||||
setup_celery_from_config(
|
if asbool(os.environ.get('CELERY_ALWAYS_EAGER')):
|
||||||
app_config, global_config,
|
setup_celery_from_config(
|
||||||
force_celery_always_eager=True)
|
app_config, global_config,
|
||||||
else:
|
force_celery_always_eager=True)
|
||||||
setup_celery_from_config(app_config, global_config)
|
else:
|
||||||
|
setup_celery_from_config(app_config, global_config)
|
||||||
|
|
||||||
mgoblin_app = MediaGoblinApp(
|
mgoblin_app = MediaGoblinApp(
|
||||||
connection, db,
|
connection, db,
|
||||||
|
@ -27,7 +27,9 @@ class RegistrationForm(wtforms.Form):
|
|||||||
'Password',
|
'Password',
|
||||||
[wtforms.validators.Required(),
|
[wtforms.validators.Required(),
|
||||||
wtforms.validators.Length(min=6, max=30),
|
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.PasswordField(
|
||||||
'Confirm password',
|
'Confirm password',
|
||||||
[wtforms.validators.Required()])
|
[wtforms.validators.Required()])
|
||||||
|
@ -19,7 +19,7 @@ import random
|
|||||||
|
|
||||||
import bcrypt
|
import bcrypt
|
||||||
|
|
||||||
from mediagoblin.util import send_email
|
from mediagoblin.util import send_email, render_template
|
||||||
from mediagoblin import globals as mgoblin_globals
|
from mediagoblin import globals as mgoblin_globals
|
||||||
|
|
||||||
|
|
||||||
@ -89,6 +89,10 @@ def fake_login_attempt():
|
|||||||
randplus_stored_hash == randplus_hashed_pass
|
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):
|
def send_verification_email(user, request):
|
||||||
"""
|
"""
|
||||||
Send the verification email to users to activate their accounts.
|
Send the verification email to users to activate their accounts.
|
||||||
@ -97,9 +101,14 @@ def send_verification_email(user, request):
|
|||||||
- user: a user object
|
- user: a user object
|
||||||
- request: the request
|
- request: the request
|
||||||
"""
|
"""
|
||||||
|
rendered_email = render_template(
|
||||||
email_template = request.template_env.get_template(
|
request, 'mediagoblin/auth/verification_email.txt',
|
||||||
'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
|
# TODO: There is no error handling in place
|
||||||
send_email(
|
send_email(
|
||||||
@ -111,10 +120,4 @@ def send_verification_email(user, request):
|
|||||||
# specific GNU MediaGoblin instance in the subject line. For
|
# specific GNU MediaGoblin instance in the subject line. For
|
||||||
# example "GNU MediaGoblin @ Wandborg - [...]".
|
# example "GNU MediaGoblin @ Wandborg - [...]".
|
||||||
'GNU MediaGoblin - Verify your email!',
|
'GNU MediaGoblin - Verify your email!',
|
||||||
email_template.render(
|
rendered_email)
|
||||||
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'])))
|
|
||||||
|
@ -20,7 +20,8 @@ auth_routes = [
|
|||||||
Route('mediagoblin.auth.register', '/register/',
|
Route('mediagoblin.auth.register', '/register/',
|
||||||
controller='mediagoblin.auth.views:register'),
|
controller='mediagoblin.auth.views:register'),
|
||||||
Route('mediagoblin.auth.register_success', '/register/success/',
|
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/',
|
Route('mediagoblin.auth.login', '/login/',
|
||||||
controller='mediagoblin.auth.views:login'),
|
controller='mediagoblin.auth.views:login'),
|
||||||
Route('mediagoblin.auth.logout', '/logout/',
|
Route('mediagoblin.auth.logout', '/logout/',
|
||||||
@ -28,9 +29,11 @@ auth_routes = [
|
|||||||
Route('mediagoblin.auth.verify_email', '/verify_email/',
|
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/',
|
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/',
|
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',
|
Route('mediagoblin.auth.resend_verification_success',
|
||||||
'/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
|
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.db.util import ObjectId
|
||||||
from mediagoblin.auth import lib as auth_lib
|
from mediagoblin.auth import lib as auth_lib
|
||||||
from mediagoblin.auth import forms as auth_forms
|
from mediagoblin.auth import forms as auth_forms
|
||||||
@ -53,25 +54,12 @@ def register(request):
|
|||||||
|
|
||||||
send_verification_email(entry, request)
|
send_verification_email(entry, request)
|
||||||
|
|
||||||
# Redirect to register_success
|
return redirect(request, "mediagoblin.auth.register_success")
|
||||||
return exc.HTTPFound(
|
|
||||||
location=request.urlgen("mediagoblin.auth.register_success"))
|
|
||||||
|
|
||||||
# render
|
return render_to_response(
|
||||||
template = request.template_env.get_template(
|
request,
|
||||||
'mediagoblin/auth/register.html')
|
'mediagoblin/auth/register.html',
|
||||||
return Response(
|
{'register_form': register_form})
|
||||||
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(request):
|
def login(request):
|
||||||
@ -96,8 +84,7 @@ def login(request):
|
|||||||
if request.POST.get('next'):
|
if request.POST.get('next'):
|
||||||
return exc.HTTPFound(location=request.POST['next'])
|
return exc.HTTPFound(location=request.POST['next'])
|
||||||
else:
|
else:
|
||||||
return exc.HTTPFound(
|
return redirect(request, "index")
|
||||||
location=request.urlgen("index"))
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Prevent detecting who's on this system by testing login
|
# Prevent detecting who's on this system by testing login
|
||||||
@ -105,23 +92,19 @@ def login(request):
|
|||||||
auth_lib.fake_login_attempt()
|
auth_lib.fake_login_attempt()
|
||||||
login_failed = True
|
login_failed = True
|
||||||
|
|
||||||
# render
|
return render_to_response(
|
||||||
template = request.template_env.get_template(
|
request,
|
||||||
'mediagoblin/auth/login.html')
|
'mediagoblin/auth/login.html',
|
||||||
return Response(
|
{'login_form': login_form,
|
||||||
template.render(
|
'next': request.GET.get('next') or request.POST.get('next'),
|
||||||
{'request': request,
|
'login_failed': login_failed})
|
||||||
'login_form': login_form,
|
|
||||||
'next': request.GET.get('next') or request.POST.get('next'),
|
|
||||||
'login_failed': login_failed}))
|
|
||||||
|
|
||||||
|
|
||||||
def logout(request):
|
def logout(request):
|
||||||
# Maybe deleting the user_id parameter would be enough?
|
# Maybe deleting the user_id parameter would be enough?
|
||||||
request.session.delete()
|
request.session.delete()
|
||||||
|
|
||||||
return exc.HTTPFound(
|
return redirect(request, "index")
|
||||||
location=request.urlgen("index"))
|
|
||||||
|
|
||||||
|
|
||||||
def verify_email(request):
|
def verify_email(request):
|
||||||
@ -146,27 +129,11 @@ def verify_email(request):
|
|||||||
else:
|
else:
|
||||||
verification_successful = False
|
verification_successful = False
|
||||||
|
|
||||||
template = request.template_env.get_template(
|
return render_to_response(
|
||||||
'mediagoblin/auth/verify_email.html')
|
request,
|
||||||
return Response(
|
'mediagoblin/auth/verify_email.html',
|
||||||
template.render(
|
{'user': user,
|
||||||
{'request': request,
|
'verification_successful': verification_successful})
|
||||||
'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}))
|
|
||||||
|
|
||||||
|
|
||||||
def resend_activation(request):
|
def resend_activation(request):
|
||||||
@ -175,19 +142,9 @@ def resend_activation(request):
|
|||||||
|
|
||||||
Resend the activation email.
|
Resend the activation email.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
request.user['verification_key'] = unicode(uuid.uuid4())
|
request.user['verification_key'] = unicode(uuid.uuid4())
|
||||||
request.user.save()
|
request.user.save()
|
||||||
|
|
||||||
send_verification_email(request.user, request)
|
send_verification_email(request.user, request)
|
||||||
|
|
||||||
return exc.HTTPFound(
|
return redirect(request, 'mediagoblin.auth.resend_verification_success')
|
||||||
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}))
|
|
||||||
|
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 bson.errors import InvalidId
|
||||||
from webob import exc
|
from webob import exc
|
||||||
|
|
||||||
|
from mediagoblin.util import redirect
|
||||||
from mediagoblin.db.util import ObjectId
|
from mediagoblin.db.util import ObjectId
|
||||||
|
|
||||||
|
|
||||||
@ -38,9 +39,8 @@ def require_active_login(controller):
|
|||||||
def new_controller_func(request, *args, **kwargs):
|
def new_controller_func(request, *args, **kwargs):
|
||||||
if request.user and \
|
if request.user and \
|
||||||
request.user.get('status') == u'needs_email_verification':
|
request.user.get('status') == u'needs_email_verification':
|
||||||
return exc.HTTPFound(
|
return redirect(request,
|
||||||
location = request.urlgen(
|
'mediagoblin.auth.verify_email_notice')
|
||||||
'mediagoblin.auth.verify_email_notice'))
|
|
||||||
elif not request.user or request.user.get('status') != u'active':
|
elif not request.user or request.user.get('status') != u'active':
|
||||||
return exc.HTTPFound(
|
return exc.HTTPFound(
|
||||||
location="%s?next=%s" % (
|
location="%s?next=%s" % (
|
||||||
|
@ -14,9 +14,9 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
from routes.route import Route
|
from routes.route import Route
|
||||||
|
|
||||||
edit_routes = [
|
edit_routes = [
|
||||||
Route('mediagoblin.edit.edit_media', "/{user}/{media}/",
|
# Media editing view handled in user_pages/routing.py
|
||||||
controller="mediagoblin.edit.views:edit_media"),
|
|
||||||
]
|
]
|
||||||
|
@ -15,8 +15,9 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# 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 import forms
|
||||||
from mediagoblin.edit.lib import may_edit_media
|
from mediagoblin.edit.lib import may_edit_media
|
||||||
from mediagoblin.decorators import require_active_login, get_user_media_entry
|
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['title'] = request.POST['title']
|
||||||
media['description'] = request.POST['description']
|
media['description'] = request.POST['description']
|
||||||
media['slug'] = request.POST['slug']
|
media['slug'] = request.POST['slug']
|
||||||
|
media.save()
|
||||||
|
|
||||||
# redirect
|
return redirect(request, "mediagoblin.user_pages.media_home",
|
||||||
return exc.HTTPFound(
|
user=media.uploader()['username'], media=media['slug'])
|
||||||
location=request.urlgen("mediagoblin.user_pages.media_home",
|
|
||||||
user=media.uploader()['username'], media=media['_id']))
|
|
||||||
|
|
||||||
# render
|
return render_to_response(
|
||||||
template = request.template_env.get_template(
|
request,
|
||||||
'mediagoblin/edit/edit.html')
|
'mediagoblin/edit/edit.html',
|
||||||
return Response(
|
{'media': media,
|
||||||
template.render(
|
'form': form})
|
||||||
{'request': request,
|
|
||||||
'media': media,
|
|
||||||
'form': form}))
|
|
||||||
|
@ -20,5 +20,5 @@ submit_routes = [
|
|||||||
Route('mediagoblin.submit.start', '/',
|
Route('mediagoblin.submit.start', '/',
|
||||||
controller='mediagoblin.submit.views:submit_start'),
|
controller='mediagoblin.submit.views:submit_start'),
|
||||||
Route('mediagoblin.submit.success', '/success/',
|
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 os.path import splitext
|
||||||
from cgi import FieldStorage
|
from cgi import FieldStorage
|
||||||
|
|
||||||
from webob import Response, exc
|
|
||||||
from werkzeug.utils import secure_filename
|
from werkzeug.utils import secure_filename
|
||||||
|
|
||||||
|
from mediagoblin.util import render_to_response, redirect
|
||||||
from mediagoblin.decorators import require_active_login
|
from mediagoblin.decorators import require_active_login
|
||||||
from mediagoblin.submit import forms as submit_forms
|
from mediagoblin.submit import forms as submit_forms
|
||||||
from mediagoblin.process_media import process_media_initial
|
from mediagoblin.process_media import process_media_initial
|
||||||
@ -75,23 +75,14 @@ def submit_start(request):
|
|||||||
# queue it for processing
|
# queue it for processing
|
||||||
process_media_initial.delay(unicode(entry['_id']))
|
process_media_initial.delay(unicode(entry['_id']))
|
||||||
|
|
||||||
# redirect
|
return redirect(request, "mediagoblin.submit.success")
|
||||||
return exc.HTTPFound(
|
|
||||||
location=request.urlgen("mediagoblin.submit.success"))
|
|
||||||
|
|
||||||
# render
|
return render_to_response(
|
||||||
template = request.template_env.get_template(
|
request,
|
||||||
'mediagoblin/submit/start.html')
|
'mediagoblin/submit/start.html',
|
||||||
return Response(
|
{'submit_form': submit_form})
|
||||||
template.render(
|
|
||||||
{'request': request,
|
|
||||||
'submit_form': submit_form}))
|
|
||||||
|
|
||||||
|
|
||||||
def submit_success(request):
|
def submit_success(request):
|
||||||
# render
|
return render_to_response(
|
||||||
template = request.template_env.get_template(
|
request, 'mediagoblin/submit/success.html', {})
|
||||||
'mediagoblin/submit/success.html')
|
|
||||||
return Response(
|
|
||||||
template.render(
|
|
||||||
{'request': request}))
|
|
||||||
|
@ -33,7 +33,8 @@
|
|||||||
<input type="submit" value="submit" class="button"/>
|
<input type="submit" value="submit" class="button"/>
|
||||||
</div>
|
</div>
|
||||||
{% if next %}
|
{% if next %}
|
||||||
<input type="hidden" name="next" value="{{ next }}" class="button" />
|
<input type="hidden" name="next" value="{{ next }}" class="button"
|
||||||
|
style="display: none;"/>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<p>Don't have an account yet? <a href="{{ request.urlgen('mediagoblin.auth.register') }}">Create one here!</a></p>
|
<p>Don't have an account yet? <a href="{{ request.urlgen('mediagoblin.auth.register') }}">Create one here!</a></p>
|
||||||
</div>
|
</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
|
# 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/>.
|
# 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.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')
|
pw, hashed_pw, '3><7R45417')
|
||||||
assert not auth_lib.bcrypt_check_password(
|
assert not auth_lib.bcrypt_check_password(
|
||||||
'notthepassword', hashed_pw, '3><7R45417')
|
'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}/',
|
Route('mediagoblin.user_pages.media_home', '/{user}/m/{media}/',
|
||||||
requirements=dict(m_id="[0-9a-fA-F]{24}"),
|
requirements=dict(m_id="[0-9a-fA-F]{24}"),
|
||||||
controller="mediagoblin.user_pages.views:media_home"),
|
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/',
|
Route('mediagoblin.user_pages.atom_feed', '/{user}/atom/',
|
||||||
controller="mediagoblin.user_pages.views:atom_feed")]
|
controller="mediagoblin.user_pages.views:atom_feed")]
|
||||||
|
@ -14,9 +14,9 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# 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.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
|
from mediagoblin.decorators import uses_pagination, get_user_media_entry
|
||||||
|
|
||||||
@ -42,26 +42,22 @@ def user_home(request, page):
|
|||||||
if media_entries == None:
|
if media_entries == None:
|
||||||
return exc.HTTPNotFound()
|
return exc.HTTPNotFound()
|
||||||
|
|
||||||
template = request.template_env.get_template(
|
return render_to_response(
|
||||||
'mediagoblin/user_pages/user.html')
|
request,
|
||||||
|
'mediagoblin/user_pages/user.html',
|
||||||
return Response(
|
{'user': user,
|
||||||
template.render(
|
'media_entries': media_entries,
|
||||||
{'request': request,
|
'pagination': pagination})
|
||||||
'user': user,
|
|
||||||
'media_entries': media_entries,
|
|
||||||
'pagination': pagination}))
|
|
||||||
|
|
||||||
|
|
||||||
@get_user_media_entry
|
@get_user_media_entry
|
||||||
def media_home(request, media):
|
def media_home(request, media):
|
||||||
"""'Homepage' of a MediaEntry()"""
|
"""'Homepage' of a MediaEntry()"""
|
||||||
template = request.template_env.get_template(
|
return render_to_response(
|
||||||
'mediagoblin/user_pages/media.html')
|
request,
|
||||||
return Response(
|
'mediagoblin/user_pages/media.html',
|
||||||
template.render(
|
{'media': media})
|
||||||
{'request': request,
|
|
||||||
'media': media}))
|
|
||||||
|
|
||||||
ATOM_DEFAULT_NR_OF_UPDATED_ITEMS = 5
|
ATOM_DEFAULT_NR_OF_UPDATED_ITEMS = 5
|
||||||
|
|
||||||
|
@ -18,18 +18,23 @@ from email.MIMEText import MIMEText
|
|||||||
import gettext
|
import gettext
|
||||||
import pkg_resources
|
import pkg_resources
|
||||||
import smtplib
|
import smtplib
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
import re
|
import re
|
||||||
import jinja2
|
|
||||||
from mediagoblin.db.util import ObjectId
|
|
||||||
import translitcodec
|
|
||||||
|
|
||||||
from mediagoblin import globals as mgoblin_globals
|
|
||||||
|
|
||||||
import urllib
|
import urllib
|
||||||
from math import ceil
|
from math import ceil
|
||||||
import copy
|
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
|
TESTS_ENABLED = False
|
||||||
def _activate_testing():
|
def _activate_testing():
|
||||||
"""
|
"""
|
||||||
@ -39,6 +44,26 @@ def _activate_testing():
|
|||||||
TESTS_ENABLED = True
|
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):
|
def get_jinja_loader(user_template_path=None):
|
||||||
"""
|
"""
|
||||||
Set up the Jinja template loaders, possibly allowing for user
|
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')
|
return jinja2.PackageLoader('mediagoblin', 'templates')
|
||||||
|
|
||||||
|
|
||||||
|
SETUP_JINJA_ENVS = {}
|
||||||
|
|
||||||
|
|
||||||
def get_jinja_env(template_loader, locale):
|
def get_jinja_env(template_loader, locale):
|
||||||
"""
|
"""
|
||||||
Set up the Jinja environment,
|
Set up the Jinja environment,
|
||||||
@ -64,6 +92,11 @@ def get_jinja_env(template_loader, locale):
|
|||||||
"""
|
"""
|
||||||
setup_gettext(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(
|
template_env = jinja2.Environment(
|
||||||
loader=template_loader, autoescape=True,
|
loader=template_loader, autoescape=True,
|
||||||
extensions=['jinja2.ext.i18n'])
|
extensions=['jinja2.ext.i18n'])
|
||||||
@ -72,9 +105,49 @@ def get_jinja_env(template_loader, locale):
|
|||||||
mgoblin_globals.translations.gettext,
|
mgoblin_globals.translations.gettext,
|
||||||
mgoblin_globals.translations.ngettext)
|
mgoblin_globals.translations.ngettext)
|
||||||
|
|
||||||
|
if exists(locale):
|
||||||
|
SETUP_JINJA_ENVS[locale] = template_env
|
||||||
|
|
||||||
return 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):
|
def setup_user_in_request(request):
|
||||||
"""
|
"""
|
||||||
Examine a request and tack on a request.user parameter if that's
|
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)
|
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):
|
def setup_gettext(locale):
|
||||||
"""
|
"""
|
||||||
Setup the gettext instance based on this 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
|
# TODO: fallback nicely on translations from pt_PT to pt if not
|
||||||
# available, etc.
|
# available, etc.
|
||||||
this_gettext = gettext.translation(
|
if SETUP_GETTEXTS.has_key(locale):
|
||||||
'mediagoblin', TRANSLATIONS_PATH, [locale], fallback=True)
|
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(
|
mgoblin_globals.setup_globals(
|
||||||
translations=this_gettext)
|
translations=this_gettext)
|
||||||
|
@ -14,16 +14,23 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# 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
|
from mediagoblin.db.util import DESCENDING
|
||||||
|
|
||||||
def root_view(request):
|
def root_view(request):
|
||||||
media_entries = request.db.MediaEntry.find(
|
media_entries = request.db.MediaEntry.find(
|
||||||
{u'state': u'processed'}).sort('created', DESCENDING)
|
{u'state': u'processed'}).sort('created', DESCENDING)
|
||||||
|
|
||||||
template = request.template_env.get_template(
|
return render_to_response(
|
||||||
'mediagoblin/root.html')
|
request, 'mediagoblin/root.html',
|
||||||
return Response(
|
{'media_entries': media_entries})
|
||||||
template.render(
|
|
||||||
{'request': request,
|
|
||||||
'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