Esempio n. 1
0
    def process_reject(self):
        """
        Reject an app.
        Changes status to Rejected.
        Creates Rejection note.
        """
        # Hold onto the status before we change it.
        status = self.webapp.status

        self.set_files(mkt.STATUS_DISABLED, self.version.files.all(),
                       hide_disabled_file=True)
        # If this app is not packaged (packaged apps can have multiple
        # versions) or if there aren't other versions with already reviewed
        # files, reject the app also.
        if (not self.webapp.is_packaged or
            not self.webapp.versions.exclude(id=self.version.id)
                .filter(files__status__in=mkt.REVIEWED_STATUSES).exists()):
            self.set_webapp(status=mkt.STATUS_REJECTED)

        if self.in_escalate:
            EscalationQueue.objects.filter(webapp=self.webapp).delete()
        if self.in_rereview:
            RereviewQueue.objects.filter(webapp=self.webapp).delete()

        self.create_note(mkt.LOG.REJECT_VERSION)

        log.info(u'Making %s disabled' % self.webapp)

        # Assign reviewer incentive scores.
        return ReviewerScore.award_points(self.request.user, self.webapp,
                                          status, in_rereview=self.in_rereview)
Esempio n. 2
0
def hera(request):
    form = FlushForm(initial={'flushprefix': settings.SITE_URL})

    boxes = []
    configured = False  # Default to not showing the form.
    for i in settings.HERA:
        hera = get_hera(i)
        r = {'location': urlparse(i['LOCATION'])[1], 'stats': False}
        if hera:
            r['stats'] = hera.getGlobalCacheInfo()
            configured = True
        boxes.append(r)

    if not configured:
        messages.error(request, "Hera is not (or mis-)configured.")
        form = None

    if request.method == 'POST' and hera:
        form = FlushForm(request.POST)
        if form.is_valid():
            expressions = request.POST['flushlist'].splitlines()

            for url in expressions:
                num = flush_urls([url], request.POST['flushprefix'], True)
                msg = ("Flushed %d objects from front end cache for: %s"
                       % (len(num), url))
                log.info("[Hera] (user:%s) %s" % (request.user, msg))
                messages.success(request, msg)

    return jingo.render(request, 'zadmin/hera.html',
                        {'form': form, 'boxes': boxes})
Esempio n. 3
0
    def process_request(self, request):
        regions = mkt.regions.REGION_LOOKUP
        user_region = restofworld = mkt.regions.RESTOFWORLD

        if not getattr(request, 'API', False):
            request.REGION = restofworld
            mkt.regions.set_region(restofworld)
            return

        # Try 'region' in POST/GET data first, if it's not there try geoip.
        url_region = request.REQUEST.get('region')
        if url_region in regions:
            statsd.incr('z.regions.middleware.source.url')
            user_region = regions[url_region]
            log.info('Region {0} specified in URL; region set as {1}'
                     .format(url_region, user_region.slug))
        elif getattr(request, 'API_VERSION', None) == 1:
            # Fallback to GeoIP, but only for API version 1.
            statsd.incr('z.regions.middleware.source.geoip')
            user_region = self.region_from_request(request)
            log.info('Region not specified in URL; region set as {0}'
                     .format(user_region.slug))

        # Update the region on the user object if it changed.
        if (request.user.is_authenticated() and
                request.user.region != user_region.slug):
            request.user.region = user_region.slug
            request.user.save()

        # Persist the region on the request / local thread.
        self.store_region(request, user_region)
Esempio n. 4
0
def revision_add_attachment(request, pk):
    """Add attachment, download if necessary
    """
    revision = get_object_or_404(PackageRevision, pk=pk)
    if request.user.pk != revision.author.pk:
        log_msg = ("[security] Attempt to add attachment to package (%s) by "
                   "non-owner (%s)" % (revision.package, request.user))
        log.warning(log_msg)
        return HttpResponseForbidden(
            'You are not the author of this %s' % escape(
                revision.package.get_type_name()))
    url = request.POST.get('url', None)
    filename = request.POST.get('filename', None)
    if not filename or filename == "":
        log.error('Trying to create an attachment without name')
        return HttpResponseBadRequest('Path not found.')
    content = ''
    if url:
        log.info(('[%s] Preparing to download %s as an attachment of '
            'PackageRevision %d') % (filename, url, revision.pk))
        # validate url
        field = URLField(verify_exists=True)
        encoding = request.POST.get('force_contenttype', False)
        try:
            url = field.clean(url)
        except ValidationError, err:
            log.warning('[%s] Invalid url provided\n%s' % (url,
                '\n'.join(err.messages)))
            return HttpResponseBadRequest(("Loading attachment failed\n"
                "%s") % parse_validation_messages(err))
        except Exception, err:
            log.warning('[%s] Exception raised\n%s' % (url, str(err)))
            return HttpResponseBadRequest(str(err))
Esempio n. 5
0
def performance_add(request):
    """
    A wrapper around adding in performance data that is easier than
    using the piston API.
    """
    # Trigger OAuth.
    if not AMOOAuthAuthentication(two_legged=True).is_authenticated(request):
        return rc.FORBIDDEN

    form = PerformanceForm(request.POST)
    if not form.is_valid():
        return form.show_error()

    os, created = (PerformanceOSVersion
                        .objects.safer_get_or_create(**form.os_version))
    app, created = (PerformanceAppVersions
                        .objects.safer_get_or_create(**form.app_version))

    data = form.performance
    data.update({'osversion': os, 'appversion': app})

    # Look up on everything except the average time.
    result, created = Performance.objects.safer_get_or_create(**data)
    result.average = form.cleaned_data['average']
    result.save()

    log.info('Performance created for add-on: %s, %s' %
             (form.cleaned_data['addon_id'], form.cleaned_data['average']))
    return rc.ALL_OK
Esempio n. 6
0
def cleanup_validation_results():
    """Will remove all validation results.  Used when the validator is
    upgraded and results may no longer be relevant."""
    # With a large enough number of objects not using tracebacks
    all = FileValidation.objects.all()
    log.info('Removing %s old validation results.' % (all.count()))
    all.delete()
Esempio n. 7
0
def emailchange(request, user_id, token, hash):
    user = get_object_or_404(UserProfile, id=user_id)

    try:
        _uid, newemail = EmailResetCode.parse(token, hash)
    except ValueError:
        return http.HttpResponse(status=400)

    if _uid != user.id:
        # I'm calling this a warning because invalid hashes up to this point
        # could be any number of things, but this is a targeted attack from
        # one user account to another
        log.warning((u"[Tampering] Valid email reset code for UID (%s) "
                     "attempted to change email address for user (%s)")
                                                        % (_uid, user))
        return http.HttpResponse(status=400)

    user.email = newemail
    user.save()

    l = {'user': user, 'newemail': newemail}
    log.info(u"User (%(user)s) confirmed new email address (%(newemail)s)" % l)
    messages.success(request, _('Your email address was changed successfully'),
            _(u'From now on, please use {0} to log in.').format(newemail))

    return http.HttpResponseRedirect(reverse('users.edit'))
