Ejemplo n.º 1
0
    def obj_create(self, bundle, request=None, **kwargs):
        """
        Handle POST requests to the resource. If the data validates, create a
        new Review from bundle data.
        """
        form = ReviewForm(bundle.data)

        if not form.is_valid():
            raise self.form_errors(form)

        app = self.get_app(bundle.data["app"])

        # Return 409 if the user has already reviewed this app.
        qs = self._meta.queryset.filter(addon=app, user=request.user)
        if app.is_packaged:
            qs = qs.filter(version_id=bundle.data.get("version", app.current_version.id))
        if qs.exists():
            raise http_error(http.HttpConflict, "You have already reviewed this app.")

        # Return 403 if the user is attempting to review their own app:
        if app.has_author(request.user):
            raise http_error(http.HttpForbidden, "You may not review your own app.")

        # Return 403 if not a free app and the user hasn't purchased it.
        if app.is_premium() and not app.is_purchased(request.amo_user):
            raise http_error(http.HttpForbidden, "You may not review paid apps you haven't purchased.")

        bundle.obj = Review.objects.create(**self._review_data(request, app, form))

        amo.log(amo.LOG.ADD_REVIEW, app, bundle.obj)
        log.debug("[Review:%s] Created by user %s " % (bundle.obj.id, request.user.id))
        record_action("new-review", request, {"app-id": app.id})

        return bundle
Ejemplo n.º 2
0
    def obj_create(self, bundle, request, **kwargs):
        form = UploadForm(bundle.data)

        if not request.amo_user.read_dev_agreement:
            log.info(u'Attempt to use API without dev agreement: %s'
                     % request.amo_user.pk)
            raise http_error(http.HttpUnauthorized,
                             'Terms of service not accepted.')

        if not form.is_valid():
            raise self.form_errors(form)

        if not (OwnerAuthorization()
                .is_authorized(request, object=form.obj)):
            raise http_error(http.HttpForbidden,
                             'You do not own that app.')

        plats = [Platform.objects.get(id=amo.PLATFORM_ALL.id)]

        # Create app, user and fetch the icon.
        bundle.obj = Addon.from_upload(form.obj, plats,
                                       is_packaged=form.is_packaged)
        AddonUser(addon=bundle.obj, user=request.amo_user).save()

        self._icons_and_images(bundle.obj)
        record_action('app-submitted', request, {'app-id': bundle.obj.pk})

        log.info('App created: %s' % bundle.obj.pk)
        return bundle
Ejemplo n.º 3
0
 def perform_create(self, serializer):
     serializer.save()
     app = serializer.instance.addon
     mkt.log(mkt.LOG.ADD_REVIEW, app, serializer.instance)
     log.debug('[Review:%s] Created by user %s ' %
               (serializer.instance.pk, self.request.user.id))
     record_action('new-review', self.request, {'app-id': app.id})
Ejemplo n.º 4
0
 def perform_create(self, serializer):
     serializer.save()
     app = serializer.instance.addon
     mkt.log(mkt.LOG.ADD_REVIEW, app, serializer.instance)
     log.debug('[Review:%s] Created by user %s ' %
               (serializer.instance.pk, self.request.user.id))
     record_action('new-review', self.request, {'app-id': app.id})
Ejemplo n.º 5
0
def _fxa_authorize(fxa, client_secret, request, auth_response):
    token = fxa.fetch_token(
        fxa_oauth_api('token'),
        authorization_response=auth_response,
        client_secret=client_secret)
    res = fxa.post(fxa_oauth_api('verify'),
                   data=json.dumps({'token': token['access_token']}),
                   headers={'Content-Type': 'application/json'})
    data = res.json()
    if 'user' in data:
        email = data['email']
        username = data['user']
        try:
            profile = UserProfile.objects.get(email=email)
        except UserProfile.DoesNotExist:
            source = amo.LOGIN_SOURCE_FXA
            profile = UserProfile.objects.create(
                username=username,
                email=email,
                source=source,
                display_name=email.partition('@')[0],
                is_verified=True)
            log_cef('New Account', 5, request, username=username,
                    signature='AUTHNOTICE',
                    msg='User created a new account (from FxA)')
            record_action('new-user', request)
        auth.login(request, profile)
        profile.log_login_attempt(True)
        auth.signals.user_logged_in.send(
            sender=profile.__class__, request=request,
            user=profile)
        return profile
Ejemplo n.º 6
0
    def obj_create(self, bundle, request, **kwargs):
        form = UploadForm(bundle.data)

        if not request.amo_user.read_dev_agreement:
            log.info(u'Attempt to use API without dev agreement: %s'
                     % request.amo_user.pk)
            response = http.HttpUnauthorized()
            response.content = json.dumps({'reason':
                                           'Terms of service not accepted.'})
            raise ImmediateHttpResponse(response=response)

        if not form.is_valid():
            raise self.form_errors(form)

        if not (OwnerAuthorization()
                .is_authorized(request, object=form.obj)):
            raise ImmediateHttpResponse(response=http.HttpForbidden())

        plats = [Platform.objects.get(id=amo.PLATFORM_ALL.id)]

        # Create app, user and fetch the icon.
        bundle.obj = Addon.from_upload(form.obj, plats,
                                       is_packaged=form.is_packaged)
        AddonUser(addon=bundle.obj, user=request.amo_user).save()

        self._icons_and_images(bundle.obj)
        record_action('app-submitted', request, {'app-id': bundle.obj.pk})

        log.info('App created: %s' % bundle.obj.pk)
        return bundle
Ejemplo n.º 7
0
    def obj_create(self, bundle, request=None, **kwargs):
        """
        Handle POST requests to the resource. If the data validates, create a
        new Review from bundle data.
        """
        form = ReviewForm(bundle.data)

        if not form.is_valid():
            raise self.form_errors(form)

        app = self.get_app(bundle.data['app'])

        # Return 409 if the user has already reviewed this app.
        if self._meta.queryset.filter(addon=app, user=request.user).exists():
            raise ImmediateHttpResponse(response=http.HttpConflict())

        # Return 403 if the user is attempting to review their own app:
        if app.has_author(request.user):
            raise ImmediateHttpResponse(response=http.HttpForbidden())

        # Return 403 if not a free app and the user hasn't purchased it.
        if app.is_premium() and not app.is_purchased(request.amo_user):
            raise ImmediateHttpResponse(response=http.HttpForbidden())

        bundle.obj = Review.objects.create(**self._review_data(request, app,
                                                               form))

        amo.log(amo.LOG.ADD_REVIEW, app, bundle.obj)
        log.debug('[Review:%s] Created by user %s ' %
                  (bundle.obj.id, request.user.id))
        record_action('new-review', request, {'app-id': app.id})

        return bundle
Ejemplo n.º 8
0
    def obj_create(self, bundle, request=None, **kwargs):
        """
        Handle POST requests to the resource. If the data validates, create a
        new Review from bundle data.
        """
        form = ReviewForm(bundle.data)

        if not form.is_valid():
            raise self.form_errors(form)

        app = self.get_app(bundle.data['app'])

        # Return 409 if the user has already reviewed this app.
        if self._meta.queryset.filter(addon=app, user=request.user).exists():
            raise ImmediateHttpResponse(response=http.HttpConflict())

        # Return 403 if the user is attempting to review their own app:
        if app.has_author(request.user):
            raise ImmediateHttpResponse(response=http.HttpForbidden())

        # Return 403 if not a free app and the user hasn't purchased it.
        if app.is_premium() and not app.is_purchased(request.amo_user):
            raise ImmediateHttpResponse(response=http.HttpForbidden())

        bundle.obj = Review.objects.create(
            **self._review_data(request, app, form))

        amo.log(amo.LOG.ADD_REVIEW, app, bundle.obj)
        log.debug('[Review:%s] Created by user %s ' %
                  (bundle.obj.id, request.user.id))
        record_action('new-review', request, {'app-id': app.id})

        return bundle
Ejemplo n.º 9
0
    def create(self, request, *args, **kwargs):
        uuid = request.DATA.get("upload", "")
        if uuid:
            is_packaged = True
        else:
            uuid = request.DATA.get("manifest", "")
            is_packaged = False
        if not uuid:
            raise serializers.ValidationError("No upload or manifest specified.")

        try:
            upload = FileUpload.objects.get(uuid=uuid)
        except FileUpload.DoesNotExist:
            raise exceptions.ParseError("No upload found.")
        if not upload.valid:
            raise exceptions.ParseError("Upload not valid.")

        if not request.user.read_dev_agreement:
            log.info(u"Attempt to use API without dev agreement: %s" % request.user.pk)
            raise exceptions.PermissionDenied("Terms of Service not accepted.")
        if not (upload.user and upload.user.pk == request.user.pk):
            raise exceptions.PermissionDenied("You do not own that app.")

        # Create app, user and fetch the icon.
        obj = Webapp.from_upload(upload, is_packaged=is_packaged)
        AddonUser(addon=obj, user=request.user).save()
        tasks.fetch_icon.delay(obj, obj.latest_version.all_files[0])
        record_action("app-submitted", request, {"app-id": obj.pk})

        log.info("App created: %s" % obj.pk)
        data = AppSerializer(context=self.get_serializer_context()).to_native(obj)

        return response.Response(data, status=201, headers={"Location": reverse("app-detail", kwargs={"pk": obj.pk})})
Ejemplo n.º 10
0
 def test_record_action(self, record_stat):
     request = mock.Mock()
     request.GET = {'src': 'foo'}
     request.LANG = 'en'
     request.META = {'HTTP_USER_AGENT': 'py'}
     record_action('install', request, {})
     record_stat.assert_called_with('install', request,
         **{'locale': 'en', 'src': 'foo', 'user-agent': 'py'})
Ejemplo n.º 11
0
def record(request, app):
    amo.log(amo.LOG.INSTALL_ADDON, app)
    domain = app.domain_from_url(app.origin, allow_none=True)
    record_action('install', request, {
        'app-domain': domain,
        'app-id': app.pk,
        'anonymous': request.user.is_anonymous(),
    })
