コード例 #1
0
def version_edit(request, addon_id, addon, version_id):
    show_features = waffle.switch_is_active('buchets') and addon.is_packaged
    formdata = request.POST if request.method == 'POST' else None
    version = get_object_or_404(Version, pk=version_id, addon=addon)
    version.addon = addon  # Avoid extra useless query.
    form = AppVersionForm(formdata, instance=version)
    all_forms = [form]

    if show_features:
        appfeatures = version.features
        appfeatures_form = AppFeaturesForm(request.POST or None,
                                           instance=appfeatures)
        all_forms.append(appfeatures_form)

    if request.method == 'POST' and all(f.is_valid() for f in all_forms):
        [f.save() for f in all_forms]
        messages.success(request, _('Version successfully edited.'))
        return redirect(addon.get_dev_url('versions'))

    context = {'addon': addon, 'version': version, 'form': form}

    if show_features:
        context.update({
            'appfeatures_form':
            appfeatures_form,
            'appfeatures':
            appfeatures,
            'feature_list': [unicode(f) for f in appfeatures.to_list()]
        })

    return jingo.render(request, 'developers/apps/version_edit.html', context)
コード例 #2
0
ファイル: test_views.py プロジェクト: diox/zamboni
 def test_appfeatures_creation(self):
     addon = self.post_addon(data={
         'free_platforms': ['free-desktop'],
         'has_contacts': 'on'
     })
     features = addon.latest_version.features
     ok_(isinstance(features, AppFeatures))
     field_names = [f.name for f in AppFeaturesForm().all_fields()]
     for field in field_names:
         expected = field == 'has_contacts'
         eq_(getattr(features, field), expected)
コード例 #3
0
def version_edit(request, addon_id, addon, version_id):
    show_features = waffle.switch_is_active('buchets') and addon.is_packaged
    formdata = request.POST if request.method == 'POST' else None
    version = get_object_or_404(Version, pk=version_id, addon=addon)
    version.addon = addon  # Avoid extra useless query.
    form = AppVersionForm(formdata, instance=version)
    all_forms = [form]

    if show_features:
        appfeatures = version.features
        appfeatures_form = AppFeaturesForm(request.POST or None,
                                           instance=appfeatures)
        all_forms.append(appfeatures_form)

    if request.method == 'POST' and all(f.is_valid() for f in all_forms):
        [f.save() for f in all_forms]

        # Make note visible to reviewers, senior reviewers and staff.
        comm_perms = ('reviewer', 'senior_reviewer', 'staff')
        create_comm_thread(addon=addon,
                           version=version,
                           action='comment',
                           perms=comm_perms,
                           comments=f.data['approvalnotes'],
                           profile=request.amo_user)

        messages.success(request, _('Version successfully edited.'))
        return redirect(addon.get_dev_url('versions'))

    context = {'addon': addon, 'version': version, 'form': form}

    if show_features:
        context.update({
            'appfeatures_form':
            appfeatures_form,
            'appfeatures':
            appfeatures,
            'feature_list': [unicode(f) for f in appfeatures.to_list()]
        })

    return jingo.render(request, 'developers/apps/version_edit.html', context)
コード例 #4
0
ファイル: views.py プロジェクト: j-barron/zamboni
def version_edit(request, addon_id, addon, version_id):
    show_features = addon.is_packaged
    formdata = request.POST if request.method == 'POST' else None
    version = get_object_or_404(Version, pk=version_id, addon=addon)
    version.addon = addon  # Avoid extra useless query.
    form = AppVersionForm(formdata, instance=version)
    all_forms = [form]

    if show_features:
        appfeatures = version.features
        appfeatures_form = AppFeaturesForm(request.POST or None,
                                           instance=appfeatures)
        all_forms.append(appfeatures_form)

    if request.method == 'POST' and all(f.is_valid() for f in all_forms):
        [f.save() for f in all_forms]

        if f.data.get('approvalnotes'):
            create_comm_note(
                addon,
                version,
                request.user,
                f.data['approvalnotes'],
                note_type=comm.DEVELOPER_VERSION_NOTE_FOR_REVIEWER)

        messages.success(request, _('Version successfully edited.'))
        return redirect(addon.get_dev_url('versions'))

    context = {'addon': addon, 'version': version, 'form': form}

    if show_features:
        context.update({
            'appfeatures_form':
            appfeatures_form,
            'appfeatures':
            appfeatures,
            'feature_list': [unicode(f) for f in appfeatures.to_list()]
        })

    return render(request, 'developers/apps/version_edit.html', context)