Esempio n. 8
0
    def process_reject(self):
        """
        Reject an app.
        Changes status to Rejected.
        Creates Rejection note/email.
        """
        # Hold onto the status before we change it.
        status = self.addon.status

        self.set_files(amo.STATUS_DISABLED, self.version.files.all(),
                       hide_disabled_file=True)
        # If this app is not packaged (packaged apps can have multiple
        # versions) or if there aren't other versions with already reviewed
        # files, reject the app also.
        if (not self.addon.is_packaged or
            not self.addon.versions.exclude(id=self.version.id)
                .filter(files__status__in=amo.REVIEWED_STATUSES).exists()):
            self.set_addon(status=amo.STATUS_REJECTED)

        if self.in_escalate:
            EscalationQueue.objects.filter(addon=self.addon).delete()
        if self.in_rereview:
            RereviewQueue.objects.filter(addon=self.addon).delete()

        self.create_note(amo.LOG.REJECT_VERSION)
        self.notify_email('pending_to_sandbox', u'Your submission has been rejected: %s')

        log.info(u'Making %s disabled' % self.addon)

        # Assign reviewer incentive scores.
        return ReviewerScore.award_points(self.request.amo_user, self.addon,
                                          status, in_rereview=self.in_rereview)
Esempio n. 9
0
def cleanup_extracted_file():
    log.info('Removing extracted files for file viewer.')
    root = os.path.join(settings.TMP_PATH, 'file_viewer')
    # Local storage uses local time for file modification. S3 uses UTC time.
    now = datetime.utcnow if storage_is_remote() else datetime.now
    for path in private_storage.listdir(root)[0]:
        full = os.path.join(root, path)
        age = now() - private_storage.modified_time(
            os.path.join(full, 'manifest.webapp'))
        if age.total_seconds() > (60 * 60):
            log.debug('Removing extracted files: %s, %dsecs old.' %
                      (full, age.total_seconds()))
            for subroot, dirs, files in walk_storage(full):
                for f in files:
                    private_storage.delete(os.path.join(subroot, f))
            # Nuke out the file and diff caches when the file gets removed.
            id = os.path.basename(path)
            try:
                int(id)
            except ValueError:
                continue

            key = hashlib.md5()
            key.update(str(id))
            cache.delete('%s:memoize:%s:%s' % (settings.CACHE_PREFIX,
                                               'file-viewer', key.hexdigest()))
Esempio n. 10
0
def edit(request):
    webapp = settings.APP_PREVIEW
    # Don't use request.amo_user since it has too much caching.
    amouser = UserProfile.objects.get(pk=request.user.id)
    if request.method == 'POST':
        # ModelForm alters the instance you pass in.  We need to keep a copy
        # around in case we need to use it below (to email the user)
        original_email = amouser.email
        form = forms.UserEditForm(request.POST, request.FILES, request=request,
                                  instance=amouser, webapp=webapp)
        if form.is_valid():
            messages.success(request, _('Profile Updated'))
            if amouser.email != original_email:
                # Temporarily block email changes.
                if settings.APP_PREVIEW:
                    messages.error(request, 'Error',
                                   'You cannot change your email on the '
                                   'developer preview site.')
                    return jingo.render(request, 'users/edit.html',
                                        {'form': form, 'amouser': amouser})

                l = {'user': amouser,
                     'mail1': original_email,
                     'mail2': amouser.email}
                log.info(u"User (%(user)s) has requested email change from"
                          "(%(mail1)s) to (%(mail2)s)" % l)
                messages.info(request, _('Email Confirmation Sent'),
                    _(u'An email has been sent to {0} to confirm your new '
                       'email address. For the change to take effect, you '
                       'need to click on the link provided in this email. '
                       'Until then, you can keep logging in with your '
                       'current email address.').format(amouser.email))

                domain = settings.DOMAIN
                token, hash = EmailResetCode.create(amouser.id, amouser.email)
                url = "%s%s" % (settings.SITE_URL,
                                reverse('users.emailchange', args=[amouser.id,
                                                                token, hash]))
                t = loader.get_template('users/email/emailchange.ltxt')
                c = {'domain': domain, 'url': url}
                send_mail(_('Please confirm your email address '
                            'change at %s' % domain),
                    t.render(Context(c)), None, [amouser.email],
                    use_blacklist=False, real_email=True)

                # Reset the original email back.  We aren't changing their
                # address until they confirm the new one
                amouser.email = original_email
            form.save()
            return redirect('users.edit')
        else:

            messages.error(request, _('Errors Found'),
                                    _('There were errors in the changes '
                                      'you made. Please correct them and '
                                      'resubmit.'))
    else:
        form = forms.UserEditForm(instance=amouser, webapp=webapp)
    return jingo.render(request, 'users/edit.html',
                        {'form': form, 'amouser': amouser, 'webapp': webapp})
Esempio n. 11
0
    def notify_email(self, template, subject, fresh_thread=False):
        """Notify the authors that their app has been reviewed."""
        if waffle.switch_is_active('comm-dashboard'):
            # Communication dashboard uses send_mail_comm.
            return

        data = self.data.copy()
        data.update(self.get_context_data())
        data['tested'] = ''
        dt, br = data.get('device_types'), data.get('browsers')
        if dt and br:
            data['tested'] = 'Tested on %s with %s' % (dt, br)
        elif dt and not br:
            data['tested'] = 'Tested on %s' % dt
        elif not dt and br:
            data['tested'] = 'Tested with %s' % br

        emails = list(self.addon.authors.values_list('email', flat=True))
        cc_email = self.addon.get_mozilla_contacts()

        log.info(u'Sending email for %s' % self.addon)
        send_mail(subject % data['name'],
                  'reviewers/emails/decisions/%s.txt' % template, data,
                  emails, perm_setting='app_reviewed', cc=cc_email,
                  attachments=self.get_attachments())
Esempio n. 12
0
def index_collection_counts(ids, **kw):
    index = kw.pop('index', None)
    indices = get_indices(index)

    es = amo.search.get_es()
    qs = CollectionCount.objects.filter(collection__in=ids)
    if qs:
        log.info('Indexing %s addon collection counts: %s'
                 % (qs.count(), qs[0].date))
    try:
        for collection_count in qs:
            collection = collection_count.collection_id
            key = '%s-%s' % (collection, collection_count.date)
            filters = dict(collection=collection,
                           date=collection_count.date)
            data = search.extract_addon_collection(
                collection_count,
                AddonCollectionCount.objects.filter(**filters),
                CollectionStats.objects.filter(**filters))
            for index in indices:
                CollectionCount.index(data, bulk=True, id=key, index=index)
        es.flush_bulk(forced=True)
    except Exception, exc:
        index_collection_counts.retry(args=[ids], exc=exc)
        raise
Esempio n. 13
0
    def _process_private(self):
        """Make an app private."""
        if self.addon.has_incomplete_status():
            # Failsafe.
            return

        self.addon.sign_if_packaged(self.version.pk)

        # If there are no prior PUBLIC versions we set the file status to
        # PUBLIC no matter what ``publish_type`` was chosen since at least one
        # version needs to be PUBLIC when an app is approved to set a
        # ``current_version``.
        if File.objects.filter(version__addon__pk=self.addon.pk,
                               status=mkt.STATUS_PUBLIC).count() == 0:
            self.set_files(mkt.STATUS_PUBLIC, self.version.files.all())
        else:
            self.set_files(mkt.STATUS_APPROVED, self.version.files.all())

        if self.addon.status not in (mkt.STATUS_PUBLIC, mkt.STATUS_UNLISTED):
            self.set_addon(status=mkt.STATUS_APPROVED,
                           highest_status=mkt.STATUS_APPROVED)
        self.set_reviewed()

        self.create_note(mkt.LOG.APPROVE_VERSION_PRIVATE)

        log.info(u'Making %s approved' % self.addon)