Ejemplo n.º 12
0
def browserid_authenticate(request, assertion, is_mobile=False, browserid_audience=get_audience):
    """
    Verify a BrowserID login attempt. If the BrowserID assertion is
    good, but no account exists, create one.

    """
    extra_params = {}
    url = settings.NATIVE_FXA_VERIFICATION_URL
    log.debug("Verifying Native FxA at %s, audience: %s, " "extra_params: %s" % (url, browserid_audience, extra_params))
    v = BrowserIDBackend().get_verifier()
    v.verification_service_url = url
    result = v.verify(assertion, browserid_audience, url=url, **extra_params)
    if not result:
        return None, _("Native FxA authentication failure.")

    if "unverified-email" in result._response:
        email = result._response["unverified-email"]
        verified = False
    elif result._response.get("issuer") == settings.NATIVE_FXA_ISSUER and "fxa-verifiedEmail" in result._response.get(
        "idpClaims", {}
    ):
        email = result._response["idpClaims"]["fxa-verifiedEmail"]
        verified = True
    else:
        email = result.email
        verified = True

    try:
        profile = UserProfile.objects.filter(email=email)[0]
    except IndexError:
        profile = None

    if profile:
        if profile.is_verified and not verified:
            # An attempt to log in to a verified address with an unverified
            # assertion is a very bad thing. Don't let that happen.
            log.debug("Verified user %s attempted to log in with an " "unverified assertion!" % profile)
            return None, _("Please use the verified email for this account.")
        else:
            profile.is_verified = verified
            profile.save()

        return profile, None

    source = mkt.LOGIN_SOURCE_MMO_BROWSERID
    display_name = email.partition("@")[0]
    profile = UserProfile.objects.create(email=email, source=source, display_name=display_name, is_verified=verified)
    log_cef(
        "New Account",
        5,
        request,
        username=display_name,
        signature="AUTHNOTICE",
        msg="User created a new account (from Persona)",
    )
    record_action("new-user", request)

    return profile, None
Ejemplo n.º 13
0
def _record(request, addon):
    logged = request.user.is_authenticated()
    premium = addon.is_premium()

    # Require login for premium.
    if not logged and premium:
        return http.HttpResponseRedirect(reverse('users.login'))

    ctx = {'addon': addon.pk}

    # Don't generate receipts if we're allowing logged-out install.
    if logged:
        is_dev = request.check_ownership(addon,
                                         require_owner=False,
                                         ignore_disabled=True,
                                         admin=False)
        is_reviewer = acl.check_reviewer(request)
        if (not addon.is_public() and not (is_reviewer or is_dev)):
            raise http.Http404

        if (premium and not addon.has_purchased(request.user)
                and not is_reviewer and not is_dev):
            raise PermissionDenied

        # If you are reviewer, you get a user receipt. Use the reviewer tools
        # to get a reviewer receipt. App developers still get their special
        # receipt.
        install = (apps.INSTALL_TYPE_DEVELOPER
                   if is_dev else apps.INSTALL_TYPE_USER)
        # Log the install.
        installed, c = Installed.objects.get_or_create(addon=addon,
                                                       user=request.user,
                                                       install_type=install)

        # Get a suitable uuid for this receipt.
        uuid = get_uuid(addon, request.user)

        error = ''
        receipt_cef.log(request, addon, 'sign', 'Receipt requested')
        try:
            receipt = create_receipt(addon, request.user, uuid)
        except SigningError:
            error = _('There was a problem installing the app.')

        ctx.update(receipt=receipt, error=error)
    else:
        if not addon.is_public():
            raise http.Http404

    amo.log(amo.LOG.INSTALL_ADDON, addon)
    record_action(
        'install', request, {
            'app-domain': addon.domain_from_url(addon.origin, allow_none=True),
            'app-id': addon.pk,
            'anonymous': request.user.is_anonymous(),
        })

    return ctx
Ejemplo n.º 14
0
 def obj_create(self, bundle, request=None, **kwargs):
     bundle.data['receipt'] = self.handle(bundle, request=request, **kwargs)
     amo.log(amo.LOG.INSTALL_ADDON, bundle.obj)
     record_action('install', request, {
         'app-domain': bundle.obj.domain_from_url(bundle.obj.origin),
         'app-id': bundle.obj.pk,
         'anonymous': request.user.is_anonymous(),
     })
     return bundle
Ejemplo n.º 15
0
 def post_save(self, obj, created=False):
     app = obj.addon
     if created:
         amo.log(amo.LOG.ADD_REVIEW, app, obj)
         log.debug("[Review:%s] Created by user %s " % (obj.pk, self.request.amo_user.id))
         record_action("new-review", self.request, {"app-id": app.id})
     else:
         amo.log(amo.LOG.EDIT_REVIEW, app, obj)
         log.debug("[Review:%s] Edited by %s" % (obj.pk, self.request.amo_user.id))
Ejemplo n.º 16
0
    def create_action(self, request, serializer):
        client_id = request.POST.get('client_id', settings.FXA_CLIENT_ID)
        secret = settings.FXA_SECRETS[client_id]
        session = OAuth2Session(
            client_id,
            scope=u'profile',
            state=serializer.data['state'])

        auth_response = serializer.data['auth_response']
        fxa_authorization = fxa_authorize(session, secret, auth_response)

        if 'user' in fxa_authorization:
            email = fxa_authorization['email']
            fxa_uid = fxa_authorization['user']
            profile, created = find_or_create_user(email, fxa_uid)
            if created:
                log_cef('New Account', 5, request, username=fxa_uid,
                        signature='AUTHNOTICE',
                        msg='User created a new account (from FxA)')
                record_action('new-user', request)
            auth.login(request, profile)
            profile.update(last_login_ip=request.META.get('REMOTE_ADDR', ''))

            auth.signals.user_logged_in.send(sender=profile.__class__,
                                             request=request,
                                             user=profile)
        else:
            raise AuthenticationFailed('No profile.')

        request.user = profile
        request.groups = profile.groups.all()
        # Remember whether the user has logged in to highlight the register or
        # sign in nav button. 31536000 == one year.
        request.set_cookie('has_logged_in', '1', max_age=5 * 31536000)

        # We want to return completely custom data, not the serializer's.
        data = {
            'error': None,
            'token': commonplace_token(request.user.email),
            'settings': {
                'display_name': request.user.display_name,
                'email': request.user.email,
                'enable_recommendations': request.user.enable_recommendations,
                'source': 'firefox-accounts',
            }
        }
        # Serializers give up if they aren't passed an instance, so we
        # do that here despite PermissionsSerializer not needing one
        # really.
        permissions = PermissionsSerializer(context={'request': request},
                                            instance=True)
        data.update(permissions.data)

        # Add ids of installed/purchased/developed apps.
        data['apps'] = user_relevant_apps(profile)

        return data
Ejemplo n.º 17
0
def record(request, app):
    mkt.log(mkt.LOG.INSTALL_WEBAPP, app)
    domain = app.domain_from_url(app.origin, allow_none=True)
    record_action('install', request, {
        'app-domain': domain,
        'app-id': app.pk,
        'region': request.REGION.slug,
        'anonymous': request.user.is_anonymous(),
    })
Ejemplo n.º 18
0
def record(request, app):
    amo.log(amo.LOG.INSTALL_ADDON, app)
    domain = app.domain_from_url(app.origin, allow_none=True)
    record_action(
        'install', request, {
            'app-domain': domain,
            'app-id': app.pk,
            'anonymous': request.user.is_anonymous(),
        })
Ejemplo n.º 19
0
def browserid_authenticate(request, assertion, is_mobile=False,
                           browserid_audience=get_audience):
    """
    Verify a BrowserID login attempt. If the BrowserID assertion is
    good, but no account exists, create one.

    """
    extra_params = {}
    url = settings.NATIVE_FXA_VERIFICATION_URL
    log.debug('Verifying Native FxA at %s, audience: %s, '
              'extra_params: %s' % (url, browserid_audience, extra_params))
    v = BrowserIDBackend().get_verifier()
    v.verification_service_url = url
    result = v.verify(assertion, browserid_audience, url=url, **extra_params)
    if not result:
        return None, _('Native FxA authentication failure.')

    if 'unverified-email' in result._response:
        email = result._response['unverified-email']
        verified = False
    elif (result._response.get('issuer') == settings.NATIVE_FXA_ISSUER and
          'fxa-verifiedEmail' in result._response.get('idpClaims', {})):
        email = result._response['idpClaims']['fxa-verifiedEmail']
        verified = True
    else:
        email = result.email
        verified = True

    try:
        profile = UserProfile.objects.filter(email=email)[0]
    except IndexError:
        profile = None

    if profile:
        if profile.is_verified and not verified:
            # An attempt to log in to a verified address with an unverified
            # assertion is a very bad thing. Don't let that happen.
            log.debug('Verified user %s attempted to log in with an '
                      'unverified assertion!' % profile)
            return None, _('Please use the verified email for this account.')
        else:
            profile.is_verified = verified
            profile.save()

        return profile, None

    username = autocreate_username(email.partition('@')[0])
    source = amo.LOGIN_SOURCE_MMO_BROWSERID
    profile = UserProfile.objects.create(username=username, email=email,
                                         source=source, display_name=username,
                                         is_verified=verified)
    log_cef('New Account', 5, request, username=username,
            signature='AUTHNOTICE',
            msg='User created a new account (from Persona)')
    record_action('new-user', request)

    return profile, None
