aboutsummaryrefslogtreecommitdiffstats
path: root/mediagoblin
diff options
context:
space:
mode:
authorjgart <jgart@dismail.de>2021-04-19 23:35:07 +0000
committerBen Sturmfels <ben@sturm.com.au>2021-04-23 17:48:03 +1000
commitec74b6d032ee23f6ebb163bba6005d636d824392 (patch)
tree4c51076661108d7ffd4cb040ba04d7fa75aa282e /mediagoblin
parent63ab28795aaf90f7da39dedc744c52d6eb9095e0 (diff)
downloadmediagoblin-ec74b6d032ee23f6ebb163bba6005d636d824392.tar.lz
mediagoblin-ec74b6d032ee23f6ebb163bba6005d636d824392.tar.xz
mediagoblin-ec74b6d032ee23f6ebb163bba6005d636d824392.zip
Remove Mozilla Persona plugin [#5512].
Mozilla persona is RIP since 2016. Signed-off-by: Ben Sturmfels <ben@sturm.com.au>
Diffstat (limited to 'mediagoblin')
-rw-r--r--mediagoblin/plugins/persona/README.rst41
-rw-r--r--mediagoblin/plugins/persona/__init__.py116
-rw-r--r--mediagoblin/plugins/persona/forms.py41
-rw-r--r--mediagoblin/plugins/persona/migrations/c7d4840a5592_persona_plugin_initial_migration.py35
-rw-r--r--mediagoblin/plugins/persona/models.py36
-rw-r--r--mediagoblin/plugins/persona/static/js/persona.js59
-rw-r--r--mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html43
-rw-r--r--mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html24
-rw-r--r--mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html25
-rw-r--r--mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/persona.html38
-rw-r--r--mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/persona_js_end.html21
-rw-r--r--mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html25
-rw-r--r--mediagoblin/plugins/persona/views.py194
-rw-r--r--mediagoblin/tests/auth_configs/persona_appconfig.ini42
-rw-r--r--mediagoblin/tests/test_persona.py221
15 files changed, 0 insertions, 961 deletions
diff --git a/mediagoblin/plugins/persona/README.rst b/mediagoblin/plugins/persona/README.rst
deleted file mode 100644
index ef19ac5d..00000000
--- a/mediagoblin/plugins/persona/README.rst
+++ /dev/null
@@ -1,41 +0,0 @@
-.. _persona-chapter:
-
-================
- persona plugin
-================
-
-The persona plugin allows users to login to you GNU MediaGoblin instance using
-`Mozilla Persona`_.
-
-This plugin can be enabled alongside :ref:`openid-chapter` and
-:ref:`basic_auth-chapter`.
-
-.. note::
- When :ref:`basic_auth-chapter` is enabled alongside this persona plugin, and
- a user creates an account using their persona. If they would like to add a
- password to their account, they can use the forgot password feature to do
- so.
-
-.. _Mozilla Persona: https://www.mozilla.org/en-US/persona/
-
-Set up the persona plugin
-=========================
-
-1. Install the ``requests`` package.
-
-2. Add the following to your MediaGoblin .ini file in the ``[plugins]`` section::
-
- [[mediagoblin.plugins.persona]]
-
-3. Run::
-
- gmg dbupdate
-
- in order to create and apply migrations to any database tables that the
- plugin requires.
-
-4. Run::
-
- gmg assetlink
-
- in order to persona's static assets.
diff --git a/mediagoblin/plugins/persona/__init__.py b/mediagoblin/plugins/persona/__init__.py
deleted file mode 100644
index 8fab726a..00000000
--- a/mediagoblin/plugins/persona/__init__.py
+++ /dev/null
@@ -1,116 +0,0 @@
-# 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/>.
-from pkg_resources import resource_filename
-import os
-
-from sqlalchemy import or_
-
-from mediagoblin.auth.tools import create_basic_user
-from mediagoblin.db.models import User, LocalUser
-from mediagoblin.plugins.persona.models import PersonaUserEmails
-from mediagoblin.tools import pluginapi
-from mediagoblin.tools.staticdirect import PluginStatic
-from mediagoblin.tools.translate import pass_to_ugettext as _
-
-PLUGIN_DIR = os.path.dirname(__file__)
-
-
-def setup_plugin():
- config = pluginapi.get_config('mediagoblin.plugins.persona')
-
- routes = [
- ('mediagoblin.plugins.persona.login',
- '/auth/persona/login/',
- 'mediagoblin.plugins.persona.views:login'),
- ('mediagoblin.plugins.persona.register',
- '/auth/persona/register/',
- 'mediagoblin.plugins.persona.views:register'),
- ('mediagoblin.plugins.persona.edit',
- '/edit/persona/',
- 'mediagoblin.plugins.persona.views:edit'),
- ('mediagoblin.plugins.persona.add',
- '/edit/persona/add/',
- 'mediagoblin.plugins.persona.views:add')]
-
- pluginapi.register_routes(routes)
- pluginapi.register_template_path(os.path.join(PLUGIN_DIR, 'templates'))
- pluginapi.register_template_hooks(
- {'persona_end': 'mediagoblin/plugins/persona/persona_js_end.html',
- 'persona_form': 'mediagoblin/plugins/persona/persona.html',
- 'edit_link': 'mediagoblin/plugins/persona/edit_link.html',
- 'login_link': 'mediagoblin/plugins/persona/login_link.html',
- 'register_link': 'mediagoblin/plugins/persona/register_link.html'})
-
-
-def create_user(register_form):
- if 'persona_email' in register_form:
- username = register_form.username.data
- user = User.query.filter(
- or_(
- LocalUser.username == username,
- LocalUser.email == username,
- )).first()
-
- if not user:
- user = create_basic_user(register_form)
-
- new_entry = PersonaUserEmails()
- new_entry.persona_email = register_form.persona_email.data
- new_entry.user_id = user.id
- new_entry.save()
-
- return user
-
-
-def extra_validation(register_form):
- persona_email = register_form.persona_email.data if 'persona_email' in \
- register_form else None
- if persona_email:
- persona_email_exists = PersonaUserEmails.query.filter_by(
- persona_email=persona_email
- ).count()
-
- extra_validation_passes = True
-
- if persona_email_exists:
- register_form.persona_email.errors.append(
- _('Sorry, an account is already registered to that Persona'
- ' email.'))
- extra_validation_passes = False
-
- return extra_validation_passes
-
-
-def Auth():
- return True
-
-
-def add_to_global_context(context):
- if len(pluginapi.hook_runall('authentication')) == 1:
- context['persona_auth'] = True
- context['persona'] = True
- return context
-
-hooks = {
- 'setup': setup_plugin,
- 'authentication': Auth,
- 'auth_extra_validation': extra_validation,
- 'auth_create_user': create_user,
- 'template_global_context': add_to_global_context,
- 'static_setup': lambda: PluginStatic(
- 'coreplugin_persona',
- resource_filename('mediagoblin.plugins.persona', 'static'))
-}
diff --git a/mediagoblin/plugins/persona/forms.py b/mediagoblin/plugins/persona/forms.py
deleted file mode 100644
index f74d97fa..00000000
--- a/mediagoblin/plugins/persona/forms.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# 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/>.
-import wtforms
-
-from mediagoblin.tools.translate import lazy_pass_to_ugettext as _
-from mediagoblin.auth.tools import normalize_user_or_email_field
-
-
-class RegistrationForm(wtforms.Form):
- username = wtforms.StringField(
- _('Username'),
- [wtforms.validators.InputRequired(),
- normalize_user_or_email_field(allow_email=False)])
- email = wtforms.StringField(
- _('Email address'),
- [wtforms.validators.InputRequired(),
- normalize_user_or_email_field(allow_user=False)])
- persona_email = wtforms.HiddenField(
- '',
- [wtforms.validators.InputRequired(),
- normalize_user_or_email_field(allow_user=False)])
-
-
-class EditForm(wtforms.Form):
- email = wtforms.StringField(
- _('Email address'),
- [wtforms.validators.InputRequired(),
- normalize_user_or_email_field(allow_user=False)])
diff --git a/mediagoblin/plugins/persona/migrations/c7d4840a5592_persona_plugin_initial_migration.py b/mediagoblin/plugins/persona/migrations/c7d4840a5592_persona_plugin_initial_migration.py
deleted file mode 100644
index 0c40893a..00000000
--- a/mediagoblin/plugins/persona/migrations/c7d4840a5592_persona_plugin_initial_migration.py
+++ /dev/null
@@ -1,35 +0,0 @@
-"""Persona plugin initial migration
-
-Revision ID: c7d4840a5592
-Revises: 52bf0ccbedc1
-Create Date: 2016-03-12 23:30:33.624390
-
-"""
-
-# revision identifiers, used by Alembic.
-revision = 'c7d4840a5592'
-down_revision = '52bf0ccbedc1'
-branch_labels = ('persona_plugin',)
-depends_on = None
-
-from alembic import op
-import sqlalchemy as sa
-
-
-def upgrade():
- if op.get_bind().engine.has_table('persona__user_emails'):
- # Skip; this has already been instantiated
- # (probably via sqlalchemy-migrate)
- return
-
- op.create_table(
- 'persona__user_emails',
- sa.Column('id', sa.Integer(), nullable=False),
- sa.Column('persona_email', sa.Unicode(), nullable=False),
- sa.Column('user_id', sa.Integer(), nullable=False),
- sa.ForeignKeyConstraint(['user_id'], ['core__users.id'], ),
- sa.PrimaryKeyConstraint('id'))
-
-
-def downgrade():
- op.drop_table('persona__user_emails')
diff --git a/mediagoblin/plugins/persona/models.py b/mediagoblin/plugins/persona/models.py
deleted file mode 100644
index ff3c525a..00000000
--- a/mediagoblin/plugins/persona/models.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# 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/>.
-from sqlalchemy import Column, Integer, Unicode, ForeignKey
-from sqlalchemy.orm import relationship, backref
-
-from mediagoblin.db.models import User
-from mediagoblin.db.base import Base
-
-
-class PersonaUserEmails(Base):
- __tablename__ = "persona__user_emails"
-
- id = Column(Integer, primary_key=True)
- persona_email = Column(Unicode, nullable=False)
- user_id = Column(Integer, ForeignKey(User.id), nullable=False)
-
- # Persona's are owned by their user, so do the full thing.
- user = relationship(User, backref=backref('persona_emails',
- cascade='all, delete-orphan'))
-
-MODELS = [
- PersonaUserEmails
-]
diff --git a/mediagoblin/plugins/persona/static/js/persona.js b/mediagoblin/plugins/persona/static/js/persona.js
deleted file mode 100644
index 76a7757a..00000000
--- a/mediagoblin/plugins/persona/static/js/persona.js
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * 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/>.
- */
-
-$(document).ready(function () {
- var requestParams = {
- backgroundColor: "#171717",
- siteName: "GNU MediaGoblin",
- siteLogo: "data:image/png;base64,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"
- };
-
- var signinLink = document.getElementById('persona_login');
- if (signinLink) {
- signinLink.onclick = function() { navigator.id.request(requestParams); };
- }
-
- var signinLink1 = document.getElementById('persona_login1');
- if (signinLink1) {
- signinLink1.onclick = function() { navigator.id.request(requestParams); };
- }
-
- var signoutLink = document.getElementById('logout');
- if (signoutLink) {
- signoutLink.onclick = function() { navigator.id.logout(); };
- }
-
- var logout_url = document.getElementById('_logout_url').value;
- var persona_user = document.getElementById('_persona_user').value;
-
- navigator.id.watch({
- loggedInUser: persona_user || null,
- onlogin: function(assertion) {
- document.getElementById('_assertion').value = assertion;
- document.getElementById('_persona_login').submit();
- },
- onlogout: function() {
- $.ajax({
- type: 'GET',
- url: logout_url,
- success: function(res, status, xhr) { window.location.reload(); },
- error: function(xhr, status, err) { alert("Logout failure: " + err); }
- });
- }
- });
-});
diff --git a/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html b/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html
deleted file mode 100644
index be62b8cc..00000000
--- a/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html
+++ /dev/null
@@ -1,43 +0,0 @@
-{#
-# 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 %}Add an OpenID{% endtrans %} &mdash; {{ super() }}
-{%- endblock %}
-
-{% block mediagoblin_content %}
- <form action="{{ request.urlgen('mediagoblin.plugins.persona.edit') }}"
- method="POST" enctype="multipart/form-data">
- {{ csrf_token }}
- <div class="form_box">
- <h1>{% trans %}Delete a Persona email address{% endtrans %}</h1>
- <p>
- <a href="javascript:;" id="persona_login">
- {% trans %}Add a Persona email address{% endtrans %}
- </a>
- </p>
- {{ wtforms_util.render_divs(form, True) }}
- <div class="form_submit_buttons">
- <input type="submit" value="{% trans %}Delete{% endtrans %}" class="button_form"/>
- </div>
- </div>
- </form>
-{% endblock %}
diff --git a/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html b/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html
deleted file mode 100644
index a022c62a..00000000
--- a/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html
+++ /dev/null
@@ -1,24 +0,0 @@
-{#
-# 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/>.
-#}
-
-{% block persona_edit_link %}
- <a href="{{ request.urlgen('mediagoblin.plugins.persona.edit') }}">
- {% trans %}Persona's{% endtrans %}
- </a>
- &middot;
-{% endblock %}
diff --git a/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html b/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html
deleted file mode 100644
index 975683da..00000000
--- a/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html
+++ /dev/null
@@ -1,25 +0,0 @@
-{#
-# 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/>.
-#}
-
-{% block person_login_link %}
- <p>
- <a href="javascript:;" id="persona_login">
- {% trans %}Or login with Persona!{% endtrans %}
- </a>
- </p>
-{% endblock %}
diff --git a/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/persona.html b/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/persona.html
deleted file mode 100644
index 03d63aae..00000000
--- a/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/persona.html
+++ /dev/null
@@ -1,38 +0,0 @@
-{#
-# 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/>.
-#}
-{% block persona %}
- <form id="_persona_login"
- action=
- {%- if edit_persona is defined -%}
- "{{ request.urlgen('mediagoblin.plugins.persona.add') }}"
- {%- else -%}
- "{{ request.urlgen('mediagoblin.plugins.persona.login') }}"
- {%- endif %}
- method="POST">
- {{ csrf_token }}
- <input type="hidden" name="assertion" type="text" id="_assertion"/>
- <input type="hidden" name="_logout_url" type="text" id="_logout_url"
- value="{{ request.urlgen('mediagoblin.auth.logout') }}"/>
- <input type="hidden" type="text" id="_persona_user"
- {% if request.session.get('persona_login_email', False) %}
- value="{{ request.session['persona_login_email'] }}"/>
- {% else %}
- value=""/>
- {% endif %}
- </form>
-{% endblock %}
diff --git a/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/persona_js_end.html b/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/persona_js_end.html
deleted file mode 100644
index 8c0d72d5..00000000
--- a/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/persona_js_end.html
+++ /dev/null
@@ -1,21 +0,0 @@
-{#
-# 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/>.
-#}
-
-<script src="https://login.persona.org/include.js"></script>
-<script type="text/javascript"
- src="{{ request.staticdirect('/js/persona.js', 'coreplugin_persona') }}"></script>
diff --git a/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html b/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html
deleted file mode 100644
index bcd9ae2b..00000000
--- a/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html
+++ /dev/null
@@ -1,25 +0,0 @@
-{#
-# 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/>.
-#}
-
-{% block persona_register_link %}
- <p>
- <a href="javascript:;" id="persona_login">
- {% trans %}Or register with Persona!{% endtrans %}
- </a>
- </p>
-{% endblock %}
diff --git a/mediagoblin/plugins/persona/views.py b/mediagoblin/plugins/persona/views.py
deleted file mode 100644
index d97429be..00000000
--- a/mediagoblin/plugins/persona/views.py
+++ /dev/null
@@ -1,194 +0,0 @@
-# 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/>.
-import json
-import logging
-import requests
-
-from werkzeug.exceptions import BadRequest
-
-from mediagoblin import messages, mg_globals
-from mediagoblin.auth.tools import register_user
-from mediagoblin.decorators import (auth_enabled, allow_registration,
- require_active_login)
-from mediagoblin.tools.response import render_to_response, redirect
-from mediagoblin.tools.translate import pass_to_ugettext as _
-from mediagoblin.plugins.persona import forms
-from mediagoblin.plugins.persona.models import PersonaUserEmails
-
-_log = logging.getLogger(__name__)
-
-
-def _get_response(request):
- if 'assertion' not in request.form:
- _log.debug('assertion not in request.form')
- raise BadRequest()
-
- data = {'assertion': request.form['assertion'],
- 'audience': request.urlgen('index', qualified=True)}
- resp = requests.post('https://verifier.login.persona.org/verify',
- data=data, verify=True)
-
- if resp.ok:
- verification_data = json.loads(resp.content)
-
- if verification_data['status'] == 'okay':
- return verification_data['email']
-
- return None
-
-
-@auth_enabled
-def login(request):
- if request.method == 'GET':
- return redirect(request, 'mediagoblin.auth.login')
-
- email = _get_response(request)
- if email:
- query = PersonaUserEmails.query.filter_by(
- persona_email=email
- ).first()
- user = query.user if query else None
-
- if user:
- request.session['user_id'] = str(user.id)
- request.session['persona_login_email'] = email
- request.session.save()
-
- return redirect(request, "index")
-
- else:
- if not mg_globals.app.auth:
- messages.add_message(
- request,
- messages.WARNING,
- _('Sorry, authentication is disabled on this instance.'))
-
- return redirect(request, 'index')
-
- register_form = forms.RegistrationForm(email=email,
- persona_email=email)
- return render_to_response(
- request,
- 'mediagoblin/auth/register.html',
- {'register_form': register_form,
- 'post_url': request.urlgen(
- 'mediagoblin.plugins.persona.register')})
-
- return redirect(request, 'mediagoblin.auth.login')
-
-
-@allow_registration
-@auth_enabled
-def register(request):
- if request.method == 'GET':
- # Need to connect to persona before registering a user. If method is
- # 'GET', then this page was acessed without logging in first.
- return redirect(request, 'mediagoblin.auth.login')
- register_form = forms.RegistrationForm(request.form)
-
- if register_form.validate():
- user = register_user(request, register_form)
-
- if user:
- # redirect the user to their homepage... there will be a
- # message waiting for them to verify their email
- return redirect(
- request, 'mediagoblin.user_pages.user_home',
- user=user.username)
-
- return render_to_response(
- request,
- 'mediagoblin/auth/register.html',
- {'register_form': register_form,
- 'post_url': request.urlgen('mediagoblin.plugins.persona.register')})
-
-
-@require_active_login
-def edit(request):
- form = forms.EditForm(request.form)
-
- if request.method == 'POST' and form.validate():
- query = PersonaUserEmails.query.filter_by(
- persona_email=form.email.data)
- user = query.first().user if query.first() else None
-
- if user and user.id == int(request.user.id):
- count = len(user.persona_emails)
-
- if count > 1 or user.pw_hash:
- # User has more then one Persona email or also has a password.
- query.first().delete()
-
- messages.add_message(
- request,
- messages.SUCCESS,
- _('The Persona email address was successfully removed.'))
-
- return redirect(request, 'mediagoblin.edit.account')
-
- elif not count > 1:
- form.email.errors.append(
- _("You can't delete your only Persona email address unless"
- " you have a password set."))
-
- else:
- form.email.errors.append(
- _('That Persona email address is not registered to this'
- ' account.'))
-
- return render_to_response(
- request,
- 'mediagoblin/plugins/persona/edit.html',
- {'form': form,
- 'edit_persona': True})
-
-
-@require_active_login
-def add(request):
- if request.method == 'GET':
- return redirect(request, 'mediagoblin.plugins.persona.edit')
-
- email = _get_response(request)
-
- if email:
- query = PersonaUserEmails.query.filter_by(
- persona_email=email
- ).first()
- user_exists = query.user if query else None
-
- if user_exists:
- messages.add_message(
- request,
- messages.WARNING,
- _('Sorry, an account is already registered with that Persona'
- ' email address.'))
- return redirect(request, 'mediagoblin.plugins.persona.edit')
-
- else:
- # Save the Persona Email to the user
- new_entry = PersonaUserEmails()
- new_entry.persona_email = email
- new_entry.user_id = request.user.id
- new_entry.save()
-
- request.session['persona_login_email'] = email
-
- messages.add_message(
- request,
- messages.SUCCESS,
- _('Your Persona email address was saved successfully.'))
-
- return redirect(request, 'mediagoblin.edit.account')
diff --git a/mediagoblin/tests/auth_configs/persona_appconfig.ini b/mediagoblin/tests/auth_configs/persona_appconfig.ini
deleted file mode 100644
index 0bd5d634..00000000
--- a/mediagoblin/tests/auth_configs/persona_appconfig.ini
+++ /dev/null
@@ -1,42 +0,0 @@
-# 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/>.
-[mediagoblin]
-direct_remote_path = /test_static/
-email_sender_address = "notice@mediagoblin.example.org"
-email_debug_mode = true
-
-# TODO: Switch to using an in-memory database
-sql_engine = "sqlite:///%(here)s/user_dev/mediagoblin.db"
-
-# Celery shouldn't be set up by the application as it's setup via
-# mediagoblin.init.celery.from_celery
-celery_setup_elsewhere = true
-
-[storage:publicstore]
-base_dir = %(here)s/user_dev/media/public
-base_url = /mgoblin_media/
-
-[storage:queuestore]
-base_dir = %(here)s/user_dev/media/queue
-
-[celery]
-CELERY_ALWAYS_EAGER = true
-CELERY_RESULT_DBURI = "sqlite:///%(here)s/user_dev/celery.db"
-BROKER_HOST = "sqlite:///%(here)s/user_dev/kombu.db"
-
-[plugins]
-[[mediagoblin.plugins.persona]]
-
diff --git a/mediagoblin/tests/test_persona.py b/mediagoblin/tests/test_persona.py
deleted file mode 100644
index 6e7ee419..00000000
--- a/mediagoblin/tests/test_persona.py
+++ /dev/null
@@ -1,221 +0,0 @@
-# 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/>.
-
-import pkg_resources
-import pytest
-try:
- from unittest import mock
-except ImportError:
- import unittest.mock as mock
-
-import urllib.parse as urlparse
-
-pytest.importorskip("requests")
-
-from mediagoblin import mg_globals
-from mediagoblin.db.base import Session
-from mediagoblin.db.models import Privilege, LocalUser
-from mediagoblin.tests.tools import get_app
-from mediagoblin.tools import template
-
-
-# App with plugin enabled
-@pytest.fixture()
-def persona_plugin_app(request):
- return get_app(
- request,
- mgoblin_config=pkg_resources.resource_filename(
- 'mediagoblin.tests.auth_configs',
- 'persona_appconfig.ini'))
-
-
-class TestPersonaPlugin:
- def test_authentication_views(self, persona_plugin_app):
- res = persona_plugin_app.get('/auth/login/')
-
- assert urlparse.urlsplit(res.location)[2] == '/'
-
- res = persona_plugin_app.get('/auth/register/')
-
- assert urlparse.urlsplit(res.location)[2] == '/'
-
- res = persona_plugin_app.get('/auth/persona/login/')
-
- assert urlparse.urlsplit(res.location)[2] == '/auth/login/'
-
- res = persona_plugin_app.get('/auth/persona/register/')
-
- assert urlparse.urlsplit(res.location)[2] == '/auth/login/'
-
- @mock.patch('mediagoblin.plugins.persona.views._get_response', mock.Mock(return_value='test@example.com'))
- def _test_registration():
- # No register users
- template.clear_test_template_context()
- res = persona_plugin_app.post(
- '/auth/persona/login/', {})
-
- assert 'mediagoblin/auth/register.html' in template.TEMPLATE_TEST_CONTEXT
- context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
- register_form = context['register_form']
-
- assert register_form.email.data == 'test@example.com'
- assert register_form.persona_email.data == 'test@example.com'
-
- template.clear_test_template_context()
- res = persona_plugin_app.post(
- '/auth/persona/register/', {})
-
- assert 'mediagoblin/auth/register.html' in template.TEMPLATE_TEST_CONTEXT
- context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
- register_form = context['register_form']
-
- assert register_form.username.errors == ['This field is required.']
- assert register_form.email.errors == ['This field is required.']
- assert register_form.persona_email.errors == ['This field is required.']
-
- # Successful register
- template.clear_test_template_context()
- res = persona_plugin_app.post(
- '/auth/persona/register/',
- {'username': 'chris',
- 'email': 'chris@example.com',
- 'persona_email': 'test@example.com'})
- res.follow()
-
- assert urlparse.urlsplit(res.location)[2] == '/u/chris/'
- assert 'mediagoblin/user_pages/user_nonactive.html' in template.TEMPLATE_TEST_CONTEXT
-
- # Try to register same Persona email address
- template.clear_test_template_context()
- res = persona_plugin_app.post(
- '/auth/persona/register/',
- {'username': 'chris1',
- 'email': 'chris1@example.com',
- 'persona_email': 'test@example.com'})
-
- assert 'mediagoblin/auth/register.html' in template.TEMPLATE_TEST_CONTEXT
- context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
- register_form = context['register_form']
-
- assert register_form.persona_email.errors == ['Sorry, an account is already registered to that Persona email.']
-
- # Logout
- persona_plugin_app.get('/auth/logout/')
-
- # Get user and detach from session
- test_user = mg_globals.database.LocalUser.query.filter(
- LocalUser.username=='chris'
- ).first()
- active_privilege = Privilege.query.filter(
- Privilege.privilege_name=='active').first()
- test_user.all_privileges.append(active_privilege)
- test_user.save()
- test_user = mg_globals.database.LocalUser.query.filter(
- LocalUser.username=='chris'
- ).first()
- Session.expunge(test_user)
-
- # Add another user for _test_edit_persona
- persona_plugin_app.post(
- '/auth/persona/register/',
- {'username': 'chris1',
- 'email': 'chris1@example.com',
- 'persona_email': 'test1@example.com'})
-
- # Log back in
- template.clear_test_template_context()
- res = persona_plugin_app.post(
- '/auth/persona/login/')
- res.follow()
-
- assert urlparse.urlsplit(res.location)[2] == '/'
- assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT
-
- # Make sure user is in the session
- context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html']
- session = context['request'].session
- assert session['user_id'] == str(test_user.id)
-
- _test_registration()
-
- @mock.patch('mediagoblin.plugins.persona.views._get_response', mock.Mock(return_value='new@example.com'))
- def _test_edit_persona():
- # Try and delete only Persona email address
- template.clear_test_template_context()
- res = persona_plugin_app.post(
- '/edit/persona/',
- {'email': 'test@example.com'})
-
- assert 'mediagoblin/plugins/persona/edit.html' in template.TEMPLATE_TEST_CONTEXT
- context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/persona/edit.html']
- form = context['form']
-
- assert form.email.errors == ["You can't delete your only Persona email address unless you have a password set."]
-
- template.clear_test_template_context()
- res = persona_plugin_app.post(
- '/edit/persona/', {})
-
- assert 'mediagoblin/plugins/persona/edit.html' in template.TEMPLATE_TEST_CONTEXT
- context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/persona/edit.html']
- form = context['form']
-
- assert form.email.errors == ['This field is required.']
-
- # Try and delete Persona not owned by the user
- template.clear_test_template_context()
- res = persona_plugin_app.post(
- '/edit/persona/',
- {'email': 'test1@example.com'})
-
- assert 'mediagoblin/plugins/persona/edit.html' in template.TEMPLATE_TEST_CONTEXT
- context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/persona/edit.html']
- form = context['form']
-
- assert form.email.errors == ['That Persona email address is not registered to this account.']
-
- res = persona_plugin_app.get('/edit/persona/add/')
-
- assert urlparse.urlsplit(res.location)[2] == '/edit/persona/'
-
- # Add Persona email address
- template.clear_test_template_context()
- res = persona_plugin_app.post(
- '/edit/persona/add/')
- res.follow()
-
- assert urlparse.urlsplit(res.location)[2] == '/edit/account/'
-
- # Delete a Persona
- res = persona_plugin_app.post(
- '/edit/persona/',
- {'email': 'test@example.com'})
- res.follow()
-
- assert urlparse.urlsplit(res.location)[2] == '/edit/account/'
-
- _test_edit_persona()
-
- @mock.patch('mediagoblin.plugins.persona.views._get_response', mock.Mock(return_value='test1@example.com'))
- def _test_add_existing():
- template.clear_test_template_context()
- res = persona_plugin_app.post(
- '/edit/persona/add/')
- res.follow()
-
- assert urlparse.urlsplit(res.location)[2] == '/edit/persona/'
-
- _test_add_existing()