Esempio n. 14
0
 def reviewer_sign_file(self):
     """Sign the original file (`file_path`) with reviewer certs, then move
     the signed file to the reviewers-specific signed path
     (`reviewer_signed_file_path`) on private storage."""
     if not self.extension.uuid:
         raise SigningError('Need uuid to be set to sign')
     if not self.pk:
         raise SigningError('Need version pk to be set to sign')
     ids = json.dumps({
         # Reviewers get a unique 'id' so the reviewer installed add-on
         # won't conflict with the public add-on, and also so even multiple
         # versions of the same add-on can be installed side by side with
         # other versions.
         'id': 'reviewer-{guid}-{version_id}'.format(
             guid=self.extension.uuid, version_id=self.pk),
         'version': self.pk
     })
     with statsd.timer('extensions.sign_reviewer'):
         try:
             # This will read the file from self.file_path, generate a
             # reviewer signature and write the signed file to
             # self.reviewer_signed_file_path.
             sign_app(private_storage.open(self.file_path),
                      self.reviewer_signed_file_path, ids, reviewer=True)
         except SigningError:
             log.info(
                 '[ExtensionVersion:%s] Reviewer Signing failed' % self.pk)
             if private_storage.exists(self.reviewer_signed_file_path):
                 private_storage.delete(self.reviewer_signed_file_path)
             raise
Esempio n. 15
0
    def sign_file(self):
        """Sign the original file (`file_path`), then move signed extension
        file to the signed path (`signed_file_path`) on public storage. The
        original file remains on private storage.

        Return the signed file size."""
        if not self.extension.uuid:
            raise SigningError('Need uuid to be set to sign')
        if not self.pk:
            raise SigningError('Need version pk to be set to sign')

        ids = json.dumps({
            # 'id' needs to be an unique identifier not shared with anything
            # else (other extensions, langpacks, webapps...), but should not
            # change when there is an update.
            'id': self.extension.uuid,
            # 'version' should be an integer and should be monotonically
            # increasing.
            'version': self.pk
        })
        with statsd.timer('extensions.sign'):
            try:
                # This will read the file from self.file_path, generate a
                # signature and write the signed file to self.signed_file_path.
                sign_app(private_storage.open(self.file_path),
                         self.signed_file_path, ids)
            except SigningError:
                log.info('[ExtensionVersion:%s] Signing failed' % self.pk)
                self.remove_public_signed_file()  # Clean up.
                raise
        return public_storage.size(self.signed_file_path)
Esempio n. 16
0
    def from_upload(cls, upload, addon, platforms):
        data = utils.parse_addon(upload.path, addon)
        try:
            license = addon.versions.latest().license_id
        except Version.DoesNotExist:
            license = None
        v = cls.objects.create(addon=addon, version=data['version'],
                               license_id=license)
        log.info('New version: %r (%s) from %r' % (v, v.id, upload))
        # appversions
        AV = ApplicationsVersions
        for app in data.get('apps', []):
            AV(version=v, min=app.min, max=app.max,
               application_id=app.id).save()
        if addon.type == amo.ADDON_SEARCH:
            # Search extensions are always for all platforms.
            platforms = [Platform.objects.get(id=amo.PLATFORM_ALL.id)]
        else:
            platforms = cls._make_safe_platform_files(platforms)

        for platform in platforms:
            File.from_upload(upload, v, platform, parse_data=data)

        v.disable_old_files()
        # After the upload has been copied to all
        # platforms, remove the upload.
        upload.path.unlink()
        version_uploaded.send(sender=v)
        return v
Esempio n. 17
0
    def obj_create(self, bundle, request, **kwargs):
        with statsd.timer('auth.browserid.verify'):
            profile, msg = browserid_authenticate(
                request, bundle.data['assertion'],
                browserid_audience=bundle.data['audience'],
                is_native=bundle.data.get('is_native', False)
            )
        if profile is None:
            log.info('No profile: %s' % (msg or ''))
            raise http_error(http.HttpUnauthorized,
                             'No profile.')

        request.user, request.amo_user = profile.user, profile
        request.groups = profile.groups.all()

        # TODO: move this to the signal.
        profile.log_login_attempt(True)
        user_logged_in.send(sender=profile.user.__class__, request=request,
                            user=profile.user)
        bundle.data = {
            'error': None,
            'token': self.get_token(request.amo_user.email),
            'settings': {
                'display_name': request.amo_user.display_name,
                'email': request.amo_user.email,
            }
        }
        bundle.data.update(PermissionResource()
                           .dehydrate(Bundle(request=request)).data)
        return bundle
Esempio n. 18
0
def save_from_email_reply(reply_text):
    parser = CommEmailParser(reply_text)
    if hasattr(parser, "decode_error"):
        return False

    uuid = parser.get_uuid()

    if not uuid:
        return False
    try:
        tok = CommunicationThreadToken.objects.get(uuid=uuid)
    except CommunicationThreadToken.DoesNotExist:
        log.error("An email was skipped with non-existing uuid %s." % uuid)
        return False

    if user_has_perm_thread(tok.thread, tok.user) and tok.is_valid():
        t, note = create_comm_note(tok.thread.addon, tok.thread.version, tok.user, parser.get_body())
        log.info("A new note has been created (from %s using tokenid %s)." % (tok.user.id, uuid))
        return note
    elif tok.is_valid():
        log.error("%s did not have perms to reply to comm email thread %s." % (tok.user.email, tok.thread.id))
    else:
        log.error("%s tried to use an invalid comm token for thread %s." % (tok.user.email, tok.thread.id))

    return False
Esempio n. 19
0
    def wrapper(request, addon, *args, **kw):
        # If there is a 'token' in request.GET we either return 200 or 403.
        # Otherwise we treat it like a normal django view and redirect to a
        # login page or check for Apps:Review permissions.
        allowed = False
        token = request.GET.get('token')

        if token and Token.pop(token, data={'app_id': addon.id}):
            log.info('Token for app:%s was successfully used' % addon.id)
            allowed = True
        elif not token and not request.user.is_authenticated():
            return redirect_for_login(request)
        elif acl.action_allowed(request, 'Apps', 'Review'):
            allowed = True

        if allowed:
            if token:
                log.info('Token provided for app:%s and all was happy'
                         % addon.id)
            else:
                log.info('Apps:Review (no token) all happy for app:%s'
                         % addon.id)
            return f(request, addon, *args, **kw)
        else:
            if token:
                log.info('Token provided for app:%s but was not valid'
                         % addon.id)
            else:
                log.info('Apps:Review permissions not met for app:%s'
                         % addon.id)
            raise PermissionDenied
Esempio n. 20
0
    def post(self, request, *args, **kwargs):
        form = PrepareWebAppForm(request.DATA)
        if not form.is_valid():
            return Response(form.errors, status=status.HTTP_400_BAD_REQUEST)
        app = form.cleaned_data['app']

        region = getattr(request, 'REGION', None)
        if region and region.id not in app.get_price_region_ids():
            log.info('Region {0} is not in {1}'
                     .format(region.id, app.get_price_region_ids()))
            return Response('Payments are limited and flag not enabled',
                            status=status.HTTP_403_FORBIDDEN)

        if app.is_premium() and app.has_purchased(request._request.amo_user):
            log.info('Already purchased: {0}'.format(app.pk))
            return Response({'reason': u'Already purchased app.'},
                            status=status.HTTP_409_CONFLICT)

        app_pay_cef.log(request._request, 'Preparing JWT', 'preparing_jwt',
                        'Preparing JWT for: {0}'.format(app.pk), severity=3)

        token = get_product_jwt(
            WebAppProduct(app),
            client_data=ClientData.get_or_create(request._request),
            lang=request._request.LANG,
            region=request._request.REGION,
            source=request._request.REQUEST.get('src', ''),
            user=request._request.amo_user,
        )

        return Response(token, status=status.HTTP_201_CREATED)