Ejemplo n.º 20
0
    def create_action(self, request, serializer):
        client_id = request.POST.get('client_id', settings.FXA_CLIENT_ID)
        secret = settings.FXA_SECRETS[client_id]
        session = OAuth2Session(
            client_id,
            scope=u'profile',
            state=serializer.data['state'])

        auth_response = serializer.data['auth_response']
        fxa_authorization = fxa_authorize(session, secret, auth_response)

        if 'user' in fxa_authorization:
            email = fxa_authorization['email']
            fxa_uid = fxa_authorization['user']
            profile, created = find_or_create_user(email, fxa_uid)
            if created:
                log_cef('New Account', 5, request, username=fxa_uid,
                        signature='AUTHNOTICE',
                        msg='User created a new account (from FxA)')
                record_action('new-user', request)
            auth.login(request, profile)
            profile.update(last_login_ip=request.META.get('REMOTE_ADDR', ''))

            auth.signals.user_logged_in.send(sender=profile.__class__,
                                             request=request,
                                             user=profile)
        else:
            raise AuthenticationFailed('No profile.')

        request.user = profile
        request.groups = profile.groups.all()
        # Remember whether the user has logged in to highlight the register or
        # sign in nav button. 31536000 == one year.
        request.set_cookie('has_logged_in', '1', max_age=5 * 31536000)

        # We want to return completely custom data, not the serializer's.
        data = {
            'error': None,
            'token': commonplace_token(request.user.email),
            'settings': {
                'display_name': request.user.display_name,
                'email': request.user.email,
                'enable_recommendations': request.user.enable_recommendations,
                'source': 'firefox-accounts',
            }
        }
        # Serializers give up if they aren't passed an instance, so we
        # do that here despite PermissionsSerializer not needing one
        # really.
        permissions = PermissionsSerializer(context={'request': request},
                                            instance=True)
        data.update(permissions.data)

        # Add ids of installed/purchased/developed apps.
        data['apps'] = user_relevant_apps(profile)

        return data
Ejemplo n.º 21
0
def _record(request, addon):
    logged = request.user.is_authenticated()
    premium = addon.is_premium()

    # Require login for premium.
    if not logged and premium:
        return http.HttpResponseRedirect(reverse('users.login'))

    ctx = {'addon': addon.pk}

    # Don't generate receipts if we're allowing logged-out install.
    if logged:
        is_dev = request.check_ownership(addon, require_owner=False,
                                         ignore_disabled=True, admin=False)
        is_reviewer = acl.check_reviewer(request)
        if (not addon.is_webapp() or not addon.is_public() and
            not (is_reviewer or is_dev)):
            raise http.Http404

        if (premium and
            not addon.has_purchased(request.amo_user) and
            not is_reviewer and not is_dev):
            raise PermissionDenied

        # If you are reviewer, you get a user receipt. Use the reviewer tools
        # to get a reviewer receipt. App developers still get their special
        # receipt.
        install_type = (apps.INSTALL_TYPE_DEVELOPER if is_dev
                        else apps.INSTALL_TYPE_USER)
        # Log the install.
        installed, c = Installed.objects.get_or_create(addon=addon,
            user=request.amo_user, install_type=install_type)

        # Get a suitable uuid for this receipt.
        uuid = get_uuid(addon, request.amo_user)

        error = ''
        receipt_cef.log(request, addon, 'sign', 'Receipt requested')
        try:
            receipt = create_receipt(addon, request.amo_user, uuid)
        except SigningError:
            error = _('There was a problem installing the app.')

        ctx.update(receipt=receipt, error=error)
    else:
        if not addon.is_public() or not addon.is_webapp():
            raise http.Http404

    amo.log(amo.LOG.INSTALL_ADDON, addon)
    record_action('install', request, {
        'app-domain': addon.domain_from_url(addon.origin, allow_none=True),
        'app-id': addon.pk,
        'anonymous': request.user.is_anonymous(),
    })

    return ctx
Ejemplo n.º 22
0
def details(request, addon_id, addon):
    # Name, Slug, Description, Privacy Policy, Homepage URL, Support URL,
    # Support Email.
    form_basic = AppDetailsBasicForm(request.POST or None, instance=addon, request=request)
    form_cats = CategoryForm(request.POST or None, product=addon, request=request)
    form_icon = AppFormMedia(request.POST or None, request.FILES or None, instance=addon, request=request)
    form_previews = PreviewFormSet(request.POST or None, prefix="files", queryset=addon.get_previews())

    # For empty webapp-locale (or no-locale) fields that have
    # form-locale values, duplicate them to satisfy the requirement.
    form_locale = request.COOKIES.get("current_locale", "")
    app_locale = to_language(addon.default_locale)
    for name, value in request.POST.items():
        if value:
            if name.endswith(form_locale):
                basename = name[: -len(form_locale)]
            else:
                basename = name + "_"
            othername = basename + app_locale
            if not request.POST.get(othername, None):
                request.POST[othername] = value
    forms = {"form_basic": form_basic, "form_cats": form_cats, "form_icon": form_icon, "form_previews": form_previews}
    if request.POST and all(f.is_valid() for f in forms.itervalues()):
        addon = form_basic.save(addon)
        form_cats.save()
        form_icon.save(addon)
        for preview in form_previews.forms:
            preview.save(addon)
        # If this is an incomplete app from the legacy submission flow, it may
        # not have device types set yet - so assume it works everywhere.
        if not addon.device_types:
            for device in amo.DEVICE_TYPES:
                addon.addondevicetype_set.create(device_type=device)

        AppSubmissionChecklist.objects.get(addon=addon).update(details=True)

        if addon.needs_payment():
            # Paid apps get STATUS_NULL until payment information and content
            # ratings entered.
            addon.update(status=amo.STATUS_NULL, highest_status=amo.STATUS_PENDING)

        # Mark as pending in special regions (i.e., China).
        # By default, the column is set to pending when the row is inserted.
        # But we need to set a nomination date so we know to list the app
        # in the China Review Queue now (and sort it by that date too).
        for region in mkt.regions.SPECIAL_REGIONS:
            addon.geodata.set_nominated_date(region, save=True)
            log.info(u"[Webapp:%s] Setting nomination date to " u"now for region (%s)." % (addon, region.slug))

        record_action("app-submitted", request, {"app-id": addon.pk})

        return redirect("submit.app.done", addon.app_slug)

    ctx = {"step": "details", "addon": addon}
    ctx.update(forms)
    return render(request, "submit/details.html", ctx)
Ejemplo n.º 23
0
 def obj_create(self, bundle, request=None, **kwargs):
     bundle.data['receipt'] = self.handle(bundle, request=request, **kwargs)
     amo.log(amo.LOG.INSTALL_ADDON, bundle.obj)
     record_action(
         'install', request, {
             'app-domain': bundle.obj.domain_from_url(bundle.obj.origin),
             'app-id': bundle.obj.pk,
             'anonymous': request.user.is_anonymous(),
         })
     return bundle
Ejemplo n.º 24
0
 def post_save(self, obj, created=False):
     app = obj.addon
     if created:
         mkt.log(mkt.LOG.ADD_REVIEW, app, obj)
         log.debug('[Review:%s] Created by user %s ' %
                   (obj.pk, self.request.user.id))
         record_action('new-review', self.request, {'app-id': app.id})
     else:
         mkt.log(mkt.LOG.EDIT_REVIEW, app, obj)
         log.debug('[Review:%s] Edited by %s' %
                   (obj.pk, self.request.user.id))
Ejemplo n.º 25
0
 def post_save(self, obj, created=False):
     app = obj.addon
     if created:
         amo.log(amo.LOG.ADD_REVIEW, app, obj)
         log.debug('[Review:%s] Created by user %s ' %
                   (obj.pk, self.request.amo_user.id))
         record_action('new-review', self.request, {'app-id': app.id})
     else:
         amo.log(amo.LOG.EDIT_REVIEW, app, obj)
         log.debug('[Review:%s] Edited by %s' %
                   (obj.pk, self.request.amo_user.id))
Ejemplo n.º 26
0
 def test_record_action(self, record_stat, urlopen):
     request = mock.Mock()
     request.GET = {'src': 'foo'}
     request.LANG = 'en'
     request.META = {'HTTP_USER_AGENT': 'py'}
     record_action('install', request, {})
     assert record_stat.called
     data = json.loads(urlopen.call_args[0][0].data)
     eq_(data['user-agent'], 'py')
     eq_(data['locale'], 'en')
     eq_(data['src'], 'foo')
Ejemplo n.º 27
0
 def test_record_action(self, record_stat):
     request = mock.Mock()
     request.GET = {'src': 'foo'}
     request.LANG = 'en'
     request.META = {'HTTP_USER_AGENT': 'py'}
     record_action('install', request, {})
     record_stat.assert_called_with(
         'install', request, **{
             'locale': 'en',
             'src': 'foo',
             'user-agent': 'py'
         })
Ejemplo n.º 28
0
def record(request, app):
    mkt.log(mkt.LOG.INSTALL_ADDON, app)
    domain = app.domain_from_url(app.origin, allow_none=True)
    record_action(
        "install",
        request,
        {
            "app-domain": domain,
            "app-id": app.pk,
            "region": request.REGION.slug,
            "anonymous": request.user.is_anonymous(),
        },
    )
Ejemplo n.º 29
0
def _fxa_authorize(fxa, client_secret, request, auth_response, userid):
    token = fxa.fetch_token(fxa_oauth_api('token'),
                            authorization_response=auth_response,
                            client_secret=client_secret)
    res = fxa.post(fxa_oauth_api('verify'),
                   data=json.dumps({'token': token['access_token']}),
                   headers={'Content-Type': 'application/json'})
    data = res.json()

    if 'user' in data:
        email = data['email']
        fxa_uid = data['user']

        def find_user(**kwargs):
            try:
                return UserProfile.objects.get(**kwargs)
            except UserProfile.DoesNotExist:
                return None

        profile = (find_user(pk=userid) or find_user(username=fxa_uid)
                   or find_user(email=email))
        if profile:
            profile.update(username=fxa_uid, email=email)
        else:
            profile = UserProfile.objects.create(
                username=fxa_uid,
                email=email,
                source=amo.LOGIN_SOURCE_FXA,
                display_name=email.partition('@')[0],
                is_verified=True)
            log_cef('New Account',
                    5,
                    request,
                    username=fxa_uid,
                    signature='AUTHNOTICE',
                    msg='User created a new account (from FxA)')
            record_action('new-user', request)

        if profile.source != amo.LOGIN_SOURCE_FXA:
            profile.update(source=amo.LOGIN_SOURCE_FXA)

        auth.login(request, profile)
        profile.log_login_attempt(True)

        auth.signals.user_logged_in.send(sender=profile.__class__,
                                         request=request,
                                         user=profile)

        return profile
