Merge remote-tracking branch 'refs/remotes/tilly-q/OPW-Moderation-Update'
authorChristopher Allan Webber <cwebber@dustycloud.org>
Mon, 7 Oct 2013 20:48:33 +0000 (15:48 -0500)
committerChristopher Allan Webber <cwebber@dustycloud.org>
Mon, 7 Oct 2013 20:48:33 +0000 (15:48 -0500)
Conflicts:
mediagoblin/templates/mediagoblin/user_pages/user.html
mediagoblin/tests/test_auth.py
mediagoblin/tests/test_submission.py

15 files changed:
1  2 
mediagoblin/auth/tools.py
mediagoblin/auth/views.py
mediagoblin/config_spec.ini
mediagoblin/db/migrations.py
mediagoblin/db/models.py
mediagoblin/edit/views.py
mediagoblin/submit/views.py
mediagoblin/templates/mediagoblin/user_pages/user.html
mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html
mediagoblin/tests/test_auth.py
mediagoblin/tests/test_edit.py
mediagoblin/tests/test_openid.py
mediagoblin/tests/test_persona.py
mediagoblin/tests/test_submission.py
mediagoblin/user_pages/views.py

Simple merge
Simple merge
Simple merge
index 423508f6bfa5afef70fad03ba2822d593203f8d3,7011d842b28f961b05796b10e3d1f15d12fef1c8..5c2a23aabafbde772ddef5361eb91b06fc3e4ccd
@@@ -26,9 -26,10 +26,10 @@@ from sqlalchemy.sql import and
  from migrate.changeset.constraint import UniqueConstraint
  
  
 -from mediagoblin.db.extratypes import JSONEncoded
 +from mediagoblin.db.extratypes import JSONEncoded, MutationDict
  from mediagoblin.db.migration_tools import RegisterMigration, inspect_table
- from mediagoblin.db.models import MediaEntry, Collection, User, MediaComment
+ from mediagoblin.db.models import (MediaEntry, Collection, MediaComment, User, 
+         Privilege)
  
  MIGRATIONS = {}
  
@@@ -469,40 -470,203 +470,235 @@@ def wants_notifications(db)
      """Add a wants_notifications field to User model"""
      metadata = MetaData(bind=db.bind)
      user_table = inspect_table(metadata, "core__users")
      col = Column('wants_notifications', Boolean, default=True)
      col.create(user_table)