Esempio n. 21
0
def send_mail_comm(note):
    """
    Email utility used globally by the Communication Dashboard to send emails.
    Given a note (its actions and permissions), recipients are determined and
    emails are sent to appropriate people.
    """
    from mkt.reviewers.utils import send_mail

    if not waffle.switch_is_active("comm-dashboard"):
        return

    recipients = get_recipients(note)
    name = note.thread.addon.name
    data = {"name": name, "sender": note.author.name, "comments": note.body, "thread_id": str(note.thread.id)}

    subject = {comm.ESCALATION: u"Escalated Review Requested: %s" % name}.get(
        note.note_type, u"Submission Update: %s" % name
    )

    log.info(u"Sending emails for %s" % note.thread.addon)
    for email, tok in recipients:
        reply_to = "{0}{1}@{2}".format(comm.REPLY_TO_PREFIX, tok, settings.POSTFIX_DOMAIN)
        send_mail(
            subject,
            "reviewers/emails/decisions/post.txt",
            data,
            [email],
            perm_setting="app_reviewed",
            reply_to=reply_to,
        )
Esempio n. 22
0
    def process_sandbox(self):
        """Set an addon back to sandbox."""

        # Hold onto the status before we change it.
        status = self.addon.status

        if (not self.is_upgrade or
            not self.addon.versions.exclude(id=self.version.id)
                          .filter(files__status__in=amo.REVIEWED_STATUSES)):
            self.set_addon(status=amo.STATUS_NULL)
        else:
            self.set_addon(status=amo.STATUS_LITE)

        self.set_files(amo.STATUS_DISABLED, self.version.files.all(),
                       hide_disabled_file=True)

        self.log_action(amo.LOG.REJECT_VERSION)
        self.notify_email('%s_to_sandbox' % self.review_type,
                          u'Mozilla Add-ons: %s %s Rejected')

        log.info(u'Making %s disabled' % (self.addon))
        log.info(u'Sending email for %s' % (self.addon))

        # Assign reviewer incentive scores.
        ReviewerScore.award_points(self.request.amo_user, self.addon, status)
Esempio n. 23
0
    def obj_update(self, bundle, request, **kwargs):
        data = bundle.data
        try:
            obj = self.get_object_list(bundle.request).get(**kwargs)
        except Webapp.DoesNotExist:
            raise ImmediateHttpResponse(response=http.HttpNotFound())

        if not AppOwnerAuthorization().is_authorized(request, object=obj):
            raise ImmediateHttpResponse(response=http.HttpUnauthorized())

        data['slug'] = data.get('slug', obj.app_slug)
        data.update(self.formset(data))
        data.update(self.devices(data))

        forms = [AppDetailsBasicForm(data, instance=obj, request=request),
                 DeviceTypeForm(data, addon=obj),
                 CategoryFormSet(data, addon=obj, request=request)]

        valid = all([f.is_valid() for f in forms])
        if not valid:
            raise ValidationError(self.form_errors(forms))

        forms[0].save(obj)
        forms[1].save(obj)
        forms[2].save()
        log.info('App updated: %s' % obj.pk)
        bundle.obj = obj
        return bundle
Esempio n. 24
0
def vouchify():
    """Synchronizes LDAP vouch info into database.

    This queries LDAP for users who's corresponding ``UserProfile`` has
    ``is_vouched`` as ``False``.  It then updates ``is_vouched`` and
    ``vouched_by`` with up-to-date data.
    """
    users = UserProfile.objects.filter(is_vouched=False)

    for user in users:
        person = user.get_ldap_person()
        if person and 'mozilliansVouchedBy' in person[1]:
            user.is_vouched = True
            voucher = (person[1]['mozilliansVouchedBy'][0].split(',')[0]
                                                          .split('=')[1])
            by = larper.get_user_by_uid(voucher)
            if by:
                email = by[1]['mail'][0]
                try:
                    user.vouched_by = (User.objects.get(email=email)
                                                   .get_profile())
                except User.DoesNotExist:
                    log.warning('No matching user for %s' % email)
                except UserProfile.DoesNotExist:
                    log.warning('No matching user_profile for %s' % email)
            user.save()
            log.info('Data copied for %s' % user.user.username)
        log.debug('%s is still unvouched... skipping' % user.user.username)
Esempio n. 25
0
    def obj_get(self, request=None, **kwargs):
        obj = super(AppResource, self).obj_get(request=request, **kwargs)
        if not AppOwnerAuthorization().is_authorized(request, object=obj):
            raise ImmediateHttpResponse(response=http.HttpUnauthorized())

        log.info('App retreived: %s' % obj.pk)
        return obj
Esempio n. 26
0
    def process_preliminary(self, auto_validation=False):
        """Set an addons files to preliminary."""
        # Sign addon.
        for file_ in self.files:
            sign_file(file_, settings.PRELIMINARY_SIGNING_SERVER)

        # Hold onto the status before we change it.
        status = self.addon.status

        self.set_files(amo.STATUS_LITE, self.files, copy_to_mirror=True)

        self.log_action(amo.LOG.PRELIMINARY_VERSION)
        template = u'%s_to_preliminary' % self.review_type
        subject = u'Mozilla Add-ons: %s %s Preliminary Reviewed'
        if not self.addon.is_listed:
            template = u'unlisted_to_reviewed'
            if auto_validation:
                template = u'unlisted_to_reviewed_auto'
            subject = u'Mozilla Add-ons: %s %s signed and ready to download'
        self.notify_email(template, subject)

        log.info(u'Making %s files %s preliminary' %
                 (self.addon, ', '.join([f.filename for f in self.files])))
        log.info(u'Sending email for %s' % (self.addon))

        if self.request and not auto_validation:
            # Assign reviewer incentive scores.
            ReviewerScore.award_points(self.request.user, self.addon, status)
Esempio n. 27
0
    def from_upload(cls, upload, addon, platforms, send_signal=True):
        data = utils.parse_addon(upload, addon)
        try:
            license = addon.versions.latest().license_id
        except Version.DoesNotExist:
            license = None
        max_len = cls._meta.get_field_by_name('_developer_name')[0].max_length
        developer = data.get('developer_name', '')[:max_len]
        v = cls.objects.create(addon=addon, version=data['version'],
                               license_id=license, _developer_name=developer)
        log.info('New version: %r (%s) from %r' % (v, v.id, upload))

        AV = ApplicationsVersions
        for app in data.get('apps', []):
            AV(version=v, min=app.min, max=app.max,
               application_id=app.id).save()
        if addon.type == amo.ADDON_SEARCH:
            # Search extensions are always for all platforms.
            platforms = [Platform.objects.get(id=amo.PLATFORM_ALL.id)]
        else:
            platforms = cls._make_safe_platform_files(platforms)

        for platform in platforms:
            File.from_upload(upload, v, platform, parse_data=data)

        v.disable_old_files()
        # After the upload has been copied to all platforms, remove the upload.
        storage.delete(upload.path)
        if send_signal:
            version_uploaded.send(sender=v)

        return v
Esempio n. 28
0
 def send_super_mail(self):
     self.log_action(amo.LOG.REQUEST_SUPER_REVIEW)
     log.info(u'Super review requested for %s' % (self.addon))
     send_mail('editors/emails/super_review.ltxt',
               u'Super review requested: %s' % (self.addon.name),
               [settings.SENIOR_EDITORS_EMAIL],
               Context(self.get_context_data()))