コード例 #5
0
ファイル: views.py プロジェクト: j-barron/zamboni
def _review(request, addon, version):

    if (not settings.ALLOW_SELF_REVIEWS
            and not acl.action_allowed(request, 'Admin', '%')
            and addon.has_author(request.user)):
        messages.warning(request, _('Self-reviews are not allowed.'))
        return redirect(reverse('reviewers.home'))

    if (addon.status == amo.STATUS_BLOCKED
            and not acl.action_allowed(request, 'Apps', 'ReviewEscalated')):
        messages.warning(
            request, _('Only senior reviewers can review blocklisted apps.'))
        return redirect(reverse('reviewers.home'))

    attachment_formset = CommAttachmentFormSet(data=request.POST or None,
                                               files=request.FILES or None,
                                               prefix='attachment')
    form = forms.get_review_form(data=request.POST or None,
                                 files=request.FILES or None,
                                 request=request,
                                 addon=addon,
                                 version=version,
                                 attachment_formset=attachment_formset)
    postdata = request.POST if request.method == 'POST' else None
    all_forms = [form, attachment_formset]

    if version:
        features_list = [unicode(f) for f in version.features.to_list()]
        appfeatures_form = AppFeaturesForm(data=postdata,
                                           instance=version.features)
        all_forms.append(appfeatures_form)
    else:
        appfeatures_form = None
        features_list = None

    queue_type = form.helper.review_type
    redirect_url = reverse('reviewers.apps.queue_%s' % queue_type)
    is_admin = acl.action_allowed(request, 'Apps', 'Edit')

    if request.method == 'POST' and all(f.is_valid() for f in all_forms):

        old_types = set(o.id for o in addon.device_types)
        new_types = set(form.cleaned_data.get('device_override'))

        old_features = set(features_list)
        new_features = set(
            unicode(f) for f in appfeatures_form.instance.to_list())

        if form.cleaned_data.get('action') == 'public':
            if old_types != new_types:
                # The reviewer overrode the device types. We need to not
                # publish this app immediately.
                if addon.publish_type == amo.PUBLISH_IMMEDIATE:
                    addon.update(publish_type=amo.PUBLISH_PRIVATE)

                # And update the device types to what the reviewer set.
                AddonDeviceType.objects.filter(addon=addon).delete()
                for device in form.cleaned_data.get('device_override'):
                    addon.addondevicetype_set.create(device_type=device)

                # Log that the reviewer changed the device types.
                added_devices = new_types - old_types
                removed_devices = old_types - new_types
                msg = _(
                    u'Device(s) changed by '
                    u'reviewer: {0}'
                ).format(', '.join([
                    _(u'Added {0}').format(unicode(amo.DEVICE_TYPES[d].name))
                    for d in added_devices
                ] + [
                    _(u'Removed {0}').format(unicode(amo.DEVICE_TYPES[d].name))
                    for d in removed_devices
                ]))

                log_reviewer_action(addon, request.user, msg,
                                    amo.LOG.REVIEW_DEVICE_OVERRIDE)

            if old_features != new_features:
                # The reviewer overrode the requirements. We need to not
                # publish this app immediately.
                if addon.publish_type == amo.PUBLISH_IMMEDIATE:
                    addon.update(publish_type=amo.PUBLISH_PRIVATE)

                appfeatures_form.save(mark_for_rereview=False)

                # Log that the reviewer changed the minimum requirements.
                added_features = new_features - old_features
                removed_features = old_features - new_features

                fmt = ', '.join(
                    [_(u'Added {0}').format(f) for f in added_features] +
                    [_(u'Removed {0}').format(f) for f in removed_features])
                # L10n: {0} is the list of requirements changes.
                msg = _(u'Requirements changed by reviewer: {0}').format(fmt)

                log_reviewer_action(addon, request.user, msg,
                                    amo.LOG.REVIEW_FEATURES_OVERRIDE)

        score = form.helper.process()

        if form.cleaned_data.get('notify'):
            # TODO: bug 741679 for implementing notifications in Marketplace.
            EditorSubscription.objects.get_or_create(user=request.user,
                                                     addon=addon)

        is_tarako = form.cleaned_data.get('is_tarako', False)
        if is_tarako:
            Tag(tag_text='tarako').save_tag(addon)
        else:
            Tag(tag_text='tarako').remove_tag(addon)

        # Success message.
        if score:
            score = ReviewerScore.objects.filter(user=request.user)[0]
            # L10N: {0} is the type of review. {1} is the points they earned.
            #       {2} is the points they now have total.
            success = _(
                u'"{0}" successfully processed (+{1} points, {2} total).'.
                format(unicode(amo.REVIEWED_CHOICES[score.note_key]),
                       score.score, ReviewerScore.get_total(request.user)))
        else:
            success = _('Review successfully processed.')
        messages.success(request, success)

        return redirect(redirect_url)

    canned = CannedResponse.objects.all()
    actions = form.helper.actions.items()

    try:
        if not version:
            raise Version.DoesNotExist
        show_diff = (addon.versions.exclude(id=version.id).filter(
            files__isnull=False,
            created__lt=version.created,
            files__status=amo.STATUS_PUBLIC).latest())
    except Version.DoesNotExist:
        show_diff = None

    # The actions we should show a minimal form from.
    actions_minimal = [k for (k, a) in actions if not a.get('minimal')]

    # We only allow the user to check/uncheck files for "pending"
    allow_unchecking_files = form.helper.review_type == "pending"

    versions = (Version.with_deleted.filter(
        addon=addon).order_by('-created').transform(
            Version.transformer_activity).transform(Version.transformer))

    product_attrs = {
        'product':
        json.dumps(product_as_dict(request, addon, False, 'reviewer'),
                   cls=JSONEncoder),
        'manifest_url':
        addon.manifest_url,
    }

    pager = paginate(request, versions, 10)

    num_pages = pager.paginator.num_pages
    count = pager.paginator.count

    ctx = context(request,
                  version=version,
                  product=addon,
                  pager=pager,
                  num_pages=num_pages,
                  count=count,
                  form=form,
                  canned=canned,
                  is_admin=is_admin,
                  status_types=amo.STATUS_CHOICES,
                  show_diff=show_diff,
                  allow_unchecking_files=allow_unchecking_files,
                  actions=actions,
                  actions_minimal=actions_minimal,
                  tab=queue_type,
                  product_attrs=product_attrs,
                  attachment_formset=attachment_formset,
                  appfeatures_form=appfeatures_form)

    if features_list is not None:
        ctx['feature_list'] = features_list

    return render(request, 'reviewers/review.html', ctx)