+     db.commit()
+ class ReportBase_v0(declarative_base()):
+     __tablename__ = 'core__reports'
+     id = Column(Integer, primary_key=True)
+     reporter_id = Column(Integer, ForeignKey(User.id), nullable=False)
+     report_content = Column(UnicodeText)
+     reported_user_id = Column(Integer, ForeignKey(User.id), nullable=False)
+     created = Column(DateTime, nullable=False, default=datetime.datetime.now)
+     discriminator = Column('type', Unicode(50))
+     resolver_id = Column(Integer, ForeignKey(User.id))
+     resolved = Column(DateTime)
+     result = Column(UnicodeText)
+     __mapper_args__ = {'polymorphic_on': discriminator}
+ class CommentReport_v0(ReportBase_v0):
+     __tablename__ = 'core__reports_on_comments'
+     __mapper_args__ = {'polymorphic_identity': 'comment_report'}
+     id = Column('id',Integer, ForeignKey('core__reports.id'),
+                                                 primary_key=True)
+     comment_id = Column(Integer, ForeignKey(MediaComment.id), nullable=True)
+ class MediaReport_v0(ReportBase_v0):
+     __tablename__ = 'core__reports_on_media'
+     __mapper_args__ = {'polymorphic_identity': 'media_report'}
+     id = Column('id',Integer, ForeignKey('core__reports.id'), primary_key=True)
+     media_entry_id = Column(Integer, ForeignKey(MediaEntry.id), nullable=True)
+ class UserBan_v0(declarative_base()):
+     __tablename__ = 'core__user_bans'
+     user_id = Column(Integer, ForeignKey(User.id), nullable=False,
+                                          primary_key=True)
+     expiration_date = Column(Date)
+     reason = Column(UnicodeText, nullable=False)
+ class Privilege_v0(declarative_base()):
+     __tablename__ = 'core__privileges'
+     id = Column(Integer, nullable=False, primary_key=True, unique=True)
+     privilege_name = Column(Unicode, nullable=False, unique=True)
+ class PrivilegeUserAssociation_v0(declarative_base()):
+     __tablename__ = 'core__privileges_users'
+     privilege_id = Column(
+         'core__privilege_id',
+         Integer,
+         ForeignKey(User.id),
+         primary_key=True)
+     user_id = Column(
+         'core__user_id',
+         Integer,
+         ForeignKey(Privilege.id),
+         primary_key=True)
+ PRIVILEGE_FOUNDATIONS_v0 = [{'privilege_name':u'admin'},
+                                               {'privilege_name':u'moderator'},
+                                               {'privilege_name':u'uploader'},
+                                               {'privilege_name':u'reporter'},
+                                               {'privilege_name':u'commenter'},
+                                               {'privilege_name':u'active'}]
+ class User_vR1(declarative_base()):
+     __tablename__ = 'rename__users'
+     id = Column(Integer, primary_key=True)
+     username = Column(Unicode, nullable=False, unique=True)
+     email = Column(Unicode, nullable=False)
+     pw_hash = Column(Unicode)
+     created = Column(DateTime, nullable=False, default=datetime.datetime.now)
+     wants_comment_notification = Column(Boolean, default=True)
+     wants_notifications = Column(Boolean, default=True)
+     license_preference = Column(Unicode)
+     url = Column(Unicode)
+     bio = Column(UnicodeText)  # ??
+ @RegisterMigration(18, MIGRATIONS)
+ def create_moderation_tables(db):
+     # First, we will create the new tables in the database.
+     #--------------------------------------------------------------------------
+     ReportBase_v0.__table__.create(db.bind)
+     CommentReport_v0.__table__.create(db.bind)
+     MediaReport_v0.__table__.create(db.bind)
+     UserBan_v0.__table__.create(db.bind)
+     Privilege_v0.__table__.create(db.bind)
+     PrivilegeUserAssociation_v0.__table__.create(db.bind)
+     db.commit()
+     # Then initialize the tables that we will later use
+     #--------------------------------------------------------------------------
+     metadata = MetaData(bind=db.bind)
+     privileges_table= inspect_table(metadata, "core__privileges")
+     user_table = inspect_table(metadata, 'core__users')
+     user_privilege_assoc = inspect_table(
+         metadata, 'core__privileges_users')
+     # This section initializes the default Privilege foundations, that
+     # would be created through the FOUNDATIONS system in a new instance
+     #--------------------------------------------------------------------------
+     for parameters in PRIVILEGE_FOUNDATIONS_v0:
+         db.execute(privileges_table.insert().values(**parameters))
+     db.commit()
+     # This next section takes the information from the old is_admin and status
+     # columns and converts those to the new privilege system
+     #--------------------------------------------------------------------------
+     admin_users_ids, active_users_ids, inactive_users_ids = (
+         db.execute(
+             user_table.select().where(
+                 user_table.c.is_admin==1)).fetchall(),
+         db.execute(
+             user_table.select().where(
+                 user_table.c.is_admin==0).where(
+                 user_table.c.status==u"active")).fetchall(),
+         db.execute(
+             user_table.select().where(
+                 user_table.c.is_admin==0).where(
+                 user_table.c.status!=u"active")).fetchall())
+     # Get the ids for each of the privileges so we can reference them ~~~~~~~~~
+     (admin_privilege_id, uploader_privilege_id,
+      reporter_privilege_id, commenter_privilege_id,
+      active_privilege_id) = [
+         db.execute(privileges_table.select().where(
+             privileges_table.c.privilege_name==privilege_name)).first()['id']
+         for privilege_name in
+             [u"admin",u"uploader",u"reporter",u"commenter",u"active"]
+     ]
+     # Give each user the appopriate privileges depending whether they are an
+     # admin, an active user or an inactivated user ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+     for admin_user in admin_users_ids:
+         admin_user_id = admin_user['id']
+         for privilege_id in [admin_privilege_id, uploader_privilege_id, reporter_privilege_id, commenter_privilege_id, active_privilege_id]:
+             db.execute(user_privilege_assoc.insert().values(
+                 core__privilege_id=admin_user_id,
+                 core__user_id=privilege_id))
+     for active_user in active_users_ids:
+         active_user_id = active_user['id']
+         for privilege_id in [uploader_privilege_id, reporter_privilege_id, commenter_privilege_id, active_privilege_id]:
+             db.execute(user_privilege_assoc.insert().values(
+                 core__privilege_id=active_user_id,
+                 core__user_id=privilege_id))
+     for inactive_user in inactive_users_ids:
+         inactive_user_id = inactive_user['id']
+         for privilege_id in [uploader_privilege_id, reporter_privilege_id, commenter_privilege_id]:
+             db.execute(user_privilege_assoc.insert().values(
+                 core__privilege_id=inactive_user_id,
+                 core__user_id=privilege_id))
+     db.commit()
+     # And then, once the information is taken from the is_admin & status columns
+     # we drop all of the vestigial columns from the User table.
+     #--------------------------------------------------------------------------
+     if db.bind.url.drivername == 'sqlite':
+         # SQLite has some issues that make it *impossible* to drop boolean
+         # columns. So, the following code is a very hacky workaround which
+         # makes it possible. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+         User_vR1.__table__.create(db.bind)
+         db.commit()
+         new_user_table = inspect_table(metadata, 'rename__users')
+         for row in db.execute(user_table.select()):
+             db.execute(new_user_table.insert().values(
+                 username=row.username,
+                 email=row.email,
+                 pw_hash=row.pw_hash,
+                 created=row.created,
+                 wants_comment_notification=row.wants_comment_notification,
+                 wants_notifications=row.wants_notifications,
+                 license_preference=row.license_preference,
+                 url=row.url,
+                 bio=row.bio))
+         db.commit()
+         user_table.drop()
+         db.commit()
+         new_user_table.rename("core__users")
+     else:
+         # If the db is not SQLite, this process is much simpler ~~~~~~~~~~~~~~~
+         status = user_table.columns['status']
+         email_verified = user_table.columns['email_verified']
+         is_admin = user_table.columns['is_admin']
+         status.drop()
+         email_verified.drop()
+         is_admin.drop()
  
      db.commit()
 +
 +
 +@RegisterMigration(16, MIGRATIONS)
 +def upload_limits(db):
 +    """Add user upload limit columns"""
 +    metadata = MetaData(bind=db.bind)
 +
 +    user_table = inspect_table(metadata, 'core__users')
 +    media_entry_table = inspect_table(metadata, 'core__media_entries')
 +
 +    col = Column('uploaded', Integer, default=0)
 +    col.create(user_table)
 +
 +    col = Column('upload_limit', Integer)
 +    col.create(user_table)
 +
 +    col = Column('file_size', Integer, default=0)
 +    col.create(media_entry_table)
 +
 +    db.commit()
 +
 +
 +@RegisterMigration(17, MIGRATIONS)
 +def add_file_metadata(db):
 +    """Add file_metadata to MediaFile"""
 +    metadata = MetaData(bind=db.bind)
 +    media_file_table = inspect_table(metadata, "core__mediafiles")
 +
 +    col = Column('file_metadata', MutationDict.as_mutable(JSONEncoded))
 +    col.create(media_file_table)
 +
 +    db.commit()
