Skip to content

Commit

Permalink
Allow listed add-ons to become unlisted (bug 1122108)
Browse files Browse the repository at this point in the history
  • Loading branch information
robhudson committed Apr 22, 2015
1 parent cc7139d commit d2dfe31
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 6 deletions.
6 changes: 6 additions & 0 deletions apps/amo/log.py
Expand Up @@ -577,6 +577,12 @@ class CONTENT_RATING_CHANGED(_LOG):
format = _('{addon} content rating changed.')


class ADDON_UNLISTED(_LOG):
id = 128
format = _(u'{addon} unlisted.')
keep = True


LOGS = [x for x in vars().values()
if isclass(x) and issubclass(x, _LOG) and x != _LOG]

Expand Down
36 changes: 35 additions & 1 deletion apps/devhub/templates/devhub/versions/list.html
Expand Up @@ -116,7 +116,7 @@ <h3>{{ _('Addon visibility') }}</h3>
<strong>{{ _('Hidden:') }}</strong> {{ _('Hosted on {0}, but hidden to anyone but authors. Used to temporarily hide listings or discontinue them.')|f(settings.SITE_URL) }}</label>
<br><br>
<label><input name="addon-state" value="unlisted" type="radio"
disabled="disabled"
{% if not owner or addon.status == amo.STATUS_DISABLED %}disabled="disabled"{% endif %}
{% if not addon.is_listed %}checked="checked"{% endif %}
class="unlist-addon">
<strong>{{ _('Unlisted:') }}</strong> {{ _('Not distributed on {0}. Developers will upload new versions for signing and distribute the add-ons on their own.')|f(settings.SITE_URL) }}</label>
Expand Down Expand Up @@ -277,6 +277,40 @@ <h3>
</div>
{% endif %}

{% if addon.is_listed %}
<div id="modal-unlist" class="modal">
<form method="post" action="{{ addon.get_dev_url('unlist') }}">
<h3>
{{ _('Unlist Add-on') }}
</h3>
<p>
{% trans update_url='https://developer.mozilla.org/docs/Mozilla/Add-ons/Install_Manifests#updateURL' %}
Unlisting your add-on will make it (and each of its versions/files)
invisible on this website. It won't show up in searches, won't have a
public facing page, and won't be updated automatically for current
users. It is recommended for unlisted add-ons to provide a custom
<a href="{{ update_url }}" target="_blank">updateURL</a> in their
install.rdf file for automatic updates.
{% endtrans %}
</p>
<p>
{% trans %}
Are you sure you wish to unlist your add-on?
{% endtrans %}
</p>
{{ csrf() }}
<input type="hidden" name="addon_id" class="addon_id" value="{{ addon.id }}">
<p>
<button type="submit">
{{ _('Unlist Add-on') }}
</button>
{{ _('or') }} <a href="#" class="close">{{ _('Cancel') }}</a>
</p>
</form>
</div>
{% endif %}


{% if not addon.is_disabled and addon.is_under_review %}
<div id="modal-cancel" class="modal">
<form method="post" action="{{ url('devhub.addons.cancel', addon.slug) }}">
Expand Down
34 changes: 29 additions & 5 deletions apps/devhub/tests/test_views_versions.py
Expand Up @@ -32,6 +32,7 @@ def setUp(self):

self.disable_url = self.addon.get_dev_url('disable')
self.enable_url = self.addon.get_dev_url('enable')
self.unlist_url = self.addon.get_dev_url('unlist')
self.delete_url = reverse('devhub.versions.delete', args=['a3615'])
self.delete_data = {'addon_id': self.addon.pk,
'version_id': self.version.pk}
Expand Down Expand Up @@ -186,6 +187,24 @@ def test_user_can_disable_addon(self, hide_mock):
msg = entry.to_string()
assert self.addon.name.__unicode__() in msg, ("Unexpected: %r" % msg)

@mock.patch('devhub.views.unindex_addons')
def test_user_can_unlist_addon(self, unindex):
self.addon.update(status=amo.STATUS_PUBLIC, disabled_by_user=False,
is_listed=True)
res = self.client.post(self.unlist_url)
assert res.status_code == 302
addon = Addon.with_unlisted.get(id=3615)
assert addon.status == amo.STATUS_PUBLIC
assert not addon.is_listed

# Make sure we remove the addon from the search index.
assert unindex.delay.called

entry = ActivityLog.objects.get()
assert entry.action == amo.LOG.ADDON_UNLISTED.id
msg = entry.to_string()
assert self.addon.name.__unicode__() in msg

def test_user_get(self):
eq_(self.client.get(self.enable_url).status_code, 405)

