Pull changes and resolve merge conflict.

This commit is contained in:
Aditi 2013-08-28 23:28:09 +05:30
commit 922599990d
85 changed files with 20906 additions and 6591 deletions

View File

@ -4,5 +4,5 @@ source_file = mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po
source_lang = en
[main]
host = https://www.transifex.net
host = https://transifex.com

View File

@ -203,18 +203,20 @@ Clone the MediaGoblin repository and set up the git submodules::
cd mediagoblin
git submodule init && git submodule update
Set up the in-package virtualenv via make::
./bootstrap.sh && ./configure && make
And set up the in-package virtualenv::
(virtualenv --system-site-packages . || virtualenv .) && ./bin/python setup.py develop
.. note::
Prefer not to use make, or want to use the "old way" of installing
MediaGoblin (maybe you know how to use virtualenv and python
packaging)? You still can! All that the above make script is doing
is installing an in-package virtualenv and running
We presently have an experimental make-style deployment system. if
you'd like to try it, instead of the above command, you can run::
./bin/python setup.py develop
./bootstrap.sh && ./configure && make
This also includes a number of nice features, such as keeping your
viratualenv up to date by simply running `make update`.
.. ::

View File

@ -22,6 +22,67 @@ If you're upgrading from a previous release, please read it
carefully, or at least skim over it.
0.5.0
=====
**Do this to upgrade**
1. Make sure to run
``./bin/python setup.py develop --upgrade && ./bin/gmg dbupdate``
after upgrading.
.. mention something about new, experimental configure && make support
2. Note that a couple of things have changed with ``mediagoblin.ini``. First
we have a new Authentication System. You need to add
``[[mediagoblin.plugins.basic_auth]]`` under the ``[plugins]`` section of
your config file. Second, media types are now plugins, so you need to add
each media type under the ``[plugins]`` section of your config file.
3. We have made a script to transition your ``mediagoblin_local.ini`` file for
you. This script can be found at
.. add a link to the script
If you run into problems, don't hesitate to
`contact us <http://mediagoblin.org/pages/join.html>`_
(IRC is often best).
**New features**
* As mentioned above, we now have a plugable Authentication system. You can
use any combination of the multiple authentication systems
(:ref:`basic_auth-chapter`, :ref:`persona-chapter`, :ref:`openid-chapter`)
or write your own!
* Media types are now plugins! This means that new media types will
be able to do new, fancy things they couldn't in the future.
* We now have notification support! This allows you to subscribe to media
comments and to be notified when someone comments on your media.
* New reprocessing framework! You can now reprocess failed uploads, and
send already processed media back to processing to re-transcode or resize
media.
* Comment preview!
* Users now have the ability to change their email associated with their
account.
* New oauth code as we move closer to federation support.
* Experimental pyconfigure support for GNU-style configue and makefile
deployment.
* Database foundations! You can now pre-populate the database models.
* Way faster unit test run-time via in-memory database.
* All mongokit stuff has been cleaned up.
* Fixes for non-ascii filenames.
* The option to stay logged in.
* Mediagoblin has been upgraded to use the latest `celery <http://celeryproject.org/>`_
version.
* You can now add jinja2 extensions to your config file to use in custom
templates.
* Fixed video permission issues.
* Mediagoblin docs are now hosted with multiple versions.
* We removed redundent tooltips from the STL media display.
* We are now using itsdangerous for verification tokens.
0.4.1
=====

View File

@ -61,10 +61,6 @@ class EditProfileForm(wtforms.Form):
class EditAccountForm(wtforms.Form):
new_email = wtforms.TextField(
_('New email address'),
[wtforms.validators.Optional(),
normalize_user_or_email_field(allow_user=False)])
wants_comment_notification = wtforms.BooleanField(
description=_("Email me when others comment on my media"))
wants_notifications = wtforms.BooleanField(
@ -113,3 +109,15 @@ class ChangePassForm(wtforms.Form):
[wtforms.validators.Required(),
wtforms.validators.Length(min=6, max=30)],
id="password")
class ChangeEmailForm(wtforms.Form):
new_email = wtforms.TextField(
_('New email address'),
[wtforms.validators.Required(),
normalize_user_or_email_field(allow_user=False)])
password = wtforms.PasswordField(
_('Password'),
[wtforms.validators.Required()],
description=_(
"Enter your password to prove you own this account."))