index 68a2faa030788517f01d92446604f4a9297591be,5173be9ed5ee83f96a1da1508eaf01ce4306d972..1514a3aa680d8b46dfcabcb514622b8ba6789e26
@@@ -72,11 -69,8 +70,10 @@@ class User(Base, UserMixin)
      wants_comment_notification = Column(Boolean, default=True)
      wants_notifications = Column(Boolean, default=True)
      license_preference = Column(Unicode)
-     is_admin = Column(Boolean, default=False, nullable=False)
      url = Column(Unicode)
      bio = Column(UnicodeText)  # ??
 +    uploaded = Column(Integer, default=0)
 +    upload_limit = Column(Integer)
  
      ## TODO
      # plugin data would be in a separate model
Simple merge
Simple merge
index 50ad766a018911894a41bb408384ed5fe7d6a54e,ab616ea8c16d1426d98ecedcd84b39de9cd899da..37983400543f09108905abe00bda965f0f6dd009
  
  
  {% block mediagoblin_content -%}
 -  {# If no user... #}
 -  {% if not user %}
 -    <p>{% trans %}Sorry, no such user found.{% endtrans %}</p>
 -
 -  {# User exists, but needs verification #}
 -  {% elif not user.has_privilege('active') %}
 -    {% if user == request.user %}
 -      {# this should only be visible when you are this user #}
 -      <div class="form_box">
 -        <h1>{% trans %}Email verification needed{% endtrans %}</h1>
 +  <h1>
 +    {%- trans username=user.username %}{{ username }}'s profile{% endtrans -%}
 +  </h1>
  
 +  {% if not user.url and not user.bio %}
 +    {% if request.user and (request.user.id == user.id) %}
 +      <div class="profile_sidebar empty_space">
          <p>
 -          {% trans -%}
 -            Almost done! Your account still needs to be activated.
 -          {%- endtrans %}
 -        </p>
 -        <p>
 -          {% trans -%}
 -            An email should arrive in a few moments with instructions on how to do so.
 -          {%- endtrans %}
 +          {% trans %}Here's a spot to tell others about yourself.{% endtrans %}
          </p>
 -        <p>{% trans %}In case it doesn't:{% endtrans %}</p>
 -  
 -        <a href="{{ request.urlgen('mediagoblin.auth.resend_verification') }}"
 -           class="button_action_highlight">{% trans %}Resend verification email{% endtrans %}</a>
 -      </div>
 +        <a href="{{ request.urlgen('mediagoblin.edit.profile',
 +                 user=user.username) }}" class="button_action">
 +          {%- trans %}Edit profile{% endtrans -%}
 +        </a>
      {% else %}
 -      {# if the user is not you, but still needs to verify their email #}
 -      <div class="form_box">
 -        <h1>{% trans %}Email verification needed{% endtrans %}</h1>
 -
 +      <div class="profile_sidebar empty_space">
          <p>
            {% trans -%}
 -            Someone has registered an account with this username, but it still has to be activated.
 -          {%- endtrans %}
 -        </p>
 -  
 -        <p>
 -          {% trans login_url=request.urlgen('mediagoblin.auth.login') -%}
 -            If you are that person but you've lost your verification email, you can <a href="{{ login_url }}">log in</a> and resend it.
 +            This user hasn't filled in their profile (yet).
            {%- endtrans %}
          </p>
 -      </div>
      {% endif %}
 -
 -  {# Active(?) (or at least verified at some point) user, horray! #}
    {% else %}
 -    <h1>
 -      {%- trans username=user.username %}{{ username }}'s profile{% endtrans -%}
 -    </h1>
 -
 -    {% if not user.url and not user.bio %}
 -      {% if request.user and (request.user.id == user.id) %}
 -        <div class="profile_sidebar empty_space">
 -          <p>
 -            {% trans %}Here's a spot to tell others about yourself.{% endtrans %}
 -          </p>
 -          <a href="{{ request.urlgen('mediagoblin.edit.profile',
 -                   user=user.username) }}" class="button_action">
 -            {%- trans %}Edit profile{% endtrans -%}
 -          </a>
 -      {% else %}
 -        <div class="profile_sidebar empty_space">
 -          <p>
 -            {% trans -%}
 -              This user hasn't filled in their profile (yet).
 -            {%- endtrans %}
 -          </p>
 +    <div class="profile_sidebar">
 +      {% include "mediagoblin/utils/profile.html" %}
 +      {% if request.user and
-             (request.user.id == user.id or request.user.is_admin) %}
++            (request.user.id == user.id or request.user.has_privilege('admin')) %}
 +        <a href="{{ request.urlgen('mediagoblin.edit.profile',
 +                 user=user.username) }}">
 +          {%- trans %}Edit profile{% endtrans -%}
 +        </a>
        {% endif %}
 -    {% else %}
 -      <div class="profile_sidebar">
 -        {% include "mediagoblin/utils/profile.html" %}
 -        {% if request.user and
 -              (request.user.id == user.id or request.user.has_privilege('admin')) %}
 -          <a href="{{ request.urlgen('mediagoblin.edit.profile',
 -                   user=user.username) }}">
 -            {%- trans %}Edit profile{% endtrans -%}
 -          </a>
 -        {% endif %}
 -    {% endif %}
 +  {% endif %}
 +    <p>
 +      <a href="{{ request.urlgen('mediagoblin.user_pages.collection_list',
 +                                         user=user.username) }}">
 +        {%- trans %}Browse collections{% endtrans -%}
 +      </a>
 +    </p>
 +  </div>
 +
 +  {% if media_entries.count() %}
 +    <div class="profile_showcase">
 +      {{ object_gallery(request, media_entries, pagination,
 +                        pagination_base_url=user_gallery_url, col_number=3) }}
 +      {% include "mediagoblin/utils/object_gallery.html" %}
 +      <div class="clear"></div>
        <p>
 -        <a href="{{ request.urlgen('mediagoblin.user_pages.collection_list',
 -                                           user=user.username) }}">
 -          {%- trans %}Browse collections{% endtrans -%}
 +        <a href="{{ user_gallery_url }}">
 +          {% trans username=user.username -%}
 +            View all of {{ username }}'s media{% endtrans -%}
          </a>
        </p>
 +      {% set feed_url = request.urlgen(
 +                'mediagoblin.user_pages.atom_feed',
 +                user=user.username) %}
 +      {% include "mediagoblin/utils/feed_link.html" %}
      </div>
 -
 -    {% if media_entries.count() %}
 -      <div class="profile_showcase">
 -        {{ object_gallery(request, media_entries, pagination,
 -                          pagination_base_url=user_gallery_url, col_number=3) }}
 -        {% include "mediagoblin/utils/object_gallery.html" %}
 -        <div class="clear"></div>
 +  {% else %}
 +    {% if request.user and (request.user.id == user.id) %}
 +      <div class="profile_showcase empty_space">
          <p>
 -          <a href="{{ user_gallery_url }}">
 -            {% trans username=user.username -%}
 -              View all of {{ username }}'s media{% endtrans -%}
 -          </a>
 +          {% trans -%}
 +          This is where your media will appear, but you don't seem to have added anything yet.
 +          {%- endtrans %}
          </p>
 -        {% set feed_url = request.urlgen(
 -                  'mediagoblin.user_pages.atom_feed',
 -                  user=user.username) %}
 -        {% include "mediagoblin/utils/feed_link.html" %}
 +        <a class="button_action"
 +           href="{{ request.urlgen('mediagoblin.submit.start') }}">
 +          {%- trans %}Add media{% endtrans -%}
 +        </a>
        </div>
      {% else %}
 -      {% if request.user and (request.user.id == user.id) %}
 -        <div class="profile_showcase empty_space">
 -          <p>
 -            {% trans -%}
 -            This is where your media will appear, but you don't seem to have added anything yet.
 -            {%- endtrans %}
 -          </p>
 -          <a class="button_action"
 -             href="{{ request.urlgen('mediagoblin.submit.start') }}">
 -            {%- trans %}Add media{% endtrans -%}
 -          </a>
 -        </div>
 -      {% else %}
 -        <div class="profile_showcase empty_space">
 -          <p>
 -            {% trans -%}
 -            There doesn't seem to be any media here yet...
 -            {%- endtrans %}
 -          </p>
 -        </div>
 -      {% endif %}
 +      <div class="profile_showcase empty_space">
 +        <p>
 +          {% trans -%}
 +          There doesn't seem to be any media here yet...
 +          {%- endtrans %}
 +        </p>
 +      </div>
      {% endif %}
 -    <div class="clear"></div>
    {% endif %}
 +  <div class="clear"></div>
  {% endblock %}