Ejemplo n.º 30
0
def _fxa_authorize(fxa, client_secret, request, auth_response, userid):
    token = fxa.fetch_token(
        fxa_oauth_api('token'),
        authorization_response=auth_response,
        client_secret=client_secret)
    res = fxa.post(fxa_oauth_api('verify'),
                   data=json.dumps({'token': token['access_token']}),
                   headers={'Content-Type': 'application/json'})
    data = res.json()

    if 'user' in data:
        email = data['email']
        fxa_uid = data['user']

        def find_user(**kwargs):
            try:
                return UserProfile.objects.get(**kwargs)
            except UserProfile.DoesNotExist:
                return None

        profile = (find_user(pk=userid) or find_user(username=fxa_uid)
                   or find_user(email=email))
        if profile:
            profile.update(username=fxa_uid, email=email)
        else:
            profile = UserProfile.objects.create(
                username=fxa_uid,
                email=email,
                source=amo.LOGIN_SOURCE_FXA,
                display_name=email.partition('@')[0],
                is_verified=True)
            log_cef('New Account', 5, request, username=fxa_uid,
                    signature='AUTHNOTICE',
                    msg='User created a new account (from FxA)')
            record_action('new-user', request)

        if profile.source != amo.LOGIN_SOURCE_FXA:
            log.info('Set account to FxA for {0}'.format(email))
            statsd.incr('z.mkt.user.fxa')
            profile.update(source=amo.LOGIN_SOURCE_FXA)

        auth.login(request, profile)
        profile.log_login_attempt(True)

        auth.signals.user_logged_in.send(sender=profile.__class__,
                                         request=request, user=profile)

        return profile
Ejemplo n.º 31
0
def _get_user_profile(request, buyer_email):
    user_profile = UserProfile.objects.filter(email=buyer_email)

    if user_profile.exists():
        user_profile = user_profile.get()
    else:
        source = mkt.LOGIN_SOURCE_WEBPAY
        user_profile = UserProfile.objects.create(
            email=buyer_email,
            is_verified=True,
            source=source)

        log_cef('New Account', 5, request, username=buyer_email,
                signature='AUTHNOTICE',
                msg='A new account was created from Webpay (using FxA)')
        record_action('new-user', request)

    return user_profile
Ejemplo n.º 32
0
def _get_user_profile(request, buyer_email):
    user_profile = UserProfile.objects.filter(email=buyer_email)

    if user_profile.exists():
        user_profile = user_profile.get()
    else:
        source = mkt.LOGIN_SOURCE_WEBPAY
        user_profile = UserProfile.objects.create(
            email=buyer_email,
            is_verified=True,
            source=source)

        log_cef('New Account', 5, request, username=buyer_email,
                signature='AUTHNOTICE',
                msg='A new account was created from Webpay (using FxA)')
        record_action('new-user', request)

    return user_profile
Ejemplo n.º 33
0
    def create(self, request, *args, **kwargs):
        uuid = request.data.get('upload', '')
        if uuid:
            is_packaged = True
        else:
            uuid = request.data.get('manifest', '')
            is_packaged = False
        if not uuid:
            raise exceptions.ParseError(
                'No upload or manifest specified.')

        try:
            upload = FileUpload.objects.get(uuid=uuid)
        except FileUpload.DoesNotExist:
            raise exceptions.ParseError('No upload found.')
        if not upload.valid:
            raise exceptions.ParseError('Upload not valid.')

        if not request.user.read_dev_agreement:
            log.info(u'Attempt to use API without dev agreement: %s'
                     % request.user.pk)
            raise exceptions.PermissionDenied('Terms of Service not accepted.')
        if not (upload.user and upload.user.pk == request.user.pk):
            raise exceptions.PermissionDenied('You do not own that app.')

        # Create app, user and fetch the icon.
        try:
            obj = Webapp.from_upload(upload, is_packaged=is_packaged)
        except (serializers.ValidationError,
                django_forms.ValidationError) as e:
            raise exceptions.ParseError(unicode(e))
        AddonUser(addon=obj, user=request.user).save()
        tasks.fetch_icon.delay(obj.pk, obj.latest_version.all_files[0].pk)
        record_action('app-submitted', request, {'app-id': obj.pk})
        log.info('App created: %s' % obj.pk)
        data = AppSerializer(
            context=self.get_serializer_context(), instance=obj).data

        return response.Response(
            data, status=201,
            headers={'Location': reverse('app-detail', kwargs={'pk': obj.pk})})
Ejemplo n.º 34
0
    def obj_create(self, bundle, request=None, **kwargs):
        """
        Handle POST requests to the resource. If the data validates, create a
        new Review from bundle data.
        """
        form = ReviewForm(bundle.data)

        if not form.is_valid():
            raise self.form_errors(form)

        app = self.get_app(bundle.data['app'])

        # Return 409 if the user has already reviewed this app.
        qs = self._meta.queryset.filter(addon=app, user=request.user)
        if app.is_packaged:
            qs = qs.filter(
                version_id=bundle.data.get('version', app.current_version.id))
        if qs.exists():
            raise http_error(http.HttpConflict,
                             'You have already reviewed this app.')

        # Return 403 if the user is attempting to review their own app:
        if app.has_author(request.user):
            raise http_error(http.HttpForbidden,
                             'You may not review your own app.')

        # Return 403 if not a free app and the user hasn't purchased it.
        if app.is_premium() and not app.is_purchased(request.amo_user):
            raise http_error(
                http.HttpForbidden,
                "You may not review paid apps you haven't purchased.")

        bundle.obj = Review.objects.create(
            **self._review_data(request, app, form))

        amo.log(amo.LOG.ADD_REVIEW, app, bundle.obj)
        log.debug('[Review:%s] Created by user %s ' %
                  (bundle.obj.id, request.user.id))
        record_action('new-review', request, {'app-id': app.id})

        return bundle
Ejemplo n.º 35
0
    def obj_create(self, bundle, request, **kwargs):
        form = UploadForm(bundle.data)

        if not form.is_valid():
            raise self.form_errors(form)

        if not (OwnerAuthorization()
                .is_authorized(request, object=form.obj)):
            raise ImmediateHttpResponse(response=http.HttpForbidden())

        plats = [Platform.objects.get(id=amo.PLATFORM_ALL.id)]

        # Create app, user and fetch the icon.
        bundle.obj = Addon.from_upload(form.obj, plats,
                                       is_packaged=form.is_packaged)
        AddonUser(addon=bundle.obj, user=request.amo_user).save()

        self._icons_and_images(bundle.obj)
        record_action('app-submitted', request, {'app-id': bundle.obj.pk})

        log.info('App created: %s' % bundle.obj.pk)
        return bundle
Ejemplo n.º 36
0
    def obj_create(self, bundle, request, **kwargs):
        form = UploadForm(bundle.data)

        if not form.is_valid():
            raise self.form_errors(form)

        if not (OwnerAuthorization().is_authorized(request, object=form.obj)):
            raise ImmediateHttpResponse(response=http.HttpForbidden())

        plats = [Platform.objects.get(id=amo.PLATFORM_ALL.id)]

        # Create app, user and fetch the icon.
        bundle.obj = Addon.from_upload(form.obj,
                                       plats,
                                       is_packaged=form.is_packaged)
        AddonUser(addon=bundle.obj, user=request.amo_user).save()

        self._icons_and_images(bundle.obj)
        record_action('app-submitted', request, {'app-id': bundle.obj.pk})

        log.info('App created: %s' % bundle.obj.pk)
        return bundle
Ejemplo n.º 37
0
    def obj_create(self, bundle, request, **kwargs):
        form = UploadForm(bundle.data)

        if not request.amo_user.read_dev_agreement:
            log.info(u"Attempt to use API without dev agreement: %s" % request.amo_user.pk)
            raise http_error(http.HttpUnauthorized, "Terms of service not accepted.")

        if not form.is_valid():
            raise self.form_errors(form)

        if not (OwnerAuthorization().is_authorized(request, object=form.obj)):
            raise http_error(http.HttpForbidden, "You do not own that app.")

        plats = [Platform.objects.get(id=amo.PLATFORM_ALL.id)]

        # Create app, user and fetch the icon.
        bundle.obj = Addon.from_upload(form.obj, plats, is_packaged=form.is_packaged)
        AddonUser(addon=bundle.obj, user=request.amo_user).save()

        self._icons_and_images(bundle.obj)
        record_action("app-submitted", request, {"app-id": bundle.obj.pk})

        log.info("App created: %s" % bundle.obj.pk)
        return bundle
Ejemplo n.º 38
0
def browserid_authenticate(request, assertion, is_native=False,
                           browserid_audience=get_audience):
    """
    Verify a BrowserID login attempt. If the BrowserID assertion is
    good, but no account exists, create one.

    """
    url = settings.BROWSERID_VERIFICATION_URL

    # We must always force the Firefox OS identity provider. This is because
    # we are sometimes allowing unverified assertions and you can't mix that
    # feature with bridged IdPs. See bug 910938.
    extra_params = {}
    if settings.UNVERIFIED_ISSUER:
        extra_params['experimental_forceIssuer'] = settings.UNVERIFIED_ISSUER

    if is_native:
        # When persona is running native on B2G then we can allow unverified
        # assertions.
        url = settings.NATIVE_BROWSERID_VERIFICATION_URL
        extra_params['experimental_allowUnverified'] = 'true'

    log.debug('Verifying Persona at %s, audience: %s, '
              'extra_params: %s' % (url, browserid_audience, extra_params))
    result = verify(assertion, browserid_audience,
                    url=url, extra_params=extra_params)
    if not result:
        return None, _('Persona authentication failure.')

    if 'unverified-email' in result:
        email = result['unverified-email']
        verified = False
    else:
        email = result['email']
        verified = True

    try:
        profile = UserProfile.objects.filter(email=email)[0]
    except IndexError:
        profile = None

    if profile:
        # Added due to bug 905984. It's possible to have a UserProfile
        # that has no corresponding User object.
        if profile.user is None:
            profile.create_django_user(
                backend='django_browserid.auth.BrowserIDBackend')
        if profile.is_verified and not verified:
            # An attempt to log in to a verified address with an unverified
            # assertion is a very bad thing. However, the same email address
            # can legitimately be used on the site on desktop and be verified
            # whilst be used on b2g and be unverified. We are forcing the
            # issuer, so this shouldn't be an issue.
            #
            # Blame kumar. Or cvan. Or deal with it.
            log.debug('Verified user %s attempted to log in with an '
                      'unverified assertion!' % profile)
        else:
            profile.is_verified = verified
            profile.save()

        backend = 'django_browserid.auth.BrowserIDBackend'
        if getattr(profile.user, 'backend', None) != backend:
            profile.user.backend = backend
            profile.user.save()

        return profile, None

    username = autocreate_username(email.partition('@')[0])
    source = (amo.LOGIN_SOURCE_MMO_BROWSERID if settings.MARKETPLACE else
              amo.LOGIN_SOURCE_AMO_BROWSERID)
    profile = UserProfile.objects.create(username=username, email=email,
                                         source=source, display_name=username,
                                         is_verified=verified)
    profile.create_django_user(
        backend='django_browserid.auth.BrowserIDBackend')
    log_cef('New Account', 5, request, username=username,
            signature='AUTHNOTICE',
            msg='User created a new account (from Persona)')
    record_action('new-user', request)
    return profile, None