View File

@ -28,3 +28,5 @@ add_route('mediagoblin.edit.pass', '/edit/password/',
'mediagoblin.edit.views:change_pass')
add_route('mediagoblin.edit.verify_email', '/edit/verify_email/',
'mediagoblin.edit.views:verify_email')
add_route('mediagoblin.edit.email', '/edit/email/',
'mediagoblin.edit.views:change_email')

View File

@ -427,30 +427,52 @@ def verify_email(request):
user=user.username)
def _update_email(request, form, user):
new_email = form.new_email.data
users_with_email = User.query.filter_by(
email=new_email).count()
def change_email(request):
""" View to change the user's email """
form = forms.ChangeEmailForm(request.form)
user = request.user
if users_with_email:
form.new_email.errors.append(
_('Sorry, a user with that email address'
' already exists.'))
# If no password authentication, no need to enter a password
if 'pass_auth' not in request.template_env.globals or not user.pw_hash:
form.__delitem__('password')
elif not users_with_email:
verification_key = get_timed_signer_url(
'mail_verification_token').dumps({
'user': user.id,
'email': new_email})
if request.method == 'POST' and form.validate():
new_email = form.new_email.data
users_with_email = User.query.filter_by(
email=new_email).count()
rendered_email = render_template(
request, 'mediagoblin/edit/verification.txt',
{'username': user.username,
'verification_url': EMAIL_VERIFICATION_TEMPLATE.format(
uri=request.urlgen('mediagoblin.edit.verify_email',
qualified=True),
verification_key=verification_key)})
if users_with_email:
form.new_email.errors.append(
_('Sorry, a user with that email address'
' already exists.'))
email_debug_message(request)
auth_tools.send_verification_email(user, request, new_email,
rendered_email)
if form.password and user.pw_hash and not auth.check_password(
form.password.data, user.pw_hash):
form.password.errors.append(
_('Wrong password'))
if not form.errors:
verification_key = get_timed_signer_url(
'mail_verification_token').dumps({
'user': user.id,
'email': new_email})
rendered_email = render_template(
request, 'mediagoblin/edit/verification.txt',
{'username': user.username,
'verification_url': EMAIL_VERIFICATION_TEMPLATE.format(
uri=request.urlgen('mediagoblin.edit.verify_email',
qualified=True),
verification_key=verification_key)})
email_debug_message(request)
auth_tools.send_verification_email(user, request, new_email,
rendered_email)
return redirect(request, 'mediagoblin.edit.account')
return render_to_response(
request,
'mediagoblin/edit/change_email.html',
{'form': form,
'user': user})

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -17,16 +17,11 @@
from mediagoblin.media_types import MediaManagerBase
from mediagoblin.media_types.ascii.processing import AsciiProcessingManager, \
sniff_handler
from mediagoblin.tools import pluginapi
ACCEPTED_EXTENSIONS = ["txt", "asc", "nfo"]
MEDIA_TYPE = 'mediagoblin.media_types.ascii'
def setup_plugin():
config = pluginapi.get_config(MEDIA_TYPE)
class ASCIIMediaManager(MediaManagerBase):
human_readable = "ASCII"
display_template = "mediagoblin/media_displays/ascii.html"
@ -39,7 +34,6 @@ def get_media_type_and_manager(ext):
hooks = {
'setup': setup_plugin,
'get_media_type_and_manager': get_media_type_and_manager,
('media_manager', MEDIA_TYPE): lambda: ASCIIMediaManager,
('reprocess_manager', MEDIA_TYPE): lambda: AsciiProcessingManager,

View File

@ -19,7 +19,7 @@ import logging
from mediagoblin.media_types import MediaManagerBase
from mediagoblin.media_types.image.processing import sniff_handler, \
ImageProcessingManager
from mediagoblin.tools import pluginapi
_log = logging.getLogger(__name__)
@ -27,11 +27,9 @@ _log = logging.getLogger(__name__)
ACCEPTED_EXTENSIONS = ["jpg", "jpeg", "png", "gif", "tiff"]
MEDIA_TYPE = 'mediagoblin.media_types.image'
def setup_plugin():
config = pluginapi.get_config(MEDIA_TYPE)
class ImageMediaManager(MediaManagerBase):
human_readable = "Image"
display_template = "mediagoblin/media_displays/image.html"
@ -67,7 +65,6 @@ def get_media_type_and_manager(ext):
hooks = {
'setup': setup_plugin,
'get_media_type_and_manager': get_media_type_and_manager,
'sniff_handler': sniff_handler,
('media_manager', MEDIA_TYPE): lambda: ImageMediaManager,

View File

@ -17,16 +17,12 @@
from mediagoblin.media_types import MediaManagerBase
from mediagoblin.media_types.pdf.processing import PdfProcessingManager, \
sniff_handler
from mediagoblin.tools import pluginapi
ACCEPTED_EXTENSIONS = ['pdf']
MEDIA_TYPE = 'mediagoblin.media_types.pdf'
def setup_plugin():
config = pluginapi.get_config(MEDIA_TYPE)
class PDFMediaManager(MediaManagerBase):
human_readable = "PDF"
display_template = "mediagoblin/media_displays/pdf.html"
@ -39,7 +35,6 @@ def get_media_type_and_manager(ext):
hooks = {
'setup': setup_plugin,
'get_media_type_and_manager': get_media_type_and_manager,
'sniff_handler': sniff_handler,
('media_manager', MEDIA_TYPE): lambda: PDFMediaManager,

View File

@ -17,16 +17,12 @@
from mediagoblin.media_types import MediaManagerBase
from mediagoblin.media_types.stl.processing import StlProcessingManager, \
sniff_handler
from mediagoblin.tools import pluginapi
MEDIA_TYPE = 'mediagoblin.media_types.stl'
ACCEPTED_EXTENSIONS = ["obj", "stl"]
def setup_plugin():
config = pluginapi.get_config(MEDIA_TYPE)
class STLMediaManager(MediaManagerBase):
human_readable = "stereo lithographics"
display_template = "mediagoblin/media_displays/stl.html"
@ -38,7 +34,6 @@ def get_media_type_and_manager(ext):
return MEDIA_TYPE, STLMediaManager
hooks = {
'setup': setup_plugin,
'get_media_type_and_manager': get_media_type_and_manager,
'sniff_handler': sniff_handler,
('media_manager', MEDIA_TYPE): lambda: STLMediaManager,

View File

@ -17,17 +17,13 @@
from mediagoblin.media_types import MediaManagerBase
from mediagoblin.media_types.video.processing import VideoProcessingManager, \
sniff_handler
from mediagoblin.tools import pluginapi
MEDIA_TYPE = 'mediagoblin.media_types.video'
ACCEPTED_EXTENSIONS = [
"mp4", "mov", "webm", "avi", "3gp", "3gpp", "mkv", "ogv", "m4v"]
def setup_plugin():
config = pluginapi.get_config(MEDIA_TYPE)
class VideoMediaManager(MediaManagerBase):
human_readable = "Video"
display_template = "mediagoblin/media_displays/video.html"
@ -43,7 +39,6 @@ def get_media_type_and_manager(ext):
return MEDIA_TYPE, VideoMediaManager
hooks = {
'setup': setup_plugin,
'get_media_type_and_manager': get_media_type_and_manager,
'sniff_handler': sniff_handler,
('media_manager', MEDIA_TYPE): lambda: VideoMediaManager,

View File

@ -223,7 +223,7 @@ class CommonVideoProcessor(MediaProcessor):
'{basename}.thumbnail.jpg'))
if not thumb_size:
thumb_size = (mgg.global_config['media:thumb']['max_width'])
thumb_size = (mgg.global_config['media:thumb']['max_width'],)
# We will only use the width so that the correct scale is kept
transcoders.VideoThumbnailerMarkII(

View File

@ -17,9 +17,8 @@
#}
{% block openid_edit_link %}
<p>
<a href="{{ request.urlgen('mediagoblin.plugins.openid.edit') }}">
{% trans %}Edit your OpenID's{% endtrans %}
</a>
</p>
<a href="{{ request.urlgen('mediagoblin.plugins.openid.edit') }}">
{% trans %}OpenID's{% endtrans %}
</a>
&middot;
{% endblock %}

View File

@ -186,6 +186,6 @@ def add(request):
messages.add_message(
request,
messages.SUCCESS,
_('Your Person email address was saved successfully.'))
_('Your Persona email address was saved successfully.'))
return redirect(request, 'mediagoblin.edit.account')

View File

@ -41,7 +41,7 @@
{% trans %}Applications with access to your account can: {% endtrans %}
<ul>
<li>{% trans %}Post new media as you{% endtrans %}</li>
<li>{% trans %}See your information (e.g profile, meida, etc...){% endtrans %}</li>
<li>{% trans %}See your information (e.g profile, media, etc...){% endtrans %}</li>
<li>{% trans %}Change your information{% endtrans %}</li>
</ul>
<br />

View File

@ -0,0 +1,45 @@
{#
# 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 <http://www.gnu.org/licenses/>.
#}
{% extends "mediagoblin/base.html" %}
{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
{% block title -%}
{% trans username=user.username -%}
Changing {{ username }}'s email
{%- endtrans %} &mdash; {{ super() }}
{%- endblock %}
{% block mediagoblin_content %}
<form action="{{ request.urlgen('mediagoblin.edit.email') }}"
method="POST" enctype="multipart/form-data">
<div class="form_box edit_box">
<h1>
{%- trans username=user.username -%}
Changing {{ username }}'s email
{%- endtrans -%}
</h1>
{{ wtforms_util.render_divs(form, True) }}
{{ csrf_token }}
<div class="form_submit_buttons">
<input type="submit" value="{% trans %}Save{% endtrans %}"
class="button_form" />
</div>
</div>
</form>
{% endblock %}

View File

@ -41,14 +41,6 @@
Changing {{ username }}'s account settings
{%- endtrans -%}
</h1>
{% if pass_auth is defined %}
<p>
<a href="{{ request.urlgen('mediagoblin.edit.pass') }}">
{% trans %}Change your password.{% endtrans %}
</a>
</p>
{% endif %}
{% template_hook("edit_link") %}
{{ wtforms_util.render_divs(form, True) }}
<div class="form_submit_buttons">
<input type="submit" value="{% trans %}Save changes{% endtrans %}" class="button_form" />
@ -60,5 +52,16 @@
<a href="{{ request.urlgen('mediagoblin.edit.delete_account') }}">
{%- trans %}Delete my account{% endtrans -%}
</a>
&middot;
{% template_hook("edit_link") %}
<a href="{{ request.urlgen('mediagoblin.edit.email') }}">
{% trans %}Email{% endtrans %}
</a>
{% if pass_auth is defined %}
&middot;
<a href="{{ request.urlgen('mediagoblin.edit.pass') }}">
{% trans %}Password{% endtrans %}
</a>
{% endif %}
</div>
{% endblock %}

View File

@ -147,26 +147,26 @@ class TestUserEdit(object):
# Test email already in db
template.clear_test_template_context()
test_app.post(
'/edit/account/', {
'/edit/email/', {
'new_email': 'chris@example.com',
'password': 'toast'})
# Check form errors
context = template.TEMPLATE_TEST_CONTEXT[
'mediagoblin/edit/edit_account.html']
'mediagoblin/edit/change_email.html']
assert context['form'].new_email.errors == [
u'Sorry, a user with that email address already exists.']
# Test successful email change
template.clear_test_template_context()
res = test_app.post(
'/edit/account/', {
'/edit/email/', {
'new_email': 'new@example.com',
'password': 'toast'})
res.follow()
# Correct redirect?
assert urlparse.urlsplit(res.location)[2] == '/u/chris/'
assert urlparse.urlsplit(res.location)[2] == '/edit/account/'
# Make sure we get email verification and try verifying
assert len(mail.EMAIL_TEST_INBOX) == 1