Esempio n. 29
0
    def process_public(self, auto_validation=False):
        """Set an addons files to public."""
        if self.review_type == 'preliminary':
            raise AssertionError('Preliminary addons cannot be made public.')

        # Sign addon.
        for file_ in self.files:
            sign_file(file_, settings.SIGNING_SERVER)

        # Hold onto the status before we change it.
        status = self.addon.status

        self.set_files(amo.STATUS_PUBLIC, self.files, copy_to_mirror=True)

        self.log_action(amo.LOG.APPROVE_VERSION)
        template = u'%s_to_public' % self.review_type
        subject = u'Mozilla Add-ons: %s %s Fully Reviewed'
        if not self.addon.is_listed:
            template = u'unlisted_to_reviewed'
            if auto_validation:
                template = u'unlisted_to_reviewed_auto'
            subject = u'Mozilla Add-ons: %s %s signed and ready to download'
        self.notify_email(template, subject)

        log.info(u'Making %s files %s public' %
                 (self.addon, ', '.join([f.filename for f in self.files])))
        log.info(u'Sending email for %s' % (self.addon))

        # Assign reviewer incentive scores.
        if self.request and not auto_validation:
            ReviewerScore.award_points(self.request.user, self.addon, status)
Esempio n. 30
0
    def process_preliminary(self):
        """Set an addon to preliminary."""
        # Hold onto the status before we change it.
        status = self.addon.status

        changes = {'status': amo.STATUS_LITE}
        if (self.addon.status in (amo.STATUS_PUBLIC,
                                  amo.STATUS_LITE_AND_NOMINATED)):
            changes['highest_status'] = amo.STATUS_LITE

        template = '%s_to_preliminary' % self.review_type
        if (self.review_type == 'preliminary' and
                self.addon.status == amo.STATUS_LITE_AND_NOMINATED):
            template = 'nominated_to_nominated'

        self.set_addon(**changes)
        self.set_files(amo.STATUS_LITE, self.version.files.all(),
                       copy_to_mirror=True)

        self.log_action(amo.LOG.PRELIMINARY_VERSION)
        self.notify_email(template,
                          u'Mozilla Add-ons: %s %s Preliminary Reviewed')

        log.info(u'Making %s preliminary' % (self.addon))
        log.info(u'Sending email for %s' % (self.addon))

        # Assign reviewer incentive scores.
        ReviewerScore.award_points(self.request.amo_user, self.addon, status)
Esempio n. 31
0
def _delete_logs(items, **kw):
    log.info('[%s@%s] Deleting logs' % (len(items), _delete_logs.rate_limit))
    ActivityLog.objects.filter(pk__in=items).exclude(
            action__in=amo.LOG_KEEP).delete()
Esempio n. 32
0
def delete_anonymous_collections(items, **kw):
    log.info('[%s@%s] Deleting anonymous collections' %
             (len(items), delete_anonymous_collections.rate_limit))
    Collection.objects.filter(type=amo.COLLECTION_ANONYMOUS,
                              pk__in=items).delete()
Esempio n. 33
0
def delete_stale_contributions(items, **kw):
    log.info('[%s@%s] Deleting stale contributions' %
             (len(items), delete_stale_contributions.rate_limit))
    Contribution.objects.filter(transaction_id__isnull=True,
                                pk__in=items).delete()
Esempio n. 34
0
def refresh_manifest(request, addon_id, addon, webapp=False):
    log.info('Manifest %s refreshed for %s' % (addon.manifest_url, addon))
    _update_manifest(addon_id, True, {})
    return http.HttpResponse(status=204)
Esempio n. 35
0
def status(request, addon_id, addon, webapp=False):
    form = forms.AppAppealForm(request.POST, product=addon)
    upload_form = NewWebappVersionForm(request.POST or None,
                                       is_packaged=True,
                                       addon=addon,
                                       request=request)

    if request.method == 'POST':
        if 'resubmit-app' in request.POST and form.is_valid():
            form.save()
            create_comm_note(addon,
                             addon.latest_version,
                             request.amo_user,
                             form.data['notes'],
                             note_type=comm.RESUBMISSION)
            if addon.vip_app:
                handle_vip(addon, addon.current_version, request.amo_user)

            messages.success(request, _('App successfully resubmitted.'))
            return redirect(addon.get_dev_url('versions'))

        elif 'upload-version' in request.POST and upload_form.is_valid():
            mobile_only = (addon.latest_version
                           and addon.latest_version.features.has_qhd)

            ver = Version.from_upload(upload_form.cleaned_data['upload'],
                                      addon, [amo.PLATFORM_ALL])

            # Update addon status now that the new version was saved.
            addon.update_status()

            res = run_validator(ver.all_files[0].file_path)
            validation_result = json.loads(res)

            # Set all detected features as True and save them.
            keys = [
                'has_%s' % feature.lower()
                for feature in validation_result['feature_profile']
            ]
            data = defaultdict.fromkeys(keys, True)

            # Set "Smartphone-Sized Displays" if it's a mobile-only app.
            qhd_devices = (set((amo.DEVICE_GAIA, )), set(
                (amo.DEVICE_MOBILE, )),
                           set((
                               amo.DEVICE_GAIA,
                               amo.DEVICE_MOBILE,
                           )))
            if set(addon.device_types) in qhd_devices or mobile_only:
                data['has_qhd'] = True

            # Update feature profile for this version.
            ver.features.update(**data)

            messages.success(request, _('New version successfully added.'))
            log.info('[Webapp:%s] New version created id=%s from upload: %s' %
                     (addon, ver.pk, upload_form.cleaned_data['upload']))

            if addon.vip_app:
                handle_vip(addon, ver, request.amo_user)

            return redirect(addon.get_dev_url('versions.edit', args=[ver.pk]))

    ctx = {
        'addon': addon,
        'webapp': webapp,
        'form': form,
        'upload_form': upload_form
    }

    # Used in the delete version modal.
    if addon.is_packaged:
        versions = addon.versions.values('id', 'version')
        version_strings = dict((v['id'], v) for v in versions)
        version_strings['num'] = len(versions)
        ctx['version_strings'] = json.dumps(version_strings)

    if addon.status == amo.STATUS_REJECTED:
        try:
            entry = (AppLog.objects.filter(
                addon=addon,
                activity_log__action=amo.LOG.REJECT_VERSION.id).order_by(
                    '-created'))[0]
        except IndexError:
            entry = None
        # This contains the rejection reason and timestamp.
        ctx['rejection'] = entry and entry.activity_log

    if waffle.switch_is_active('preload-apps'):
        test_plan = PreloadTestPlan.objects.filter(addon=addon,
                                                   status=amo.STATUS_PUBLIC)
        if test_plan.exists():
            test_plan = test_plan[0]
            if (test_plan.last_submission <
                    settings.PREINSTALL_TEST_PLAN_LATEST):
                ctx['outdated_test_plan'] = True
            ctx['next_step_suffix'] = 'submit'
        else:
            ctx['next_step_suffix'] = 'home'
        ctx['test_plan'] = test_plan

    return jingo.render(request, 'developers/apps/status.html', ctx)
Esempio n. 36
0
def ping(**kw):
    queue = kw['delivery_info']['routing_key']
    log.info('[1@None] Checking the %s queue' % queue)
    QueueCheck().set('pong', queue)