Ejemplo n.º 39
0
def browserid_authenticate(request,
                           assertion,
                           is_mobile=False,
                           browserid_audience=get_audience):
    """
    Verify a BrowserID login attempt. If the BrowserID assertion is
    good, but no account exists, create one.

    """
    url = settings.BROWSERID_VERIFICATION_URL

    # We must always force the Firefox OS identity provider. This is because
    # we are sometimes allowing unverified assertions and you can't mix that
    # feature with bridged IdPs. See bug 910938.
    extra_params = {}
    if settings.UNVERIFIED_ISSUER:
        extra_params['experimental_forceIssuer'] = settings.UNVERIFIED_ISSUER

    if is_mobile:
        # When persona is running in a mobile OS then we can allow unverified
        # assertions.
        url = settings.NATIVE_BROWSERID_VERIFICATION_URL
        extra_params['experimental_allowUnverified'] = 'true'

    log.debug('Verifying Persona at %s, audience: %s, '
              'extra_params: %s' % (url, browserid_audience, extra_params))
    result = verify(assertion,
                    browserid_audience,
                    url=url,
                    extra_params=extra_params)
    if not result:
        return None, _('Persona authentication failure.')

    if 'unverified-email' in result:
        email = result['unverified-email']
        verified = False
    else:
        email = result['email']
        verified = True

    try:
        profile = UserProfile.objects.filter(email=email)[0]
    except IndexError:
        profile = None

    if profile:
        # Added due to bug 905984. It's possible to have a UserProfile
        # that has no corresponding User object.
        if profile.user is None:
            profile.create_django_user(
                backend='django_browserid.auth.BrowserIDBackend')
        if profile.is_verified and not verified:
            # An attempt to log in to a verified address with an unverified
            # assertion is a very bad thing. However, the same email address
            # can legitimately be used on the site on desktop and be verified
            # whilst be used on b2g and be unverified. We are forcing the
            # issuer, so this shouldn't be an issue.
            #
            # Blame kumar. Or cvan. Or deal with it.
            log.debug('Verified user %s attempted to log in with an '
                      'unverified assertion!' % profile)
        else:
            profile.is_verified = verified
            profile.save()

        backend = 'django_browserid.auth.BrowserIDBackend'
        if getattr(profile.user, 'backend', None) != backend:
            profile.user.backend = backend
            profile.user.save()

        return profile, None

    username = autocreate_username(email.partition('@')[0])
    source = (amo.LOGIN_SOURCE_MMO_BROWSERID
              if settings.MARKETPLACE else amo.LOGIN_SOURCE_AMO_BROWSERID)
    profile = UserProfile.objects.create(username=username,
                                         email=email,
                                         source=source,
                                         display_name=username,
                                         is_verified=verified)
    profile.create_django_user(
        backend='django_browserid.auth.BrowserIDBackend')
    log_cef('New Account',
            5,
            request,
            username=username,
            signature='AUTHNOTICE',
            msg='User created a new account (from Persona)')
    record_action('new-user', request)
    return profile, None
Ejemplo n.º 40
0
def details(request, addon_id, addon):
    # Name, Slug, Description, Privacy Policy, Homepage URL, Support URL,
    # Support Email.
    form_basic = AppDetailsBasicForm(request.POST or None,
                                     instance=addon,
                                     request=request)
    form_cats = CategoryForm(request.POST or None,
                             product=addon,
                             request=request)
    form_icon = AppFormMedia(request.POST or None,
                             request.FILES or None,
                             instance=addon,
                             request=request)
    form_previews = PreviewFormSet(request.POST or None,
                                   prefix='files',
                                   queryset=addon.get_previews())

    # For empty webapp-locale (or no-locale) fields that have
    # form-locale values, duplicate them to satisfy the requirement.
    form_locale = request.COOKIES.get('current_locale', '')
    app_locale = to_language(addon.default_locale)
    for name, value in request.POST.items():
        if value:
            if name.endswith(form_locale):
                basename = name[:-len(form_locale)]
            else:
                basename = name + '_'
            othername = basename + app_locale
            if not request.POST.get(othername, None):
                request.POST[othername] = value
    forms = {
        'form_basic': form_basic,
        'form_cats': form_cats,
        'form_icon': form_icon,
        'form_previews': form_previews,
    }

    if request.POST and all(f.is_valid() for f in forms.itervalues()):
        addon = form_basic.save(addon)
        form_cats.save()
        form_icon.save(addon)
        for preview in form_previews.forms:
            preview.save(addon)

        # If this is an incomplete app from the legacy submission flow, it may
        # not have device types set yet - so assume it works everywhere.
        if not addon.device_types:
            for device in amo.DEVICE_TYPES:
                addon.addondevicetype_set.create(device_type=device)

        AppSubmissionChecklist.objects.get(addon=addon).update(details=True)

        make_public = (amo.PUBLIC_IMMEDIATELY
                       if form_basic.cleaned_data.get('publish') else
                       amo.PUBLIC_WAIT)

        # Free apps get pushed for review.
        if addon.premium_type == amo.ADDON_FREE:
            # The developer doesn't want the app published immediately upon
            # review.
            addon.update(status=amo.STATUS_PENDING, make_public=make_public)
        else:
            # Paid apps get STATUS_NULL until payment information has been
            # entered.
            addon.update(status=amo.STATUS_NULL,
                         highest_status=amo.STATUS_PENDING,
                         make_public=make_public)

            # Mark the app as excluded in regions that don't support payments.
            for region in mkt.regions.ALL_REGIONS:
                if not region.has_payments:
                    AddonExcludedRegion.objects.get_or_create(addon=addon,
                                                              region=region.id)
        record_action('app-submitted', request, {'app-id': addon.pk})

        return redirect('submit.app.done', addon.app_slug)

    ctx = {
        'step': 'details',
        'addon': addon,
    }
    ctx.update(forms)
    return jingo.render(request, 'submit/details.html', ctx)
Ejemplo n.º 41
0
def browserid_authenticate(request, assertion, is_mobile=False, browserid_audience=get_audience):
    """
    Verify a BrowserID login attempt. If the BrowserID assertion is
    good, but no account exists, create one.

    """
    url = settings.BROWSERID_VERIFICATION_URL

    # We must always force the Firefox OS identity provider. This is because
    # we are sometimes allowing unverified assertions and you can't mix that
    # feature with bridged IdPs. See bug 910938.
    extra_params = {}
    if settings.UNVERIFIED_ISSUER:
        extra_params["experimental_forceIssuer"] = settings.UNVERIFIED_ISSUER

    if is_mobile:
        # When persona is running in a mobile OS then we can allow unverified
        # assertions.
        url = settings.NATIVE_BROWSERID_VERIFICATION_URL
        extra_params["experimental_allowUnverified"] = "true"

    log.debug("Verifying Persona at %s, audience: %s, " "extra_params: %s" % (url, browserid_audience, extra_params))
    result = verify(assertion, browserid_audience, url=url, extra_params=extra_params)
    if not result:
        return None, _("Persona authentication failure.")

    if "unverified-email" in result:
        email = result["unverified-email"]
        verified = False
    else:
        email = result["email"]
        verified = True

    try:
        profile = UserProfile.objects.filter(email=email)[0]
    except IndexError:
        profile = None

    if profile:
        # Added due to bug 905984. It's possible to have a UserProfile
        # that has no corresponding User object.
        if profile.user is None:
            profile.create_django_user(backend="django_browserid.auth.BrowserIDBackend")
        if profile.is_verified and not verified:
            # An attempt to log in to a verified address with an unverified
            # assertion is a very bad thing. Don't let that happen.
            log.debug("Verified user %s attempted to log in with an " "unverified assertion!" % profile)
            return None, _("Please use the verified email for this account.")
        else:
            profile.is_verified = verified
            profile.save()

        backend = "django_browserid.auth.BrowserIDBackend"
        if getattr(profile.user, "backend", None) != backend:
            profile.user.backend = backend
            profile.user.save()

        return profile, None

    username = autocreate_username(email.partition("@")[0])
    source = amo.LOGIN_SOURCE_MMO_BROWSERID if settings.MARKETPLACE else amo.LOGIN_SOURCE_AMO_BROWSERID
    profile = UserProfile.objects.create(
        username=username, email=email, source=source, display_name=username, is_verified=verified
    )
    profile.create_django_user(backend="django_browserid.auth.BrowserIDBackend")
    log_cef(
        "New Account",
        5,
        request,
        username=username,
        signature="AUTHNOTICE",
        msg="User created a new account (from Persona)",
    )
    if settings.MARKETPLACE:
        record_action("new-user", request)
    return profile, None