コード例 #6
0
ファイル: views.py プロジェクト: j-barron/zamboni
def addons_section(request, addon_id, addon, section, editable=False):
    models = {
        'basic': AppFormBasic,
        'media': AppFormMedia,
        'details': AppFormDetails,
        'support': AppFormSupport,
        'technical': AppFormTechnical,
        'admin': forms.AdminSettingsForm
    }

    is_dev = acl.check_addon_ownership(request, addon, dev=True)

    if section not in models:
        raise http.Http404()

    version = addon.current_version or addon.latest_version

    tags, previews, restricted_tags = [], [], []
    cat_form = appfeatures = appfeatures_form = version_form = None
    formdata = request.POST if request.method == 'POST' else None

    # Permissions checks.
    # Only app owners can edit any of the details of their apps.
    # Users with 'Apps:Configure' can edit the admin settings.
    if (section != 'admin' and not is_dev) or (
            section == 'admin'
            and not acl.action_allowed(request, 'Apps', 'Configure')
            and not acl.action_allowed(request, 'Apps', 'ViewConfiguration')):
        raise PermissionDenied

    if section == 'basic':
        cat_form = CategoryForm(formdata, product=addon, request=request)
        # Only show/use the release notes form for hosted apps, packaged apps
        # can do that from the version edit page.
        if not addon.is_packaged:
            version_form = AppVersionForm(formdata, instance=version)

    elif section == 'media':
        previews = PreviewFormSet(request.POST or None,
                                  prefix='files',
                                  queryset=addon.get_previews())

    elif section == 'technical':
        # Only show/use the features form for hosted apps, packaged apps
        # can do that from the version edit page.
        if not addon.is_packaged:
            appfeatures = version.features
            appfeatures_form = AppFeaturesForm(formdata, instance=appfeatures)

    elif section == 'admin':
        tags = addon.tags.not_blacklisted().values_list('tag_text', flat=True)
        restricted_tags = addon.tags.filter(restricted=True)

    # Get the slug before the form alters it to the form data.
    valid_slug = addon.app_slug
    if editable:
        if request.method == 'POST':

            if (section == 'admin'
                    and not acl.action_allowed(request, 'Apps', 'Configure')):
                raise PermissionDenied

            form = models[section](formdata,
                                   request.FILES,
                                   instance=addon,
                                   version=version,
                                   request=request)

            all_forms = [form, previews]
            for additional_form in (appfeatures_form, cat_form, version_form):
                if additional_form:
                    all_forms.append(additional_form)

            if all(not f or f.is_valid() for f in all_forms):
                if cat_form:
                    cat_form.save()

                addon = form.save(addon)

                if appfeatures_form:
                    appfeatures_form.save()

                if version_form:
                    # We are re-using version_form without displaying all its
                    # fields, so we need to override the boolean fields,
                    # otherwise they'd be considered empty and therefore False.
                    version_form.cleaned_data['publish_immediately'] = (
                        version_form.fields['publish_immediately'].initial)
                    version_form.save()

                if 'manifest_url' in form.changed_data:
                    addon.update(
                        app_domain=addon.domain_from_url(addon.manifest_url))
                    update_manifests([addon.pk])

                if previews:
                    for preview in previews.forms:
                        preview.save(addon)

                editable = False
                if section == 'media':
                    amo.log(amo.LOG.CHANGE_ICON, addon)
                else:
                    amo.log(amo.LOG.EDIT_PROPERTIES, addon)

                valid_slug = addon.app_slug
        else:
            form = models[section](instance=addon,
                                   version=version,
                                   request=request)
    else:
        form = False

    data = {
        'addon': addon,
        'version': version,
        'form': form,
        'editable': editable,
        'tags': tags,
        'restricted_tags': restricted_tags,
        'cat_form': cat_form,
        'version_form': version_form,
        'preview_form': previews,
        'valid_slug': valid_slug,
    }

    if appfeatures_form and appfeatures:
        data.update({
            'appfeatures': appfeatures,
            'feature_list': [unicode(f) for f in appfeatures.to_list()],
            'appfeatures_form': appfeatures_form
        })

    return render(request, 'developers/apps/edit/%s.html' % section, data)