Esempio n. 37
0
def _activity_log_scrubber(items, **kw):
    log.info('[%s@%s] Deleting activity log items' %
             (len(items), _activity_log_scrubber.rate_limit))

    ActivityLog.objects.filter(id__in=items).delete()
Esempio n. 38
0
    log.debug('[copy: %s] Copying started from (%s)' % (revision_id, source))

    # save package
    try:
        package = source.package.copy(request.user)
    except IntegrityError, err:
        log.critical(("[copy: %s] Package copy failed") % revision_id)
        return HttpResponseForbidden('You already have a %s with that name' %
                                     escape(source.package.get_type_name()))

    # save revision with all dependencies
    source.save_new_revision(package)
    copied = source
    del source

    log.info('[copy: %s] Copied to %s, (%s)' %
             (revision_id, copied.pk, copied.full_name))
    return render_json(request,
                       "json/%s_copied.json" % package.get_type_name(),
                       {'revision': copied})


@login_required
def disable(request, pk):
    """
    Disable Package and return confirmation
    """
    package = get_object_or_404(Package, pk=pk)
    if request.user.pk != package.author.pk:
        log_msg = 'User %s wanted to disable not his own Package %s.' % (
            request.user, pk)
        log.warning(log_msg)
Esempio n. 39
0
    pass


def get_uuid():
    return 'webpay:%s' % hashlib.md5(str(uuid.uuid4())).hexdigest()


def sign_webpay_jwt(data):
    return jwt.encode(data, settings.APP_PURCHASE_SECRET)


def parse_from_webpay(signed_jwt, ip):
    try:
        data = jwt.decode(signed_jwt.encode('ascii'),
                          settings.APP_PURCHASE_SECRET,
                          algorithms=settings.SUPPORTED_JWT_ALGORITHMS)
    except Exception, e:
        exc_type, exc_value, tb = sys.exc_info()
        log.info('Received invalid webpay postback from IP %s: %s' %
                 (ip or '(unknown)', e),
                 exc_info=True)
        raise InvalidSender(e), None, tb

    verify_claims(data)
    iss, aud, product_data, trans_id = verify_keys(
        data, ('iss', 'aud', 'request.productData', 'response.transactionID'))
    log.info('Received webpay postback JWT: iss:%s aud:%s '
             'trans_id:%s product_data:%s' %
             (iss, aud, trans_id, product_data))
    return data
Esempio n. 40
0
def transaction_refund(request, tx_uuid):
    contrib = get_object_or_404(Contribution,
                                uuid=tx_uuid,
                                type=mkt.CONTRIB_PURCHASE)
    refund_contribs = contrib.get_refund_contribs()
    refund_contrib = refund_contribs[0] if refund_contribs.exists() else None

    if refund_contrib:
        messages.error(request, _('A refund has already been processed.'))
        return redirect(reverse('lookup.transaction_summary', args=[tx_uuid]))

    form = TransactionRefundForm(request.POST)
    if not form.is_valid():
        return render(
            request, 'lookup/transaction_summary.html',
            dict({
                'uuid': tx_uuid,
                'tx_refund_form': form,
                'tx_form': TransactionSearchForm()
            }.items() + _transaction_summary(tx_uuid).items()))

    data = {
        'uuid': contrib.transaction_id,
        'manual': form.cleaned_data['manual']
    }
    if settings.BANGO_FAKE_REFUNDS:
        data['fake_response_status'] = {
            'responseCode': form.cleaned_data['fake']
        }

    try:
        res = client.api.bango.refund.post(data)
    except (HttpClientError, HttpServerError):
        # Either doing something not supposed to or Solitude had an issue.
        log.exception('Refund error: %s' % tx_uuid)
        messages.error(
            request,
            _('You cannot make a refund request for this transaction.'))
        return redirect(reverse('lookup.transaction_summary', args=[tx_uuid]))

    if res['status'] in [PENDING, COMPLETED]:
        # Create refund Contribution by cloning the payment Contribution.
        refund_contrib = Contribution.objects.get(id=contrib.id)
        refund_contrib.id = None
        refund_contrib.save()
        log.info('Creating refund transaction from: {0} '
                 'with transaction_id of: {1}'.format(contrib.id, res['uuid']))
        refund_contrib.update(
            type=mkt.CONTRIB_REFUND,
            related=contrib,
            uuid=str(uuid.uuid4()),
            amount=-refund_contrib.amount if refund_contrib.amount else None,
            transaction_id=res['uuid'])

    if res['status'] == PENDING:
        # Create pending Refund.
        refund_contrib.enqueue_refund(
            mkt.REFUND_PENDING,
            request.user,
            refund_reason=form.cleaned_data['refund_reason'])
        log.info('Refund pending: %s' % tx_uuid)
        messages.success(request,
                         _('Refund for this transaction now pending.'))
    elif res['status'] == COMPLETED:
        # Create approved Refund.
        refund_contrib.enqueue_refund(
            mkt.REFUND_APPROVED,
            request.user,
            refund_reason=form.cleaned_data['refund_reason'])
        log.info('Refund approved: %s' % tx_uuid)
        messages.success(
            request, _('Refund for this transaction successfully approved.'))
    elif res['status'] == FAILED:
        # Bango no like.
        log.error('Refund failed: %s' % tx_uuid)
        messages.error(request,
                       _('Refund request for this transaction failed.'))

    return redirect(reverse('lookup.transaction_summary', args=[tx_uuid]))
Esempio n. 41
0
def register(request):

    if settings.APP_PREVIEW and waffle.switch_is_active('browserid-login'):
        messages.error(request,
                       loc('Registrations must be through browserid.'))
        form = None
        raise http.Http404()

    elif request.user.is_authenticated():
        messages.info(request, _('You are already logged in to an account.'))
        form = None

    elif request.method == 'POST':

        form = forms.UserRegisterForm(request.POST)
        mkt_user = UserProfile.objects.filter(email=form.data['email'],
                                              password='')
        if form.is_valid():
            try:
                u = form.save(commit=False)
                u.set_password(form.cleaned_data['password'])
                u.generate_confirmationcode()
                u.save()
                u.create_django_user()
                log.info(u'Registered new account for user (%s)', u)
                log_cef('New Account',
                        5,
                        request,
                        username=u.username,
                        signature='AUTHNOTICE',
                        msg='User created a new account')

                u.email_confirmation_code()

                msg = _('Congratulations! Your user account was '
                        'successfully created.')
                messages.success(request, msg)

                msg = _(u'An email has been sent to your address {0} to '
                        'confirm your account. Before you can log in, you '
                        'have to activate your account by clicking on the '
                        'link provided in this email.').format(u.email)
                messages.info(request, _('Confirmation Email Sent'), msg)

            except IntegrityError, e:
                # I was unable to reproduce this, but I suspect it happens
                # when they POST twice quickly and the slaves don't have the
                # new info yet (total guess).  Anyway, I'm assuming the
                # first one worked properly, so this is still a success
                # case to the end user so we just log it...
                log.error('Failed to register new user (%s): %s' % (u, e))

            return http.HttpResponseRedirect(reverse('users.login'))

        elif mkt_user.exists():
            # Handle BrowserID
            if (mkt_user.count() == 1
                    and mkt_user[0].source in amo.LOGIN_SOURCE_BROWSERIDS):
                messages.info(request, _('You already have an account.'))
                form = None
            else:
                f = PasswordResetForm()
                f.users_cache = [mkt_user[0]]
                f.save(use_https=request.is_secure(),
                       email_template_name='users/email/pwreset.ltxt',
                       request=request)
                return jingo.render(request, 'users/newpw_sent.html', {})
        else:
            messages.error(request, _('There are errors in this form'),
                           _('Please correct them and resubmit.'))