Ejemplo n.º 42
0
def browserid_authenticate(request,
                           assertion,
                           is_mobile=False,
                           browserid_audience=get_audience):
    """
    Verify a BrowserID login attempt. If the BrowserID assertion is
    good, but no account exists, create one.

    """
    url = settings.BROWSERID_VERIFICATION_URL

    # We must always force the Firefox OS identity provider. This is because
    # we are sometimes allowing unverified assertions and you can't mix that
    # feature with bridged IdPs. See bug 910938.
    extra_params = {}
    if settings.UNVERIFIED_ISSUER:
        extra_params['experimental_forceIssuer'] = settings.UNVERIFIED_ISSUER

    if is_mobile:
        # When persona is running in a mobile OS then we can allow unverified
        # assertions.
        url = settings.NATIVE_BROWSERID_VERIFICATION_URL
        extra_params['experimental_allowUnverified'] = 'true'

    log.debug('Verifying Persona at %s, audience: %s, '
              'extra_params: %s' % (url, browserid_audience, extra_params))
    v = BrowserIDBackend().get_verifier()
    v.verification_service_url = url
    result = v.verify(assertion, browserid_audience, url=url, **extra_params)
    if not result:
        return None, _('Persona authentication failure.')

    if 'unverified-email' in result._response:
        email = result._response['unverified-email']
        verified = False
    else:
        email = result.email
        verified = True

    try:
        profile = UserProfile.objects.filter(email=email)[0]
    except IndexError:
        profile = None

    if profile:
        if profile.is_verified and not verified:
            # An attempt to log in to a verified address with an unverified
            # assertion is a very bad thing. Don't let that happen.
            log.debug('Verified user %s attempted to log in with an '
                      'unverified assertion!' % profile)
            return None, _('Please use the verified email for this account.')
        else:
            profile.is_verified = verified
            profile.save()

        return profile, None

    username = autocreate_username(email.partition('@')[0])
    source = amo.LOGIN_SOURCE_MMO_BROWSERID
    profile = UserProfile.objects.create(username=username,
                                         email=email,
                                         source=source,
                                         display_name=username,
                                         is_verified=verified)
    log_cef('New Account',
            5,
            request,
            username=username,
            signature='AUTHNOTICE',
            msg='User created a new account (from Persona)')
    record_action('new-user', request)

    return profile, None
Ejemplo n.º 43
0
def browserid_authenticate(request,
                           assertion,
                           is_mobile=False,
                           browserid_audience=get_audience):
    """
    Verify a BrowserID login attempt. If the BrowserID assertion is
    good, but no account exists, create one.

    """
    extra_params = {}
    url = settings.NATIVE_FXA_VERIFICATION_URL
    log.debug('Verifying Native FxA at %s, audience: %s, '
              'extra_params: %s' % (url, browserid_audience, extra_params))
    v = BrowserIDBackend().get_verifier()
    v.verification_service_url = url
    result = v.verify(assertion, browserid_audience, url=url, **extra_params)
    if not result:
        return None, _('Native FxA authentication failure.')

    if 'unverified-email' in result._response:
        email = result._response['unverified-email']
        verified = False
    elif (result._response.get('issuer') == settings.NATIVE_FXA_ISSUER
          and 'fxa-verifiedEmail' in result._response.get('idpClaims', {})):
        email = result._response['idpClaims']['fxa-verifiedEmail']
        verified = True
    else:
        email = result.email
        verified = True

    try:
        profile = UserProfile.objects.filter(email=email)[0]
    except IndexError:
        profile = None

    if profile:
        if profile.is_verified and not verified:
            # An attempt to log in to a verified address with an unverified
            # assertion is a very bad thing. Don't let that happen.
            log.debug('Verified user %s attempted to log in with an '
                      'unverified assertion!' % profile)
            return None, _('Please use the verified email for this account.')
        else:
            profile.is_verified = verified
            profile.save()

        return profile, None

    username = autocreate_username(email.partition('@')[0])
    source = amo.LOGIN_SOURCE_MMO_BROWSERID
    profile = UserProfile.objects.create(username=username,
                                         email=email,
                                         source=source,
                                         display_name=username,
                                         is_verified=verified)
    log_cef('New Account',
            5,
            request,
            username=username,
            signature='AUTHNOTICE',
            msg='User created a new account (from Persona)')
    record_action('new-user', request)

    return profile, None
Ejemplo n.º 44
0
def _record(request, addon):
    # TODO(andym): we have an API now, replace this with that.
    logged = request.user.is_authenticated()
    premium = addon.is_premium()

    # Require login for premium.
    if not logged and premium:
        return http.HttpResponseRedirect(reverse('users.login'))

    ctx = {'addon': addon.pk}

    # Don't generate receipts if we're allowing logged-out install.
    if logged:
        is_dev = request.check_ownership(addon,
                                         require_owner=False,
                                         ignore_disabled=True,
                                         admin=False)
        is_reviewer = acl.check_reviewer(request)
        if (not addon.is_webapp()
                or not addon.is_public() and not (is_reviewer or is_dev)):
            raise http.Http404

        if (premium and not addon.has_purchased(request.amo_user)
                and not is_reviewer and not is_dev):
            raise PermissionDenied

        # If you are reviewer, you get a user receipt. Use the reviewer tools
        # to get a reviewer receipt. App developers still get their special
        # receipt.
        install_type = (apps.INSTALL_TYPE_DEVELOPER
                        if is_dev else apps.INSTALL_TYPE_USER)
        # Log the install.
        installed, c = Installed.objects.safer_get_or_create(
            addon=addon, user=request.amo_user, install_type=install_type)

        # Get download source from GET if it exists, if so get the download
        # source object if it exists. Then grab a client data object to hook up
        # with the Installed object.
        download_source = DownloadSource.objects.filter(
            name=request.REQUEST.get('src', None))
        download_source = download_source[0] if download_source else None
        try:
            region = request.REGION.id
        except AttributeError:
            region = mkt.regions.WORLDWIDE.id
        client_data, c = ClientData.objects.get_or_create(
            download_source=download_source,
            device_type=request.POST.get('device_type', ''),
            user_agent=request.META.get('HTTP_USER_AGENT', ''),
            is_chromeless=request.POST.get('chromeless', False),
            language=request.LANG,
            region=region)
        installed.update(client_data=client_data)

        # Look up to see if its in the receipt cache and log if we have
        # to recreate it.
        receipt = memoize_get('create-receipt', installed.pk)
        error = ''
        receipt_cef.log(request, addon, 'request', 'Receipt requested')
        if not receipt:
            receipt_cef.log(request, addon, 'sign', 'Receipt signing')
            try:
                receipt = create_receipt(installed.pk)
            except SigningError:
                error = _('There was a problem installing the app.')

        ctx.update(receipt=receipt, error=error)
    else:
        if not addon.is_public() or not addon.is_webapp():
            raise http.Http404

    amo.log(amo.LOG.INSTALL_ADDON, addon)
    record_action(
        'install', request, {
            'app-domain': addon.domain_from_url(addon.origin),
            'app-id': addon.pk,
            'anonymous': request.user.is_anonymous(),
        })

    return ctx
Ejemplo n.º 45
0
    else:
        buyer_username = autocreate_username(buyer_email.partition('@')[0])
        source = amo.LOGIN_SOURCE_WEBPAY
        user_profile = UserProfile.objects.create(display_name=buyer_username,
                                                  email=buyer_email,
                                                  is_verified=True,
                                                  source=source,
                                                  username=buyer_username)

        log_cef('New Account',
                5,
                request,
                username=buyer_username,
                signature='AUTHNOTICE',
                msg='A new account was created from Webpay (using FxA)')
        record_action('new-user', request)

    log.info('webpay postback: fulfilling purchase for contrib %s with '
             'transaction %s' % (contrib, trans_id))
    app_pay_cef.log(request,
                    'Purchase complete',
                    'purchase_complete',
                    'Purchase complete for: %s' % (contrib.addon.pk),
                    severity=3)

    contrib.update(transaction_id=trans_id,
                   type=amo.CONTRIB_PURCHASE,
                   user=user_profile,
                   amount=Decimal(data['response']['price']['amount']),
                   currency=data['response']['price']['currency'])
Ejemplo n.º 46
0
def details(request, addon_id, addon):
    # Name, Slug, Description, Privacy Policy, Homepage URL, Support URL,
    # Support Email.
    form_basic = AppDetailsBasicForm(request.POST or None,
                                     instance=addon,
                                     request=request)
    form_cats = CategoryForm(request.POST or None,
                             product=addon,
                             request=request)
    form_icon = AppFormMedia(request.POST or None,
                             request.FILES or None,
                             instance=addon,
                             request=request)
    form_previews = PreviewFormSet(request.POST or None,
                                   prefix='files',
                                   queryset=addon.get_previews())

    # For empty webapp-locale (or no-locale) fields that have
    # form-locale values, duplicate them to satisfy the requirement.
    form_locale = request.COOKIES.get('current_locale', '')
    app_locale = to_language(addon.default_locale)
    for name, value in request.POST.items():
        if value:
            if name.endswith(form_locale):
                basename = name[:-len(form_locale)]
            else:
                basename = name + '_'
            othername = basename + app_locale
            if not request.POST.get(othername, None):
                request.POST[othername] = value
    forms = {
        'form_basic': form_basic,
        'form_cats': form_cats,
        'form_icon': form_icon,
        'form_previews': form_previews,
    }
    if request.POST and all(f.is_valid() for f in forms.itervalues()):
        addon = form_basic.save(addon)
        form_cats.save()
        form_icon.save(addon)
        for preview in form_previews.forms:
            preview.save(addon)
        # If this is an incomplete app from the legacy submission flow, it may
        # not have device types set yet - so assume it works everywhere.
        if not addon.device_types:
            for device in mkt.DEVICE_TYPES:
                addon.addondevicetype_set.create(device_type=device)

        AppSubmissionChecklist.objects.get(addon=addon).update(details=True)

        if addon.needs_payment():
            # Paid apps get STATUS_NULL until payment information and content
            # ratings entered.
            addon.update(status=mkt.STATUS_NULL,
                         highest_status=mkt.STATUS_PENDING)

        # Mark as pending in special regions (i.e., China).
        # By default, the column is set to pending when the row is inserted.
        # But we need to set a nomination date so we know to list the app
        # in the China Review Queue now (and sort it by that date too).
        for region in mkt.regions.SPECIAL_REGIONS:
            addon.geodata.set_nominated_date(region, save=True)
            log.info(u'[Webapp:%s] Setting nomination date to '
                     u'now for region (%s).' % (addon, region.slug))

        record_action('app-submitted', request, {'app-id': addon.pk})

        return redirect('submit.app.done', addon.app_slug)

    ctx = {
        'step': 'details',
        'addon': addon,
    }
    ctx.update(forms)
    return render(request, 'submit/details.html', ctx)
