This was a quick update, I mostly worked on the transition from using the old

User table columns (is_admin, status, email_verified) and making sure that
their functionality is instead completely handled by privileges. I also worked
on the meta pages which I hope to finish soon. I set up migrations to ensure
the default privileges are given to users that should have them. Lastly, I made
it so that banned users can log out.

===============================================================================
    Made Sure the Vestigial Columns of the User Table were not being Used
===============================================================================
--\ mediagoblin/auth/views.py
--\ mediagoblin/db/models.py
--\ mediagoblin/templates/mediagoblin/base.html
--\ mediagoblin/templates/mediagoblin/moderation/user.html
--\ mediagoblin/templates/mediagoblin/user_pages/collection_lis$
--\ mediagoblin/templates/mediagoblin/user_pages/user.html
--\ mediagoblin/tests/test_auth.py
--\ mediagoblin/tests/test_persona.py
--\ mediagoblin/user_pages/views.py

===============================================================================
    Wrote the Migrations to Set up the Default Privileges
===============================================================================
--\ mediagoblin/db/migrations.py
--\ mediagoblin/gmg_commands/users.py

===============================================================================
    Work on the Meta Pages
===============================================================================
--\ mediagoblin/meta/routing.py
--\ mediagoblin/meta/views.py
--\ mediagoblin/static/css/base.css
--\ mediagoblin/templates/mediagoblin/meta/terms_of_service.html

===============================================================================
    Small Changes
===============================================================================
--\ mediagoblin/templates/mediagoblin/base.html
--| Benevolently made it so that banned users can log out

===============================================================================
X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X
===============================================================================
This commit is contained in:
tilly-Q 2013-09-08 18:26:37 -04:00
parent 8e91df8734
commit 25625107b6
15 changed files with 115 additions and 58 deletions

View File