Esempio n. 42
0
def edit_privacy(request, collection, username, slug):
    collection.listed = not collection.listed
    collection.save()
    log.info(u'%s changed privacy on collection %s' %
             (request.amo_user, collection.id))
    return http.HttpResponseRedirect(collection.get_url_path())
Esempio n. 43
0
def edit(request):
    # Don't use request.amo_user since it has too much caching.
    amouser = UserProfile.objects.get(pk=request.user.id)
    if request.method == 'POST':
        # ModelForm alters the instance you pass in.  We need to keep a copy
        # around in case we need to use it below (to email the user)
        original_email = amouser.email
        form = forms.UserEditForm(request.POST,
                                  request.FILES,
                                  request=request,
                                  instance=amouser)
        if form.is_valid():
            messages.success(request, _('Profile Updated'))
            if amouser.email != original_email:
                # Temporarily block email changes.
                if settings.APP_PREVIEW:
                    messages.error(
                        request, 'Error',
                        'You cannot change your email on the '
                        'developer preview site.')
                    return jingo.render(request, 'users/edit.html', {
                        'form': form,
                        'amouser': amouser
                    })

                l = {
                    'user': amouser,
                    'mail1': original_email,
                    'mail2': amouser.email
                }
                log.info(u"User (%(user)s) has requested email change from "
                         "(%(mail1)s) to (%(mail2)s)" % l)
                messages.info(
                    request, _('Email Confirmation Sent'),
                    _(u'An email has been sent to {0} to confirm your new '
                      'email address. For the change to take effect, you '
                      'need to click on the link provided in this email. '
                      'Until then, you can keep logging in with your '
                      'current email address.').format(amouser.email))

                token, hash_ = EmailResetCode.create(amouser.id, amouser.email)
                url = '%s%s' % (settings.SITE_URL,
                                reverse('users.emailchange',
                                        args=[amouser.id, token, hash_]))
                t = loader.get_template('users/email/emailchange.ltxt')
                c = {'domain': settings.DOMAIN, 'url': url}
                send_mail(_('Please confirm your email address '
                            'change at %s' % settings.DOMAIN),
                          t.render(Context(c)),
                          None, [amouser.email],
                          use_blacklist=False,
                          real_email=True)

                # Reset the original email back.  We aren't changing their
                # address until they confirm the new one
                amouser.email = original_email
            form.save()
            return redirect('users.edit')
        else:

            messages.error(
                request, _('Errors Found'),
                _('There were errors in the changes '
                  'you made. Please correct them and '
                  'resubmit.'))
    else:
        form = forms.UserEditForm(instance=amouser)
    return jingo.render(request, 'users/edit.html', {
        'form': form,
        'amouser': amouser,
        'webapp': False
    })
Esempio n. 44
0
 def unrestrict(self):
     log.info(u'User (%s: <%s>) is being unrestricted.' %
              (self, self.email))
     GroupUser.objects.filter(user=self,
                              group__rules='Restricted:UGC').delete()
Esempio n. 45
0
 def destroy(self, request, *args, **kwargs):
     obj = self.get_object()
     obj.delete()
     log.info('Price %s deleted.' % (obj, ))
     return Response(status=204)
Esempio n. 46
0
def _login(request, template=None, data=None, dont_redirect=False):
    data = data or {}
    data['webapp'] = settings.APP_PREVIEW
    # In case we need it later.  See below.
    get_copy = request.GET.copy()

    if 'to' in request.GET:
        request = _clean_next_url(request)

    if request.user.is_authenticated():
        return http.HttpResponseRedirect(
            request.GET.get('to', settings.LOGIN_REDIRECT_URL))

    limited = getattr(request, 'limited', 'recaptcha_shown' in request.POST)
    user = None
    login_status = None
    if 'username' in request.POST:
        try:
            # We are doing all this before we try and validate the form.
            user = UserProfile.objects.get(email=request.POST['username'])
            limited = (
                (user.failed_login_attempts >= settings.LOGIN_RATELIMIT_USER)
                or limited)
            login_status = False
        except UserProfile.DoesNotExist:
            log_cef('Authentication Failure',
                    5,
                    request,
                    username=request.POST['username'],
                    signature='AUTHFAIL',
                    msg='The username was invalid')
            pass

    partial_form = partial(forms.AuthenticationForm, use_recaptcha=limited)
    r = auth.views.login(request,
                         template_name=template,
                         redirect_field_name='to',
                         authentication_form=partial_form,
                         extra_context=data)

    if isinstance(r, http.HttpResponseRedirect):
        # Django's auth.views.login has security checks to prevent someone from
        # redirecting to another domain.  Since we want to allow this in
        # certain cases, we have to make a new response object here to replace
        # the above.

        if 'domain' in request.GET:
            request.GET = get_copy
            request = _clean_next_url(request)
            r = http.HttpResponseRedirect(request.GET['to'])

        # Succsesful log in according to django.  Now we do our checks.  I do
        # the checks here instead of the form's clean() because I want to use
        # the messages framework and it's not available in the request there.
        user = request.user.get_profile()

        if user.deleted:
            logout(request)
            log.warning(u'Attempt to log in with deleted account (%s)' % user)
            messages.error(request, _('Wrong email address or password!'))
            data.update({'form': partial_form()})
            user.log_login_attempt(False)
            log_cef('Authentication Failure',
                    5,
                    request,
                    username=request.user,
                    signature='AUTHFAIL',
                    msg='Account is deactivated')
            return jingo.render(request, template, data)

        if user.confirmationcode:
            logout(request)
            log.info(u'Attempt to log in with unconfirmed account (%s)' % user)
            msg1 = _(u'A link to activate your user account was sent by email '
                     'to your address {0}. You have to click it before you '
                     'can log in.').format(user.email)
            url = "%s%s" % (settings.SITE_URL,
                            reverse('users.confirm.resend', args=[user.id]))
            msg2 = _('If you did not receive the confirmation email, make '
                     'sure your email service did not mark it as "junk '
                     'mail" or "spam". If you need to, you can have us '
                     '<a href="%s">resend the confirmation message</a> '
                     'to your email address mentioned above.') % url
            messages.error(request, _('Activation Email Sent'), msg1)
            messages.info(request,
                          _('Having Trouble?'),
                          msg2,
                          title_safe=True,
                          message_safe=True)
            data.update({'form': partial_form()})
            user.log_login_attempt(False)
            return jingo.render(request, template, data)

        rememberme = request.POST.get('rememberme', None)
        if rememberme:
            request.session.set_expiry(settings.SESSION_COOKIE_AGE)
            log.debug((u'User (%s) logged in successfully with '
                       '"remember me" set') % user)

        login_status = True

        if dont_redirect:
            # We're recalling the middleware to re-initialize amo_user
            ACLMiddleware().process_request(request)
            r = jingo.render(request, template, data)

    if login_status is not None:
        user.log_login_attempt(login_status)
        log_cef('Authentication Failure',
                5,
                request,
                username=request.POST['username'],
                signature='AUTHFAIL',
                msg='The password was incorrect')

    return r