Ejemplo n.º 47
0
def details(request, addon_id, addon):
    # Name, Slug, Description, Privacy Policy, Homepage URL, Support URL,
    # Support Email.
    form_basic = AppDetailsBasicForm(request.POST or None, instance=addon,
                                     request=request)
    form_cats = CategoryForm(request.POST or None, product=addon,
                             request=request)
    form_icon = AppFormMedia(request.POST or None, request.FILES or None,
                             instance=addon, request=request)
    form_previews = PreviewFormSet(request.POST or None, prefix='files',
                                   queryset=addon.get_previews())

    # For empty webapp-locale (or no-locale) fields that have
    # form-locale values, duplicate them to satisfy the requirement.
    form_locale = request.COOKIES.get('current_locale', '')
    app_locale = to_language(addon.default_locale)
    for name, value in request.POST.items():
        if value:
            if name.endswith(form_locale):
                basename = name[:-len(form_locale)]
            else:
                basename = name + '_'
            othername = basename + app_locale
            if not request.POST.get(othername, None):
                request.POST[othername] = value
    forms = {
        'form_basic': form_basic,
        'form_cats': form_cats,
        'form_icon': form_icon,
        'form_previews': form_previews,
    }

    if request.POST and all(f.is_valid() for f in forms.itervalues()):
        addon = form_basic.save(addon)
        form_cats.save()
        form_icon.save(addon)
        for preview in form_previews.forms:
            preview.save(addon)

        # If this is an incomplete app from the legacy submission flow, it may
        # not have device types set yet - so assume it works everywhere.
        if not addon.device_types:
            for device in amo.DEVICE_TYPES:
                addon.addondevicetype_set.create(device_type=device)

        AppSubmissionChecklist.objects.get(addon=addon).update(details=True)

        make_public = (amo.PUBLIC_IMMEDIATELY
                       if form_basic.cleaned_data.get('publish')
                       else amo.PUBLIC_WAIT)

        # Free apps get pushed for review.
        if addon.premium_type == amo.ADDON_FREE:
            # The developer doesn't want the app published immediately upon
            # review.
            addon.update(status=amo.STATUS_PENDING,
                         make_public=make_public)
        else:
            # Paid apps get STATUS_NULL until payment information has been
            # entered.
            addon.update(status=amo.STATUS_NULL,
                         highest_status=amo.STATUS_PENDING,
                         make_public=make_public)

            # Mark the app as excluded in regions that don't support payments.
            for region in mkt.regions.ALL_REGIONS:
                if not region.has_payments:
                    AddonExcludedRegion.objects.get_or_create(
                        addon=addon, region=region.id)
        record_action('app-submitted', request, {'app-id': addon.pk})

        return redirect('submit.app.done', addon.app_slug)

    ctx = {
        'step': 'details',
        'addon': addon,
    }
    ctx.update(forms)
    return jingo.render(request, 'submit/details.html', ctx)
Ejemplo n.º 48
0
def _record(request, addon):
    # TODO(andym): we have an API now, replace this with that.
    logged = request.user.is_authenticated()
    premium = addon.is_premium()

    # Require login for premium.
    if not logged and premium:
        return http.HttpResponseRedirect(reverse('users.login'))

    ctx = {'addon': addon.pk}

    # Don't generate receipts if we're allowing logged-out install.
    if logged:
        is_dev = request.check_ownership(addon, require_owner=False,
                                         ignore_disabled=True, admin=False)
        is_reviewer = acl.check_reviewer(request)
        if (not addon.is_webapp() or not addon.is_public() and
            not (is_reviewer or is_dev)):
            raise http.Http404

        if (premium and
            not addon.has_purchased(request.amo_user) and
            not is_reviewer and not is_dev):
            raise PermissionDenied

        # If you are reviewer, you get a user receipt. Use the reviewer tools
        # to get a reviewer receipt. App developers still get their special
        # receipt.
        install_type = (apps.INSTALL_TYPE_DEVELOPER if is_dev
                        else apps.INSTALL_TYPE_USER)
        # Log the install.
        installed, c = Installed.objects.get_or_create(addon=addon,
            user=request.amo_user, install_type=install_type)

        # Get download source from GET if it exists, if so get the download
        # source object if it exists. Then grab a client data object to hook up
        # with the Installed object.
        download_source = DownloadSource.objects.filter(
            name=request.REQUEST.get('src', None))
        download_source = download_source[0] if download_source else None
        try:
            region = request.REGION.id
        except AttributeError:
            region = mkt.regions.WORLDWIDE.id
        client_data, c = ClientData.objects.get_or_create(
            download_source=download_source,
            device_type=request.POST.get('device_type', ''),
            user_agent=request.META.get('HTTP_USER_AGENT', ''),
            is_chromeless=request.POST.get('chromeless', False),
            language=request.LANG,
            region=region)
        installed.update(client_data=client_data)

        error = ''
        receipt_cef.log(request, addon, 'sign', 'Receipt requested')
        try:
            receipt = create_receipt(installed)
        except SigningError:
            error = _('There was a problem installing the app.')

        ctx.update(receipt=receipt, error=error)
    else:
        if not addon.is_public() or not addon.is_webapp():
            raise http.Http404

    amo.log(amo.LOG.INSTALL_ADDON, addon)
    record_action('install', request, {
        'app-domain': addon.domain_from_url(addon.origin, allow_none=True),
        'app-id': addon.pk,
        'anonymous': request.user.is_anonymous(),
    })

    return ctx
Ejemplo n.º 49
0
def browserid_authenticate(request,
                           assertion,
                           is_native=False,
                           browserid_audience=get_audience):
    """
    Verify a BrowserID login attempt. If the BrowserID assertion is
    good, but no account exists, create one.

    """
    url = settings.BROWSERID_VERIFICATION_URL
    extra_params = None
    if is_native:
        # When persona is running native on B2G then we need to
        # verify assertions with the right service.
        # We also need to force the appropriate issuer
        # for potentially unverified emails.
        url = settings.NATIVE_BROWSERID_VERIFICATION_URL
        extra_params = {
            'experimental_forceIssuer': settings.UNVERIFIED_ISSUER or False,
            'experimental_allowUnverified': 'true'
        }

    log.debug('Verifying Persona at %s, audience: %s, '
              'extra_params: %s' % (url, browserid_audience, extra_params))
    result = verify(assertion,
                    browserid_audience,
                    url=url,
                    extra_params=extra_params)
    if not result:
        return None, _('Persona authentication failure.')

    if 'unverified-email' in result:
        email = result['unverified-email']
        verified = False
    else:
        email = result['email']
        verified = True

    try:
        profile = UserProfile.objects.filter(email=email)[0]
    except IndexError:
        profile = None

    if profile:
        if profile.is_verified and not verified:
            # An attempt to log in to a verified address with an unverified
            # assertion is a very bad thing. However, the same email address
            # can legitimately be used on the site on desktop and be verified
            # whilst be used on b2g and be unverified. We are forcing the
            # issuer, so this shouldn't be an issue.
            #
            # Blame kumar. Or cvan. Or deal with it.
            log.debug('Verified user %s attempted to log in with an '
                      'unverified assertion!' % profile)
        else:
            profile.is_verified = verified
            profile.save()

        backend = 'django_browserid.auth.BrowserIDBackend'
        if getattr(profile.user, 'backend', None) != backend:
            profile.user.backend = backend
            profile.user.save()

        return profile, None

    username = autocreate_username(email.partition('@')[0])
    source = (amo.LOGIN_SOURCE_MMO_BROWSERID
              if settings.MARKETPLACE else amo.LOGIN_SOURCE_AMO_BROWSERID)
    profile = UserProfile.objects.create(username=username,
                                         email=email,
                                         source=source,
                                         display_name=username,
                                         is_verified=verified)
    profile.create_django_user(
        backend='django_browserid.auth.BrowserIDBackend')
    log_cef('New Account',
            5,
            request,
            username=username,
            signature='AUTHNOTICE',
            msg='User created a new account (from Persona)')
    record_action('new-user', request)
    return profile, None