Expand Down Expand Up @@ -240,7 +259,7 @@ def test_non_owner_cant_change_status(self):
assert not doc('.disable-addon').attr('checked')
assert doc('.disable-addon').attr('disabled') == 'disabled'
assert not doc('.unlist-addon').attr('checked')
assert doc('.unlist-addon').attr('disabled') == 'disabled' # Readonly.
assert doc('.unlist-addon').attr('disabled') == 'disabled'

def test_published_addon_radio(self):
"""Published (listed) addon is selected: can hide or publish."""
Expand All @@ -252,10 +271,11 @@ def test_published_addon_radio(self):
assert doc('.enable-addon').attr('data-url') == enable_url
assert not doc('.enable-addon').attr('disabled')
assert doc('#modal-disable')
assert doc('#modal-unlist')
assert not doc('.disable-addon').attr('checked')
assert not doc('.disable-addon').attr('disabled')
assert not doc('.unlist-addon').attr('checked')
assert doc('.unlist-addon').attr('disabled') == 'disabled' # Readonly.
assert not doc('.unlist-addon').attr('disabled')

def test_hidden_addon_radio(self):
"""Hidden (disabled) addon is selected: can hide or publish."""
Expand All @@ -267,7 +287,9 @@ def test_hidden_addon_radio(self):
assert doc('.disable-addon').attr('checked') == 'checked'
assert not doc('.disable-addon').attr('disabled')
assert not doc('.unlist-addon').attr('checked')
assert doc('.unlist-addon').attr('disabled') == 'disabled' # Readonly.
assert not doc('.unlist-addon').attr('disabled')
assert not doc('#modal-disable')
assert doc('#modal-unlist')

def test_status_disabled_addon_radio(self):
"""Disabled by Mozilla addon: hidden selected, can't change status."""
Expand All @@ -279,7 +301,7 @@ def test_status_disabled_addon_radio(self):
assert doc('.disable-addon').attr('checked') == 'checked'
assert doc('.disable-addon').attr('disabled') == 'disabled'
assert not doc('.unlist-addon').attr('checked')
assert doc('.unlist-addon').attr('disabled') == 'disabled' # Readonly.
assert doc('.unlist-addon').attr('disabled') == 'disabled'

def test_unlisted_addon_cant_change_status(self):
"""Unlisted addon: can't change its status."""
Expand All @@ -291,7 +313,9 @@ def test_unlisted_addon_cant_change_status(self):
assert not doc('.disable-addon').attr('checked')
assert doc('.disable-addon').attr('disabled') == 'disabled'
assert doc('.unlist-addon').attr('checked') == 'checked'
assert doc('.unlist-addon').attr('disabled') == 'disabled' # Readonly.
assert not doc('.unlist-addon').attr('disabled')
assert doc('#modal-disable')
assert not doc('#modal-unlist')

def test_cancel_get(self):
cancel_url = reverse('devhub.addons.cancel', args=['a3615'])
Expand Down
1 change: 1 addition & 0 deletions apps/devhub/urls.py
Expand Up @@ -48,6 +48,7 @@
url('^edit$', views.edit, name='devhub.addons.edit'),
url('^delete$', views.delete, name='devhub.addons.delete'),
url('^disable$', views.disable, name='devhub.addons.disable'),
url('^unlist$', views.unlist, name='devhub.addons.unlist'),
url('^enable$', views.enable, name='devhub.addons.enable'),
url('^cancel$', views.cancel, name='devhub.addons.cancel'),
url('^ownership$', views.ownership, name='devhub.addons.owner'),
Expand Down
10 changes: 10 additions & 0 deletions apps/devhub/views.py
Expand Up @@ -33,6 +33,7 @@
from addons import forms as addon_forms
from addons.decorators import addon_view
from addons.models import Addon, AddonUser
from addons.tasks import unindex_addons
from addons.views import BaseFilter
from amo import messages
from amo.decorators import json_view, login_required, post_required, write
Expand Down Expand Up @@ -390,6 +391,15 @@ def disable(request, addon_id, addon):
return redirect(addon.get_dev_url('versions'))


@dev_required
@post_required
def unlist(request, addon_id, addon):
addon.update(is_listed=False)
amo.log(amo.LOG.ADDON_UNLISTED, addon)
unindex_addons.delay([addon.id])
return redirect(addon.get_dev_url('versions'))


@dev_required(owner_for_post=True)
def ownership(request, addon_id, addon):
fs, ctx = [], {}
Expand Down
8 changes: 8 additions & 0 deletions static/js/zamboni/devhub.js
Expand Up @@ -226,6 +226,14 @@ $(document).ready(function() {
$modalDisable.render();
}
}
if ($("#modal-unlist").length) {
$modalUnlist = $('#modal-unlist').modal('.unlist-addon', {
width: 400
});
if (window.location.hash === '#unlist-addon') {
$modalUnlist.render();
}
}

$('.enable-addon').bind('click', function() {
$.ajax({
Expand Down

0 comments on commit d2dfe31

Please sign in to comment.