@ -150,9 +150,7 @@ def verify_email(request):
user = User.query.filter_by(id=int(token)).first()
if user and user.email_verified is False:
user.status = u'active'
user.email_verified = True
if user and user.has_privilege(u'active') is False:
user.verification_key = None
user.all_privileges.append(
Privilege.query.filter(
@ -191,7 +189,7 @@ def resend_activation(request):
return redirect(request, 'mediagoblin.auth.login')
if request.user.email_verified:
if request.user.has_privilege(u'active'):
messages.add_message(
request,
messages.ERROR,
@ -256,7 +254,7 @@ def forgot_password(request):
success_message=_("An email has been sent with instructions "
"on how to change your password.")
if user and not(user.email_verified and user.status == 'active'):
if user and not(user.has_privilege(u'active')):
# Don't send reminder because user is inactive or has no verified email
messages.add_message(request,
messages.WARNING,
@ -312,8 +310,8 @@ def verify_forgot_password(request):
return redirect(
request, 'index')
# check if user active and has email verified
if user.email_verified and user.status == 'active':
# check if user active
if user.has_privilege(u'active'):
cp_form = auth_forms.ChangePassForm(formdata_vars)
@ -333,13 +331,13 @@ def verify_forgot_password(request):
'mediagoblin/auth/change_fp.html',
{'cp_form': cp_form,})
if not user.email_verified:
if not user.has_privilege(u'active'):
messages.add_message(
request, messages.ERROR,
_('You need to verify your email before you can reset your'
' password.'))
if not user.status == 'active':
if not user.has_privilege(u'active'):
messages.add_message(
request, messages.ERROR,
_('You are no longer an active user. Please contact the system'

View File

@ -29,7 +29,8 @@ from migrate.changeset.constraint import UniqueConstraint
from mediagoblin.db.extratypes import JSONEncoded
from mediagoblin.db.migration_tools import RegisterMigration, inspect_table
from mediagoblin.db.models import (MediaEntry, Collection, User,
MediaComment, Privilege, ReportBase)
MediaComment, Privilege, ReportBase,
FOUNDATIONS)
MIGRATIONS = {}
@ -531,6 +532,40 @@ def create_moderation_tables(db):
UserBan_v0.__table__.create(db.bind)
Privilege_v0.__table__.create(db.bind)
PrivilegeUserAssociation_v0.__table__.create(db.bind)
db.commit()
for parameters in FOUNDATIONS[Privilege]:
p = Privilege(**parameters)
p.save()
@RegisterMigration(16, MIGRATIONS)
def update_user_privilege_columns(db):
metadata = MetaData(bind=db.bind)
default_privileges = Privilege.query.filter(
Privilege.privilege_name !=u'admin').filter(
Privilege.privilege_name !=u'moderator').filter(
Privilege.privilege_name !=u'active').all()
admin_privilege = Privilege.query.filter(
Privilege.privilege_name ==u'admin').first()
active_privilege = Privilege.query.filter(
Privilege.privilege_name ==u'active').first()
for inactive_user in User.query.filter(
User.status!=u'active').filter(
User.is_admin==False).all():
inactive_user.all_privileges = default_privileges
inactive_user.save()
for user in User.query.filter(
User.status==u'active').filter(
User.is_admin==False).all():
user.all_privileges = default_privileges + [active_privilege]
user.save()
for admin_user in User.query.filter(
User.is_admin==True).all():
admin_user.all_privileges = default_privileges + [
admin_privilege, active_privilege]
admin_user.save()

View File

@ -81,8 +81,8 @@ class User(Base, UserMixin):
return '<{0} #{1} {2} {3} "{4}">'.format(
self.__class__.__name__,
self.id,
'verified' if self.email_verified else 'non-verified',
'admin' if self.is_admin else 'user',
'verified' if self.has_privilege(u'active') else 'non-verified',
'admin' if self.has_privilege(u'admin') else 'user',
self.username)
def delete(self, **kwargs):

View File

@ -53,8 +53,6 @@ def adduser(args):
entry.username = unicode(args.username.lower())
entry.email = unicode(args.email)
entry.pw_hash = auth.gen_password_hash(args.password)
entry.status = u'active'
entry.email_verified = True
default_privileges = [
db.Privilege.query.filter(
db.Privilege.privilege_name==u'commenter').one(),

View File

@ -15,9 +15,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
meta_routes = [
('mediagoblin.meta.code_of_conduct',
'/coc/',
'mediagoblin.meta.views:code_of_conduct'),
('mediagoblin.meta.terms_of_service',
'/tos/',
'mediagoblin.meta.views:terms_of_service'),
('mediagoblin.meta.reports_panel',
'/reports/',
'mediagoblin.meta.views:public_reports_panel'),

View File

@ -17,9 +17,9 @@
from mediagoblin.tools.response import render_to_response
def code_of_conduct(request):
def terms_of_service(request):
return render_to_response(request,
'mediagoblin/meta/code_of_conduct.html',
'mediagoblin/meta/terms_of_service.html',
{})
def public_reports_panel(request):

View File

@ -663,13 +663,15 @@ table td.user_without_privilege {
margin-bottom: 10px;
}
#code_of_conduct_list li {
margin-top:5px;
margin:5px 0 15px 25px;
}
ol.nested_sublist{
.nested_sublist {
margin: 5px 0 10px 25px;
font-size:80%;
}
.nested_sublist li {
margin-bottom: 10px;
}
/* ASCII art and code */

View File

@ -59,7 +59,7 @@
{% block mediagoblin_header_title %}{% endblock %}
<div class="header_right">
{%- if request.user %}
{% if request.user and request.user.status == 'active' and not request.user.is_banned() %}
{% if request.user and request.user.has_privilege('active') and not request.user.is_banned() %}
{% set notification_count = get_notification_count(request.user.id) %}
{% if notification_count %}
@ -68,7 +68,7 @@
{% endif %}
<a href="javascript:;" class="button_action header_dropdown_down">&#9660;</a>
<a href="javascript:;" class="button_action header_dropdown_up">&#9650;</a>
{% elif request.user and request.user.status == "needs_email_verification" %}
{% elif request.user and not request.user.has_privilege('active') %}
{# the following link should only appear when verification is needed #}
<a href="{{ request.urlgen('mediagoblin.user_pages.user_home',
user=request.user.username) }}"
@ -81,6 +81,14 @@
"javascript:;"
{% endif %}
>{% trans %}log out{% endtrans %}</a>
{% elif request.user and request.user.is_banned() %}
<a id="logout" href=
{% if persona is not defined %}
"{{ request.urlgen('mediagoblin.auth.logout') }}"
{% else %}
"javascript:;"
{% endif %}
>{% trans %}log out{% endtrans %}</a>
{% endif %}
{%- elif auth %}
<a href=
@ -95,7 +103,7 @@
{%- endif %}
</div>
<div class="clear"></div>
{% if request.user and request.user.status == 'active' %}
{% if request.user and request.user.has_privilege('active') %}
<div class="header_dropdown">
<p>
<span class="dropdown_title">

View File

@ -1,3 +1,27 @@
{#
# 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" %}
{% block title %}
Terms of Service
{% endblock %}
{% block mediagoblin_content -%}
<h2>The gist</h2>
<h2>Terms of Service</h2>
@ -14,8 +38,8 @@ that may be published from time to time on this Site by Operator (collectively,
Please read this Agreement carefully before accessing or using the Website. By accessing or using any part of the web site, you agree to become bound by the terms and conditions of this agreement. If you do not agree to all the terms and conditions of this agreement, then you may not access the Website or use any services. If these terms and conditions are considered an offer by Operator, acceptance is expressly limited to these terms. The Website is available only to individuals who are at least 13 years old.
<ol>
<li>Your {{ app_config['html_title'] }} Account and Site. If you create a
<ol id="code_of_conduct_list">
<li><strong>Your {{ app_config['html_title'] }} Account and Site.</strong> If you create a
notice stream on the Website, you are responsible for maintaining the
security of your account and notice stream, and you are fully responsible
for all activities that occur under the account and any other actions taken
@ -30,7 +54,7 @@ Please read this Agreement carefully before accessing or using the Website. By a
including any damages of any kind incurred as a result of such acts or
omissions.
</li>
<li>Responsibility of Contributors. If you operate a notice stream, comment
<li><strong>Responsibility of Contributors.</strong> If you operate a notice stream, comment
on a notice stream, post material to the Website, post links on the
Website, or otherwise make (or allow any third party to make) material
available by means of the Website (any such material, “Content”), You are
@ -38,7 +62,7 @@ Please read this Agreement carefully before accessing or using the Website. By a
Content. That is the case regardless of whether the Content in question
constitutes text, graphics, an audio file, or computer software. By making
Content available, you represent and warrant that:
<ul>
<ul class="nested_sublist">
<li>the downloading, copying and use of the Content will not infringe
the proprietary rights, including but not limited to the copyright,
patent, trademark or trade secret rights, of any third party;
@ -102,7 +126,7 @@ Please read this Agreement carefully before accessing or using the Website. By a
(ii) terminate or deny access to and use of the Website to any individual
or entity for any reason, in Operators sole discretion.
</li>
<li>Responsibility of Website Visitors. Operator has not reviewed, and cannot
<li><strong>Responsibility of Website Visitors.</strong> Operator has not reviewed, and cannot
review, all of the material, including computer software, posted to the
Website, and cannot therefore be responsible for that materials content,
use or effects. By operating the Website, Operator does not represent or
@ -121,7 +145,7 @@ Please read this Agreement carefully before accessing or using the Website. By a
visitors of the Website, or from any downloading by those visitors of
content there posted.
</li>
<li>Content Posted on Other Websites. We have not reviewed, and cannot
<li><strong>Content Posted on Other Websites.</strong> We have not reviewed, and cannot
review, all of the material, including computer software, made available
through the websites and webpages to which {{ app_config['html_title'] }}
links, and that link to {{ app_config['html_title'] }}. Operator does not
@ -134,7 +158,7 @@ Please read this Agreement carefully before accessing or using the Website. By a
disclaims any responsibility for any harm resulting from your use of
external websites and webpages.
</li>
<li>Copyright Infringement and DMCA Policy. As Operator asks others to
<li><strong>Copyright Infringement and DMCA Policy.</strong> As Operator asks others to
respect its intellectual property rights, it respects the intellectual
property rights of others. If you believe that material located on or
linked to by {{ app_config['html_title'] }} violates your copyright, you
@ -148,7 +172,7 @@ Please read this Agreement carefully before accessing or using the Website. By a
the Website. In the case of such termination, Operator will have no
obligation to provide a refund of any amounts previously paid to Operator.
</li>
<li>Intellectual Property. This Agreement does not transfer from Operator to
<li><strong>Intellectual Property.</strong> This Agreement does not transfer from Operator to
you any Operator or third party intellectual property, and all right,
title and interest in and to such property will remain (as between the
parties) solely with Operator. {{ app_config['html_title'] }}, the
@ -161,7 +185,7 @@ Please read this Agreement carefully before accessing or using the Website. By a
Website grants you no right or license to reproduce or otherwise use any
Operator or third-party trademarks.
</li>
<li>Changes. Operator reserves the right, at its sole discretion, to modify
<li><strong>Changes.</strong> Operator reserves the right, at its sole discretion, to modify
or replace any part of this Agreement. It is your responsibility to check
this Agreement periodically for changes. Your continued use of or access
to the Website following the posting of any changes to this Agreement
@ -170,7 +194,7 @@ Please read this Agreement carefully before accessing or using the Website. By a
release of new tools and resources). Such new features and/or services
shall be subject to the terms and conditions of this Agreement.
</li>
<li>Termination. Operator may terminate your access to all or any part of
<li><strong>Termination.</strong> Operator may terminate your access to all or any part of
the Website at any time, with or without cause, with or without notice,
effective immediately. If you wish to terminate this Agreement or your
{{ app_config['html_title'] }} account (if you have one), you may simply
@ -179,7 +203,7 @@ Please read this Agreement carefully before accessing or using the Website. By a
including, without limitation, ownership provisions, warranty disclaimers,
indemnity and limitations of liability.
</li>
<li>Disclaimer of Warranties. The Website is provided “as is”. Operator and
<li><strong>Disclaimer of Warranties.</strong> The Website is provided “as is”. Operator and
its suppliers and licensors hereby disclaim all warranties of any kind,
express or implied, including, without limitation, the warranties of
merchantability, fitness for a particular purpose and non-infringement.
@ -189,7 +213,7 @@ Please read this Agreement carefully before accessing or using the Website. By a
understand that you download from, or otherwise obtain content or services
through, the Website at your own discretion and risk.
</li>
<li>Limitation of Liability. In no event will Operator, or its suppliers or
<li><strong>Limitation of Liability.</strong> In no event will Operator, or its suppliers or
licensors, be liable with respect to any subject matter of this agreement
under any contract, negligence, strict liability or other legal or
equitable theory for: (i) any special, incidental or consequential damages;
@ -201,7 +225,7 @@ Please read this Agreement carefully before accessing or using the Website. By a
reasonable control. The foregoing shall not apply to the extent prohibited
by applicable law.
</li>
<li>General Representation and Warranty. You represent and warrant that (i)
<li><strong>General Representation and Warranty.</strong> You represent and warrant that (i)
your use of the Website will be in strict accordance with the Operator
Privacy Policy, with this Agreement and with all applicable laws and
regulations (including without limitation any local laws or regulations in
@ -212,13 +236,13 @@ Please read this Agreement carefully before accessing or using the Website. By a
infringe or misappropriate the intellectual property rights of any third
party.
</li>
<li>Indemnification. You agree to indemnify and hold harmless Operator, its
<li><strong>Indemnification.</strong> You agree to indemnify and hold harmless Operator, its
contractors, and its licensors, and their respective directors, officers,
employees and agents from and against any and all claims and expenses,
including attorneys fees, arising out of your use of the Website,
including but not limited to out of your violation this Agreement.
</li>
<li>Miscellaneous. This Agreement constitutes the entire agreement between
<li><strong>Miscellaneous.</strong> This Agreement constitutes the entire agreement between
Operator and you concerning the subject matter hereof, and they may only
be modified by a written amendment signed by an authorized executive of
Operator, or by the posting by Operator of a revised version. If any part
@ -241,3 +265,5 @@ ShareAlike 3.0 License. Modifications to remove reference to "VIP services",
rename "blog" to "notice stream", remove the choice-of-venue clause, and add
variables specific to instances of this software made by Control Yourself, Inc.
and made available under the terms of the same license.
{% endblock -%}

View File

@ -37,7 +37,7 @@
{% if not user %}
<p>{% trans %}Sorry, no such user found.{% endtrans %}</p>
{# User exists, but needs verification #}
{% elif user.status == "needs_email_verification" %}
{% elif not user.has_privilege('active') %}
<div class="form_box">
<h1>{% trans %}Email verification needed{% endtrans %}</h1>
<p>

View File

@ -34,7 +34,7 @@
</h1>
{% if request.user %}
{% if request.user.status == 'active' %}
{% if request.user.has_privilege('active') %}
<p>
<a href="{{ request.urlgen('mediagoblin.submit.collection',
user=user.username) }}">

View File

@ -43,7 +43,7 @@
<p>{% trans %}Sorry, no such user found.{% endtrans %}</p>
{# User exists, but needs verification #}
{% elif user.status == "needs_email_verification" %}
{% elif not user.status.has_privilege('active') %}
{% if user == request.user %}
{# this should only be visible when you are this user #}
<div class="form_box">

View File

@ -96,8 +96,6 @@ def test_register_views(test_app):
new_user = mg_globals.database.User.query.filter_by(
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
@ -137,8 +135,6 @@ def test_register_views(test_app):
new_user = mg_globals.database.User.query.filter_by(
username=u'angrygirl').first()
assert new_user
assert new_user.status == u'needs_email_verification'
assert new_user.email_verified == False
## Verify the email activation works
template.clear_test_template_context()
@ -151,8 +147,6 @@ def test_register_views(test_app):
new_user = mg_globals.database.User.query.filter_by(
username=u'angrygirl').first()
assert new_user
assert new_user.status == u'active'
assert new_user.email_verified == True
# Uniqueness checks
# -----------------

View File

@ -112,8 +112,6 @@ class TestPersonaPlugin(object):
# Get user and detach from session
test_user = mg_globals.database.User.query.filter_by(
username=u'chris').first()
test_user.email_verified = True
test_user.status = u'active'
test_user.save()
test_user = mg_globals.database.User.query.filter_by(
username=u'chris').first()

View File

@ -57,7 +57,7 @@ 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',
@ -474,9 +474,8 @@ def atom_feed(request):
generates the atom feed with the newest images
"""
user = User.query.filter_by(
username = request.matchdict['user'],
status = u'active').first()
if not user:
username = request.matchdict['user']).first()
if not user or not user.has_privilege(u'active'):
return render_404(request)
cursor = MediaEntry.query.filter_by(
@ -537,9 +536,8 @@ def collection_atom_feed(request):
generates the atom feed with the newest images from a collection
"""
user = User.query.filter_by(
username = request.matchdict['user'],
status = u'active').first()
if not user:
username = request.matchdict['user']).first()
if not user or not user.has_privilege(u'active'):
return render_404(request)
collection = Collection.query.filter_by(