Ejemplo n.º 50
0
def add(request, addon):
    if addon.has_author(request.user):
        # Don't let app owners review their own apps.
        raise PermissionDenied

    if (request.user.is_authenticated() and
            request.method == 'GET' and (not request.MOBILE or request.TABLET)):
        return detail(request, app_slug=addon.app_slug, add_review=True)

    # Get user agent of user submitting review. If there is an install with
    # logged user agent that matches the current user agent, hook up that
    # install's client data with the rating. If there aren't any install that
    # match, use the most recent install. This implies that user must have an
    # install to submit a review, but not sure if that logic is worked in, so
    # default client_data to None.
    client_data = None
    user_agent = request.META.get('HTTP_USER_AGENT', '')
    install = (Installed.objects.filter(user=request.user, addon=addon)
                                .order_by('-created'))
    install_w_user_agent = (install.filter(client_data__user_agent=user_agent)
                                   .order_by('-created'))
    has_review = False
    try:
        if install_w_user_agent:
            client_data = install_w_user_agent[0].client_data
        elif install:
            client_data = install[0].client_data
    except ClientData.DoesNotExist:
        client_data = None

    data = request.POST or None

    # Try to get an existing review of the app by this user if we can.
    filters = dict(addon=addon, user=request.user)
    if addon.is_packaged:
        filters['version'] = addon.current_version

    try:
        existing_review = Review.objects.valid().filter(**filters)[0]
    except IndexError:
        existing_review = None

    # If the user is posting back, try to process the submission.
    if data:
        form = ReviewForm(data)
        if form.is_valid():
            cleaned = form.cleaned_data
            if existing_review:
                # If there's a review to overwrite, overwrite it.
                if (cleaned['body'] != existing_review.body or
                    cleaned['rating'] != existing_review.rating):
                    existing_review.body = cleaned['body']
                    existing_review.rating = cleaned['rating']
                    ip = request.META.get('REMOTE_ADDR', '')
                    existing_review.ip_address = ip
                    if 'flag' in cleaned and cleaned['flag']:
                        existing_review.flag = True
                        existing_review.editorreview = True
                        rf = ReviewFlag(review=existing_review,
                                        user_id=request.user.id,
                                        flag=ReviewFlag.OTHER, note='URLs')
                        rf.save()
                    existing_review.save()

                amo.log(amo.LOG.EDIT_REVIEW, addon, existing_review)
                log.debug('[Review:%s] Edited by %s' % (existing_review.id,
                                                        request.user.id))
                messages.success(request,
                                 _('Your review was updated successfully!'))

                # If there is a developer reply to the review, delete it. We do
                # this per bug 777059.
                try:
                    reply = existing_review.replies.all()[0]
                except IndexError:
                    pass
                else:
                    log.debug('[Review:%s] Deleted reply to %s' % (
                        reply.id, existing_review.id))
                    reply.delete()

            else:
                # If there isn't a review to overwrite, create a new review.
                review = Review.objects.create(client_data=client_data,
                                               **_review_details(
                                                   request, addon, form))
                if 'flag' in cleaned and cleaned['flag']:
                    rf = ReviewFlag(review=review, user_id=request.user.id,
                                    flag=ReviewFlag.OTHER, note='URLs')
                    rf.save()
                amo.log(amo.LOG.ADD_REVIEW, addon, review)
                log.debug('[Review:%s] Created by user %s ' %
                          (review.id, request.user.id))
                messages.success(request,
                                 _('Your review was successfully added!'))
                record_action('new-review', request, {'app-id': addon.id})

            return redirect(addon.get_ratings_url('list'))

        # If the form isn't valid, we've set `form` so that it can be used when
        # the template is rendered below.

    elif existing_review:
        # If the user isn't posting back but has an existing review, populate
        # the form with their existing review and rating.
        form = ReviewForm({'rating': existing_review.rating or 1,
                           'body': existing_review.body})
        has_review = True
    else:
        # If the user isn't posting back and doesn't have an existing review,
        # just show a blank version of the form.
        form = ReviewForm()

    # Get app's support url, either from support flow if contribution exists or
    # author's support url.
    support_email = str(addon.support_email) if addon.support_email else None
    try:
        contrib_id = (Contribution.objects
                      .filter(user=request.user, addon=addon,
                              type__in=(amo.CONTRIB_PURCHASE,
                                        amo.CONTRIB_INAPP,
                                        amo.CONTRIB_REFUND))
                      .order_by('-created')[0].id)
        support_url = reverse('support', args=[contrib_id])
    except IndexError:
        support_url = addon.support_url

    return jingo.render(request, 'ratings/add.html',
                        {'product': addon, 'form': form,
                         'support_url': support_url,
                         'has_review': has_review,
                         'support_email': support_email,
                         'page_parent': addon.get_detail_url() if
                                        not existing_review else ''})
Ejemplo n.º 51
0
def browserid_authenticate(request, assertion, is_mobile=False,
                           browserid_audience=get_audience):
    """
    Verify a BrowserID login attempt. If the BrowserID assertion is
    good, but no account exists, create one.

    """
    extra_params = {}
    if waffle.switch_is_active('firefox-accounts'):
        url = settings.NATIVE_FXA_VERIFICATION_URL
    else:
        url = settings.BROWSERID_VERIFICATION_URL

        # We must always force the Firefox OS identity provider. This is
        # because we are sometimes allowing unverified assertions and you
        # can't mix that feature with bridged IdPs. See bug 910938.

        if settings.UNVERIFIED_ISSUER:
            extra_params['experimental_forceIssuer'] = settings.UNVERIFIED_ISSUER

        if is_mobile:
            # When persona is running in a mobile OS then we can allow
            # unverified assertions.
            url = settings.NATIVE_BROWSERID_VERIFICATION_URL
            extra_params['experimental_allowUnverified'] = 'true'

    log.debug('Verifying Persona at %s, audience: %s, '
              'extra_params: %s' % (url, browserid_audience, extra_params))
    v = BrowserIDBackend().get_verifier()
    v.verification_service_url = url
    result = v.verify(assertion, browserid_audience, url=url, **extra_params)
    if not result:
        return None, _('Persona authentication failure.')

    if 'unverified-email' in result._response:
        email = result._response['unverified-email']
        verified = False
    elif (result._response.get('issuer') == settings.NATIVE_FXA_ISSUER and
          'fxa-verifiedEmail' in result._response.get('idpClaims', {})):
        email = result._response['idpClaims']['fxa-verifiedEmail']
        verified = True
    else:
        email = result.email
        verified = True

    try:
        profile = UserProfile.objects.filter(email=email)[0]
    except IndexError:
        profile = None

    if profile:
        if profile.is_verified and not verified:
            # An attempt to log in to a verified address with an unverified
            # assertion is a very bad thing. Don't let that happen.
            log.debug('Verified user %s attempted to log in with an '
                      'unverified assertion!' % profile)
            return None, _('Please use the verified email for this account.')
        else:
            profile.is_verified = verified
            profile.save()

        return profile, None

    username = autocreate_username(email.partition('@')[0])
    source = amo.LOGIN_SOURCE_MMO_BROWSERID
    profile = UserProfile.objects.create(username=username, email=email,
                                         source=source, display_name=username,
                                         is_verified=verified)
    log_cef('New Account', 5, request, username=username,
            signature='AUTHNOTICE',
            msg='User created a new account (from Persona)')
    record_action('new-user', request)

    return profile, None
Ejemplo n.º 52
0
def add(request, addon):
    if addon.has_author(request.user):
        # Don't let app owners review their own apps.
        raise PermissionDenied

    if (request.user.is_authenticated() and request.method == 'GET'
            and (not request.MOBILE or request.TABLET)):
        return detail(request, app_slug=addon.app_slug, add_review=True)

    # Get user agent of user submitting review. If there is an install with
    # logged user agent that matches the current user agent, hook up that
    # install's client data with the rating. If there aren't any install that
    # match, use the most recent install. This implies that user must have an
    # install to submit a review, but not sure if that logic is worked in, so
    # default client_data to None.
    client_data = None
    user_agent = request.META.get('HTTP_USER_AGENT', '')
    install = (Installed.objects.filter(user=request.user,
                                        addon=addon).order_by('-created'))
    install_w_user_agent = (install.filter(
        client_data__user_agent=user_agent).order_by('-created'))
    has_review = False
    try:
        if install_w_user_agent:
            client_data = install_w_user_agent[0].client_data
        elif install:
            client_data = install[0].client_data
    except ClientData.DoesNotExist:
        client_data = None

    data = request.POST or None

    # Try to get an existing review of the app by this user if we can.
    filters = dict(addon=addon, user=request.user)
    if addon.is_packaged:
        filters['version'] = addon.current_version

    try:
        existing_review = Review.objects.valid().filter(**filters)[0]
    except IndexError:
        existing_review = None

    # If the user is posting back, try to process the submission.
    if data:
        form = ReviewForm(data)
        if form.is_valid():
            cleaned = form.cleaned_data
            if existing_review:
                # If there's a review to overwrite, overwrite it.
                if (cleaned['body'] != existing_review.body
                        or cleaned['rating'] != existing_review.rating):
                    existing_review.body = cleaned['body']
                    existing_review.rating = cleaned['rating']
                    ip = request.META.get('REMOTE_ADDR', '')
                    existing_review.ip_address = ip
                    if 'flag' in cleaned and cleaned['flag']:
                        existing_review.flag = True
                        existing_review.editorreview = True
                        rf = ReviewFlag(review=existing_review,
                                        user_id=request.user.id,
                                        flag=ReviewFlag.OTHER,
                                        note='URLs')
                        rf.save()
                    existing_review.save()

                amo.log(amo.LOG.EDIT_REVIEW, addon, existing_review)
                log.debug('[Review:%s] Edited by %s' %
                          (existing_review.id, request.user.id))
                messages.success(request,
                                 _('Your review was updated successfully!'))
            else:
                # If there isn't a review to overwrite, create a new review.
                review = Review.objects.create(client_data=client_data,
                                               **_review_details(
                                                   request, addon, form))
                if 'flag' in cleaned and cleaned['flag']:
                    rf = ReviewFlag(review=review,
                                    user_id=request.user.id,
                                    flag=ReviewFlag.OTHER,
                                    note='URLs')
                    rf.save()
                amo.log(amo.LOG.ADD_REVIEW, addon, review)
                log.debug('[Review:%s] Created by user %s ' %
                          (review.id, request.user.id))
                messages.success(request,
                                 _('Your review was successfully added!'))
                record_action('new-review', request, {'app-id': addon.id})

            return redirect(addon.get_ratings_url('list'))

        # If the form isn't valid, we've set `form` so that it can be used when
        # the template is rendered below.

    elif existing_review:
        # If the user isn't posting back but has an existing review, populate
        # the form with their existing review and rating.
        form = ReviewForm({
            'rating': existing_review.rating or 1,
            'body': existing_review.body
        })
        has_review = True
    else:
        # If the user isn't posting back and doesn't have an existing review,
        # just show a blank version of the form.
        form = ReviewForm()

    support_email = str(addon.support_email) if addon.support_email else None
    return jingo.render(
        request, 'ratings/add.html', {
            'product': addon,
            'form': form,
            'support_url': addon.support_url,
            'has_review': has_review,
            'support_email': support_email,
            'page_parent':
            addon.get_detail_url() if not existing_review else ''
        })