index b3066665bdf9a9e8c1bfff3884eb4971fc369646,0000000000000000000000000000000000000000..d924198bc5d74a4f92bc894820a6b2ed60326fcc
mode 100644,000000..100644
--- /dev/null
@@@ -1,83 -1,0 +1,83 @@@
-   {% if user.status == "needs_email_verification" %}
 +{#
 +# 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/>.
 +
 +# This is the main user homepage for non-active users that still need
 +# registration etc.
 +#}
 +{% extends "mediagoblin/base.html" %}
 +
 +{% block title %}
 +  {%- if user -%}
 +    {%- trans username=user.username -%}
 +      {{ username }}'s profile
 +    {%- endtrans %} &mdash; {{ super() }}
 +  {%- else -%}
 +    {{ super() }}
 +  {%- endif -%}
 +{% endblock %}
 +
 +
 +{% block mediagoblin_content -%}
 +  {# User exists, but needs verification #}
++  {% if not user.has_privilege('active') %}
 +    {% if user == request.user %}
 +      {# this should only be visible when you are this user #}
 +      <div class="form_box">
 +        <h1>{% trans %}Email verification needed{% endtrans %}</h1>
 +
 +        <p>
 +          {% trans -%}
 +            Almost done! Your account still needs to be activated.
 +          {%- endtrans %}
 +        </p>
 +        <p>
 +          {% trans -%}
 +            An email should arrive in a few moments with instructions on how to do so.
 +          {%- endtrans %}
 +        </p>
 +        <p>{% trans %}In case it doesn't:{% endtrans %}</p>
 +  
 +        <a href="{{ request.urlgen('mediagoblin.auth.resend_verification') }}"
 +           class="button_action_highlight">{% trans %}Resend verification email{% endtrans %}</a>
 +      </div>
 +    {% else %}
 +      {# if the user is not you, but still needs to verify their email #}
 +      <div class="form_box">
 +        <h1>{% trans %}Email verification needed{% endtrans %}</h1>
 +
 +        <p>
 +          {% trans -%}
 +            Someone has registered an account with this username, but it still has to be activated.
 +          {%- endtrans %}
 +        </p>
 +        <p>
 +          {% trans login_url=request.urlgen('mediagoblin.auth.login') -%}
 +            If you are that person but you've lost your verification email, you can <a href="{{ login_url }}">log in</a> and resend it.
 +          {%- endtrans %}
 +        </p>
 +      </div>
 +    {% endif %}
 +
 +  {# Active(?) (or at least verified at some point) user, horray! #}
 +  {% else %}
 +    <h1>
 +      {%- trans username=user.username %}{{ username }}{% endtrans -%}
 +    </h1>
 +    <p>{{ username }} is not active.</p>
 +    <div class="clear"></div>
 +  {% endif %}
 +{% endblock %}
index d2e01e44a553219fc71db9fccd064a7456ff34a7,63c126820a3406d97f29f2fff103215b9cbf12be..1bbc3d01550f597779bbd492f60c8dbb472897ed
@@@ -90,19 -89,23 +90,23 @@@ def test_register_views(test_app)
      response.follow()
  
      ## Did we redirect to the proper page?  Use the right template?
-     assert urlparse.urlsplit(response.location)[2] == '/u/happygirl/'
+     assert urlparse.urlsplit(response.location)[2] == '/u/angrygirl/'
 -    assert 'mediagoblin/user_pages/user.html' in template.TEMPLATE_TEST_CONTEXT
 +    assert 'mediagoblin/user_pages/user_nonactive.html' in template.TEMPLATE_TEST_CONTEXT
  
      ## Make sure user is in place
      new_user = mg_globals.database.User.query.filter_by(
-         username=u'happygirl').first()
+         username=u'angrygirl').first()
      assert new_user
-     assert new_user.status == u'needs_email_verification'
-     assert new_user.email_verified == False
  
+     ## Make sure that the proper privileges are granted on registration
+     assert new_user.has_privilege(u'commenter')
+     assert new_user.has_privilege(u'uploader')
+     assert new_user.has_privilege(u'reporter')
+     assert not new_user.has_privilege(u'active')
      ## Make sure user is logged in
      request = template.TEMPLATE_TEST_CONTEXT[
 -        'mediagoblin/user_pages/user.html']['request']
 +        'mediagoblin/user_pages/user_nonactive.html']['request']
      assert request.session['user_id'] == unicode(new_user.id)
  
      ## Make sure we get email confirmation, and try verifying
      ## Make sure link to change password is sent by email
      assert len(mail.EMAIL_TEST_INBOX) == 1
      message = mail.EMAIL_TEST_INBOX.pop()
-     assert message['To'] == 'happygrrl@example.org'
+     assert message['To'] == 'angrygrrl@example.org'
      email_context = template.TEMPLATE_TEST_CONTEXT[
 -        'mediagoblin/auth/fp_verification_email.txt']
 +        'mediagoblin/plugins/basic_auth/fp_verification_email.txt']
      #TODO - change the name of verification_url to something forgot-password-ish
      assert email_context['verification_url'] in message.get_payload(decode=True)
  
Simple merge
Simple merge
Simple merge
index 7f4e808614ff9dff21c82c950788515911a011af,14766c506cc7d881fa1c952982adcfb6948fd1f1..5d42c5a5bafae79b945f587b6bb158232ffd13e6
@@@ -148,78 -128,9 +158,78 @@@ class TestSubmission
          response, context = self.do_post({'title': u'Normal upload 3 (pdf)'},
                                           do_follow=True,
                                           **self.upload_data(GOOD_PDF))
-         self.check_url(response, '/u/{0}/'.format(self.test_user.username))
+         self.check_url(response, '/u/{0}/'.format(self.our_user().username))
          assert 'mediagoblin/user_pages/user.html' in context
  
 +    def test_default_upload_limits(self):
 +        self.user_upload_limits(uploaded=500)
 +
 +        # User uploaded should be 500
 +        assert self.test_user.uploaded == 500
 +
 +        response, context = self.do_post({'title': u'Normal upload 4'},
 +                                         do_follow=True,
 +                                         **self.upload_data(GOOD_JPG))
 +        self.check_url(response, '/u/{0}/'.format(self.test_user.username))
 +        assert 'mediagoblin/user_pages/user.html' in context
 +
 +        # Reload user
 +        self.test_user = User.query.filter_by(
 +            username=self.test_user.username
 +        ).first()
 +
 +        # Shouldn't have uploaded
 +        assert self.test_user.uploaded == 500
 +
 +    def test_user_upload_limit(self):
 +        self.user_upload_limits(uploaded=25, upload_limit=25)
 +
 +        # User uploaded should be 25
 +        assert self.test_user.uploaded == 25
 +
 +        response, context = self.do_post({'title': u'Normal upload 5'},
 +                                         do_follow=True,
 +                                         **self.upload_data(GOOD_JPG))
 +        self.check_url(response, '/u/{0}/'.format(self.test_user.username))
 +        assert 'mediagoblin/user_pages/user.html' in context
 +
 +        # Reload user
 +        self.test_user = User.query.filter_by(
 +            username=self.test_user.username
 +        ).first()
 +
 +        # Shouldn't have uploaded
 +        assert self.test_user.uploaded == 25
 +
 +    def test_user_under_limit(self):
 +        self.user_upload_limits(uploaded=499)
 +
 +        # User uploaded should be 499
 +        assert self.test_user.uploaded == 499
 +
 +        response, context = self.do_post({'title': u'Normal upload 6'},
 +                                         do_follow=False,
 +                                         **self.upload_data(MED_PNG))
 +        form = context['mediagoblin/submit/start.html']['submit_form']
 +        assert form.file.errors == [u'Sorry, uploading this file will put you'
 +                                    ' over your upload limit.']
 +
 +        # Reload user
 +        self.test_user = User.query.filter_by(
 +            username=self.test_user.username
 +        ).first()
 +
 +        # Shouldn't have uploaded
 +        assert self.test_user.uploaded == 499
 +
 +    def test_big_file(self):
 +        response, context = self.do_post({'title': u'Normal upload 7'},
 +                                         do_follow=False,
 +                                         **self.upload_data(BIG_PNG))
 +
 +        form = context['mediagoblin/submit/start.html']['submit_form']
 +        assert form.file.errors == [u'Sorry, the file size is too big.']
 +
      def check_media(self, request, find_data, count=None):
          media = MediaEntry.query.filter_by(**find_data)
          if count is not None:
index 974cb3c6b864641341d535aebf56312bd374ec36,020fa6a80fe470504e9b22a972a09c256341874d..73823e4d3992855021f84cd0e8397dd07d28d756
@@@ -50,10 -53,13 +53,10 @@@ def user_home(request, page)
      user = User.query.filter_by(username=request.matchdict['user']).first()
      if not user:
          return render_404(request)
-     elif user.status != u'active':
+     elif not user.has_privilege(u'active'):
          return render_to_response(
              request,
 -            'mediagoblin/user_pages/user.html',
 +            'mediagoblin/user_pages/user_nonactive.html',
              {'user': user})
  
      cursor = MediaEntry.query.\