コード例 #7
0
ファイル: views.py プロジェクト: sunbiz/zamboni
def _review(request, addon, version):

    if (not settings.ALLOW_SELF_REVIEWS and
        not acl.action_allowed(request, 'Admin', '%') and
        addon.has_author(request.amo_user)):
        messages.warning(request, _('Self-reviews are not allowed.'))
        return redirect(reverse('reviewers.home'))

    if (addon.status == amo.STATUS_BLOCKED and
        not acl.action_allowed(request, 'Apps', 'ReviewEscalated')):
        messages.warning(
            request, _('Only senior reviewers can review blocklisted apps.'))
        return redirect(reverse('reviewers.home'))

    attachment_formset = forms.AttachmentFormSet(data=request.POST or None,
                                                 files=request.FILES or None,
                                                 prefix='attachment')
    form = forms.get_review_form(data=request.POST or None,
                                 files=request.FILES or None, request=request,
                                 addon=addon, version=version,
                                 attachment_formset=attachment_formset)
    postdata = request.POST if request.method == 'POST' else None
    all_forms = [form, attachment_formset]

    if waffle.switch_is_active('buchets') and version:
        features_list = [unicode(f) for f in version.features.to_list()]
        appfeatures_form = AppFeaturesForm(data=postdata,
                                           instance=version.features)
        all_forms.append(appfeatures_form)
    else:
        appfeatures_form = None
        features_list = None

    queue_type = form.helper.review_type
    redirect_url = reverse('reviewers.apps.queue_%s' % queue_type)
    is_admin = acl.action_allowed(request, 'Addons', 'Edit')

    if request.method == 'POST' and all(f.is_valid() for f in all_forms):

        old_types = set(o.id for o in addon.device_types)
        new_types = set(form.cleaned_data.get('device_override'))

        if waffle.switch_is_active('buchets'):
            old_features = set(features_list)
            new_features = set(unicode(f) for f
                               in appfeatures_form.instance.to_list())

        if form.cleaned_data.get('action') == 'public':
            if old_types != new_types:
                # The reviewer overrode the device types. We need to not
                # publish this app immediately.
                if addon.make_public == amo.PUBLIC_IMMEDIATELY:
                    addon.update(make_public=amo.PUBLIC_WAIT)

                # And update the device types to what the reviewer set.
                AddonDeviceType.objects.filter(addon=addon).delete()
                for device in form.cleaned_data.get('device_override'):
                    addon.addondevicetype_set.create(device_type=device)

                # Log that the reviewer changed the device types.
                added_devices = new_types - old_types
                removed_devices = old_types - new_types
                msg = _(u'Device(s) changed by '
                         'reviewer: {0}').format(', '.join(
                    [_(u'Added {0}').format(unicode(amo.DEVICE_TYPES[d].name))
                     for d in added_devices] +
                    [_(u'Removed {0}').format(
                     unicode(amo.DEVICE_TYPES[d].name))
                     for d in removed_devices]))
                amo.log(amo.LOG.REVIEW_DEVICE_OVERRIDE, addon,
                        addon.current_version, details={'comments': msg})

            if (waffle.switch_is_active('buchets') and
                 old_features != new_features):
                # The reviewer overrode the requirements. We need to not
                # publish this app immediately.
                if addon.make_public == amo.PUBLIC_IMMEDIATELY:
                    addon.update(make_public=amo.PUBLIC_WAIT)

                appfeatures_form.save(mark_for_rereview=False)

                # Log that the reviewer changed the minimum requirements.
                added_features = new_features - old_features
                removed_features = old_features - new_features

                fmt = ', '.join(
                      [_(u'Added {0}').format(f) for f in added_features] +
                      [_(u'Removed {0}').format(f) for f in removed_features])
                # L10n: {0} is the list of requirements changes.
                msg = _(u'Requirements changed by reviewer: {0}').format(fmt)
                amo.log(amo.LOG.REVIEW_FEATURES_OVERRIDE, addon,
                        addon.current_version, details={'comments': msg})

        form.helper.process()

        if form.cleaned_data.get('notify'):
            EditorSubscription.objects.get_or_create(user=request.amo_user,
                                                     addon=addon)

        messages.success(request, _('Review successfully processed.'))
        return redirect(redirect_url)

    canned = AppCannedResponse.objects.all()
    actions = form.helper.actions.items()

    try:
        if not version:
            raise Version.DoesNotExist
        show_diff = (addon.versions.exclude(id=version.id)
                                   .filter(files__isnull=False,
                                           created__lt=version.created,
                                           files__status=amo.STATUS_PUBLIC)
                                   .latest())
    except Version.DoesNotExist:
        show_diff = None

    # The actions we should show a minimal form from.
    actions_minimal = [k for (k, a) in actions if not a.get('minimal')]

    # We only allow the user to check/uncheck files for "pending"
    allow_unchecking_files = form.helper.review_type == "pending"

    versions = (Version.with_deleted.filter(addon=addon)
                                    .order_by('-created')
                                    .transform(Version.transformer_activity)
                                    .transform(Version.transformer))

    product_attrs = {
        'product': json.dumps(
            product_as_dict(request, addon, False, 'reviewer'),
            cls=JSONEncoder),
        'manifest_url': addon.manifest_url,
    }

    pager = paginate(request, versions, 10)

    num_pages = pager.paginator.num_pages
    count = pager.paginator.count

    ctx = context(request, version=version, product=addon, pager=pager,
                  num_pages=num_pages, count=count,
                  flags=Review.objects.filter(addon=addon, flag=True),
                  form=form, canned=canned, is_admin=is_admin,
                  status_types=amo.STATUS_CHOICES, show_diff=show_diff,
                  allow_unchecking_files=allow_unchecking_files,
                  actions=actions, actions_minimal=actions_minimal,
                  tab=queue_type, product_attrs=product_attrs,
                  attachment_formset=attachment_formset,
                  appfeatures_form=appfeatures_form,
                  default_visibility=DEFAULT_ACTION_VISIBILITY)

    if features_list is not None:
        ctx['feature_list'] = features_list

    return jingo.render(request, 'reviewers/review.html', ctx)