Esempio n. 47
0
def register(request):

    if settings.APP_PREVIEW:
        messages.error(request,
                       loc('Registrations must be through browserid.'))
        form = None

    elif (settings.REGISTER_USER_LIMIT
          and UserProfile.objects.count() > settings.REGISTER_USER_LIMIT
          and not can_override_reg_limit(request)):
        _m = loc('Sorry, no more registrations are allowed. '
                 '<a href="https://developer.mozilla.org/en-US/apps">'
                 'Learn more</a>')
        messages.error(request, _m, title_safe=True, message_safe=True)
        form = None

    elif request.user.is_authenticated():
        messages.info(request, _('You are already logged in to an account.'))
        form = None

    elif request.method == 'POST':

        form = forms.UserRegisterForm(request.POST)

        if form.is_valid():
            try:
                u = form.save(commit=False)
                u.set_password(form.cleaned_data['password'])
                u.generate_confirmationcode()
                u.save()
                u.create_django_user()
                log.info(u'Registered new account for user (%s)', u)
                log_cef('New Account',
                        5,
                        request,
                        username=u.username,
                        signature='AUTHNOTICE',
                        msg='User created a new account')

                u.email_confirmation_code()

                if waffle.switch_is_active('zamboni-login'):
                    # Hide these messages since prod still uses remora for
                    # authentication, so django messages won't be displayed
                    # until post-login.
                    msg = _('Congratulations! Your user account was '
                            'successfully created.')
                    messages.success(request, msg)

                    msg = _(u'An email has been sent to your address {0} to '
                            'confirm your account. Before you can log in, you '
                            'have to activate your account by clicking on the '
                            'link provided in this email.').format(u.email)
                    messages.info(request, _('Confirmation Email Sent'), msg)
            except IntegrityError, e:
                # I was unable to reproduce this, but I suspect it happens
                # when they POST twice quickly and the slaves don't have the
                # new info yet (total guess).  Anyway, I'm assuming the
                # first one worked properly, so this is still a success
                # case to the end user so we just log it...
                log.error('Failed to register new user (%s): %s' % (u, e))

            return http.HttpResponseRedirect(reverse('users.login'))

        else:
            messages.error(request, _('There are errors in this form'),
                           _('Please correct them and resubmit.'))
Esempio n. 48
0
 def delete(self):
     log.info(u'Version deleted: %r (%s)' % (self, self.id))
     amo.log(amo.LOG.DELETE_VERSION, self.addon, str(self.version))
     super(Version, self).delete()
Esempio n. 49
0
 def is_authorized(self, request, object=None):
     if acl.action_allowed(request, self.app, self.action):
         log.info('Permission authorization failed')
         return True
     return False
Esempio n. 50
0
 def post_save(self, obj, created):
     log.info('Price %s %s.' % (obj, 'created' if created else 'updated'))
Esempio n. 51
0
def update_collections_total(data, **kw):
    log.info("[%s@%s] Updating collections' download totals." %
             (len(data), update_collections_total.rate_limit))
    for var in data:
        (Collection.objects.filter(pk=var['collection_id']).update(
            downloads=var['sum']))
Esempio n. 52
0
def start_upgrade(minver, maxver):
    jetpacks = files.utils.find_jetpacks(minver, maxver)
    ids = [f.id for f in jetpacks if f.needs_upgrade]
    log.info('Starting a jetpack upgrade to %s [%s files].' %
             (maxver, len(ids)))
    files.tasks.start_upgrade.delay(ids)
Esempio n. 53
0
 def region_from_request(self, request):
     address = request.META.get('REMOTE_ADDR')
     ip_reg = self.geoip.lookup(address)
     log.info('Geodude lookup for {0} returned {1}'.format(address, ip_reg))
     return mkt.regions.REGIONS_DICT.get(ip_reg, mkt.regions.RESTOFWORLD)
Esempio n. 54
0
 def obj_get(self, request=None, **kwargs):
     obj = self.get_and_check_ownership(request, allow_anon=True, **kwargs)
     log.info('App retreived: %s' % obj.pk)
     return obj
Esempio n. 55
0
def jetpack_resend(request, file_id):
    maxver = JetpackUpgrader().version()
    log.info('Starting a jetpack upgrade to %s [1 file].' % maxver)
    start_upgrade_task.delay([file_id], sdk_version=maxver)
    return redirect('zadmin.jetpack')
Esempio n. 56
0
 def after_max_redo(msg):
     log.info('Completed run: %s' % msg)
     with establish_connection() as conn:
         update_to_json.apply_async(max_objs=max_objs, connection=conn)
Esempio n. 57
0
 def process_request_information(self):
     """Send a message to the authors."""
     self.create_note(mkt.LOG.REQUEST_INFORMATION)
     self.version.update(has_info_request=True)
     log.info(u'Sending reviewer message for %s to authors' % self.addon)
Esempio n. 58
0
 def send_super_mail(self):
     log.info(u'Super review requested for %s' % (self.addon))
     send_mail('editors/emails/super_review.ltxt',
               _lazy('Super review requested: %s') % (self.addon.name),
               [settings.SENIOR_EDITORS_EMAIL],
               Context(self.get_context_data()))
Esempio n. 59
0
    def post(self, request, pk, *args, **kwargs):
        log.info(u'Received IARC pingback for app:%s' % pk)

        if request.content_type != 'application/json':
            log.info(u'IARC pingback not of content-type "application/json"')
            return Response(
                {'detail': "Endpoint only accepts 'application/json'."},
                status=http_status.HTTP_415_UNSUPPORTED_MEDIA_TYPE)

        app = self.get_object()
        data = request.DATA[0]
        if settings.DEBUG:
            log.debug(u'%s' % data)

        if app.iarc_token() != data.get('token'):
            # Verify token.
            log.info(u'Token mismatch in IARC pingback for app:%s' % app.id)
            return Response({'detail': 'Token mismatch'},
                            status=http_status.HTTP_400_BAD_REQUEST)

        if data.get('ratings'):
            # Double-check with IARC that it's the correct rating.
            if not self.verify_data(data):
                return Response('The ratings do not match the submission ID.',
                                status=http_status.HTTP_400_BAD_REQUEST)

            log.info(u'Setting content ratings from IARC pingback for app:%s' %
                     app.id)
            # We found a rating, so store the id and code for future use.
            if 'submission_id' in data and 'security_code' in data:
                app.set_iarc_info(data['submission_id'], data['security_code'])

            # Update status if incomplete status.
            # Do this before set_content_ratings to not prematurely trigger
            # a refresh.
            log.info('Checking app:%s completeness after IARC pingback.' %
                     app.id)
            if (app.has_incomplete_status()
                    and app.is_fully_complete(ignore_ratings=True)):
                log.info('Updating app status from IARC pingback for app:%s' %
                         app.id)
                # Don't call update to prevent recursion in update_status.
                app.update(status=amo.STATUS_PENDING)
                log.info('Updated app status from IARC pingback for app:%s' %
                         app.id)
            elif app.has_incomplete_status():
                log.info('Reasons for app:%s incompleteness after IARC '
                         'pingback: %s' % (app.id, app.completion_errors()))

            app.set_descriptors(data.get('descriptors', []))
            app.set_interactives(data.get('interactives', []))
            # Set content ratings last since it triggers a refresh on Content
            # Ratings page. We want descriptors and interactives visible by
            # the time it's refreshed.
            app.set_content_ratings(data.get('ratings', {}))

        return Response('ok')
Esempio n. 60
0
def start_upgrade(minver, maxver):
    jetpacks = find_jetpacks(minver, maxver, from_builder_only=True)
    ids = [f.id for f in jetpacks if f.needs_upgrade]
    log.info('Starting a jetpack upgrade to %s [%s files].'
             % (maxver, len(ids)))
    start_upgrade_task.delay(ids, sdk_version=maxver)