コード例 #8
0
def addons_section(request,
                   addon_id,
                   addon,
                   section,
                   editable=False,
                   webapp=False):
    basic = AppFormBasic if webapp else addon_forms.AddonFormBasic
    models = {
        'basic': basic,
        'media': AppFormMedia,
        'details': AppFormDetails,
        'support': AppFormSupport,
        'technical': AppFormTechnical,
        'admin': forms.AdminSettingsForm
    }

    is_dev = acl.check_addon_ownership(request, addon, dev=True)

    if section not in models:
        raise http.Http404()

    version = addon.current_version or addon.latest_version

    tags, previews, restricted_tags = [], [], []
    cat_form = appfeatures = appfeatures_form = None

    # Permissions checks.
    # Only app owners can edit any of the details of their apps.
    # Users with 'Apps:Configure' can edit the admin settings.
    if (section != 'admin' and not is_dev) or (
            section == 'admin'
            and not acl.action_allowed(request, 'Apps', 'Configure')
            and not acl.action_allowed(request, 'Apps', 'ViewConfiguration')):
        raise PermissionDenied

    if section == 'basic':
        cat_form = CategoryForm(request.POST or None,
                                product=addon,
                                request=request)

    elif section == 'media':
        previews = PreviewFormSet(request.POST or None,
                                  prefix='files',
                                  queryset=addon.get_previews())

    elif section == 'technical':
        # Only show the list of features if app isn't packaged.
        if (waffle.switch_is_active('buchets') and not addon.is_packaged
                and section == 'technical'):
            appfeatures = version.features
            formdata = request.POST if request.method == 'POST' else None
            appfeatures_form = AppFeaturesForm(formdata, instance=appfeatures)

    elif section == 'admin':
        tags = addon.tags.not_blacklisted().values_list('tag_text', flat=True)
        restricted_tags = addon.tags.filter(restricted=True)

    # Get the slug before the form alters it to the form data.
    valid_slug = addon.app_slug
    if editable:
        if request.method == 'POST':

            if (section == 'admin'
                    and not acl.action_allowed(request, 'Apps', 'Configure')):
                raise PermissionDenied

            form = models[section](request.POST,
                                   request.FILES,
                                   instance=addon,
                                   request=request)

            all_forms = [form, previews]
            if appfeatures_form:
                all_forms.append(appfeatures_form)
            if cat_form:
                all_forms.append(cat_form)
            if all(not f or f.is_valid() for f in all_forms):
                if cat_form:
                    cat_form.save()

                addon = form.save(addon)

                if appfeatures_form:
                    appfeatures_form.save()

                if 'manifest_url' in form.changed_data:
                    addon.update(
                        app_domain=addon.domain_from_url(addon.manifest_url))
                    update_manifests([addon.pk])

                if previews:
                    for preview in previews.forms:
                        preview.save(addon)

                editable = False
                if section == 'media':
                    amo.log(amo.LOG.CHANGE_ICON, addon)
                else:
                    amo.log(amo.LOG.EDIT_PROPERTIES, addon)

                valid_slug = addon.app_slug
        else:
            form = models[section](instance=addon, request=request)
    else:
        form = False

    data = {
        'addon': addon,
        'webapp': webapp,
        'version': version,
        'form': form,
        'editable': editable,
        'tags': tags,
        'restricted_tags': restricted_tags,
        'cat_form': cat_form,
        'preview_form': previews,
        'valid_slug': valid_slug,
    }

    if appfeatures_form and appfeatures:
        data.update({
            'appfeatures': appfeatures,
            'feature_list': [unicode(f) for f in appfeatures.to_list()],
            'appfeatures_form': appfeatures_form
        })

    return jingo.render(request, 'developers/apps/edit/%s.html' % section,
                        data)