Esempio n. 1
0
def unsubscribe(request):
    token = request.REQUEST.get('token', '')
    email = request.REQUEST.get('email')

    unsubscribe_all_link = 'http://{}/unsubscribe?'.format(settings.DOMAIN) + urlencode({
        'action': 'ALL',
        'token': util.token(email),
        'email': email,
    })

    ctx = {
        'token': token,
        'email': email,

        'unsubscribed': False,
        'unsubscribed_on_get': False,
        'unsubscribed_settings': None,
        'user': None,
        'error': False,
        'action': request.REQUEST.get('action'),
        'unsubscribe_all_link': unsubscribe_all_link,
    }

    template_name = 'unsubscribe.html'

    if email and util.token(email) == token:
        # No user_id associated with the sent email, unsubscribe this email address from all email
        find_user = User.objects.filter(email=email)
        # If there is one and only one user with that email address, then pick them, otherwise we'll fall back to just an email address
        user = ctx['unsubscribing_user'] = find_user[0] if find_user.count() == 1 else None
    else:
        ctx['error'] = True
        return r2r_jinja(template_name, ctx, request)

    all_actions = EmailChannel.all_handled_actions()

    if user:
        # Support for unsubscribe headers.
        # We support passing in 'actions'
        action = request.REQUEST.get('action')
        if action and (action in EmailChannel.all_handled_actions() or action.upper() == 'ALL'):
            ctx['unsubscribed_on_get'] = ctx['unsubscribed'] = True
            user.kv.subscriptions.unsubscribe(action)
            Metrics.unsubscribe_action.record(request, action=action, method=request.method)

        if request.method == 'POST':
            # Handle the 'ALL' case separately because the semantics for it are inverted.
            # ie, if ALL is checked, it means to DISABLE. While if REMIXED is checked, it means ENABLE.
            handle_unsubscribe_post(user, request.REQUEST, request)

        # We use this dictionary to render the checkboxes in the html.
        ctx['unsubscribed'] = ctx['unsubscribed'] or get_unsubscriptions(user, all_actions)

        ctx['unsubscribed_settings'] = get_unsubscriptions(user)
        template_name = 'unsubscribe_for_user.html'
    else:
        ctx['error'] = True
        return r2r_jinja(template_name, ctx, request)

    return r2r_jinja(template_name, ctx, request)
Esempio n. 2
0
 def make_action_unsubscribe_link(self, action, recipient):
     if settings.PROJECT == 'drawquest':
         #TODO individual action unsubscriptions: action instead of 'ALL'
         return '{}/unsubscribe?action={}&token={}&email={}'.format(
             "http://" + settings.DOMAIN, 'ALL',
             util.token(recipient.email), recipient.email)
     else:
         return string.Template(
             "$absolute_path/unsubscribe?action=$action&token=$token&user_id=$user_id"
         ).substitute(
             dict(absolute_path="http://" + settings.DOMAIN,
                  action=action,
                  user_id=recipient.id,
                  token=util.token(recipient.id)), )
 def test_unsubscribe_page_without_user_id(self):
     user = create_user()
     resp = self.get('/unsubscribe?' + urllib.urlencode({
         'token': util.token(user.email),
         'email': user.email,
     }))
     self.assertNumCssMatches(0, resp, 'input[name="user_id"]')
Esempio n. 4
0
 def make_thread_unsubscribe_link(self, comment, recipient):
     return string.Template("$absolute_path/unsubscribe?post=$post&token=$token&user_id=$user_id").substitute(
         dict(absolute_path="http://" + settings.DOMAIN,
              post=comment.thread.op.id,
              user_id=recipient.id,
              token=util.token(recipient.id)),
     )
Esempio n. 5
0
 def make_thread_unsubscribe_link(self, comment, recipient):
     return string.Template(
         "$absolute_path/unsubscribe?post=$post&token=$token&user_id=$user_id"
     ).substitute(
         dict(absolute_path="http://" + settings.DOMAIN,
              post=comment.thread.op.id,
              user_id=recipient.id,
              token=util.token(recipient.id)), )
Esempio n. 6
0
 def test_unsubscribe_page_without_user_id(self):
     user = create_user()
     resp = self.get('/unsubscribe?' +
                     urllib.urlencode({
                         'token': util.token(user.email),
                         'email': user.email,
                     }))
     self.assertNumCssMatches(0, resp, 'input[name="user_id"]')
 def make_action_unsubscribe_link(self, action, recipient):
     if settings.PROJECT == "drawquest":
         # TODO individual action unsubscriptions: action instead of 'ALL'
         return "http://{}/unsubscribe?".format(settings.DOMAIN) + urlencode(
             {"action": action, "token": util.token(recipient.email), "email": recipient.email}
         )
     else:
         return string.Template(
             "$absolute_path/unsubscribe?action=$action&token=$token&user_id=$user_id"
         ).substitute(
             dict(
                 absolute_path="http://" + settings.DOMAIN,
                 action=action,
                 user_id=recipient.id,
                 token=util.token(recipient.id),
             )
         )
Esempio n. 8
0
def unsubscribe(request):
    token = request.REQUEST.get('token', '')
    email = request.REQUEST.get('email')

    ctx = {
        'token': token,
        'email': email,
        'unsubscribed': False,
        'unsubscribed_on_get': False,
        'unsubscribed_settings': None,
        'user': None,
        'error': False,
    }

    template_name = 'unsubscribe.html'

    if email and util.token(email) == token:
        # No user_id associated with the sent email, unsubscribe this email address from all email
        find_user = User.objects.filter(email=email)
        # If there is one and only one user with that email address, then pick them, otherwise we'll fall back to just an email address
        user = ctx['user'] = find_user[0] if find_user.count() == 1 else None
    else:
        ctx['error'] = True
        return r2r_jinja(template_name, ctx, request)

    all_actions = EmailChannel.all_handled_actions()

    if user:
        # Support for unsubscribe headers.
        # We support passing in 'actions'
        action = request.REQUEST.get('action')
        if action and (action in EmailChannel.all_handled_actions()
                       or action.upper() == 'ALL'):
            ctx['unsubscribed_on_get'] = ctx['unsubscribed'] = True
            user.kv.subscriptions.unsubscribe(action)
            Metrics.unsubscribe_action.record(request,
                                              action=action,
                                              method=request.method)

        if request.method == 'POST':
            # Handle the 'ALL' case separately because the semantics for it are inverted.
            # ie, if ALL is checked, it means to DISABLE. While if REMIXED is checked, it means ENABLE.
            handle_unsubscribe_post(user, request.REQUEST, request)

        # We use this dictionary to render the checkboxes in the html.
        ctx['unsubscribed'] = ctx['unsubscribed'] or get_unsubscriptions(
            user, all_actions)

        ctx['unsubscribed_settings'] = get_unsubscriptions(user)
        template_name = 'unsubscribe_for_user.html'
    else:
        unsubscribe_newsletter(email)
        ctx['unsubscribed'] = True
        Metrics.unsubscribe_email_address.record(request)

    return r2r_jinja(template_name, ctx, request)
    def test_email_token_allows_unsubscribe_from_all(self):
        email = "*****@*****.**"
        url = "/unsubscribe?" + urllib.urlencode({
            'token': util.token(email),
            'email': email,
        })

        self.assertFalse(EmailUnsubscribe.objects.get_or_none(email=email))
        self.assertStatus(200, url, user=AnonymousUser())
        self.assertTrue(EmailUnsubscribe.objects.get_or_none(email=email))
Esempio n. 10
0
    def test_email_token_allows_unsubscribe_from_all(self):
        email = "*****@*****.**"
        url = "/unsubscribe?" + urllib.urlencode({
            'token': util.token(email),
            'email': email,
        })

        self.assertFalse(EmailUnsubscribe.objects.get_or_none(email=email))
        self.assertStatus(200, url, user=AnonymousUser())
        self.assertTrue(EmailUnsubscribe.objects.get_or_none(email=email))
    def test_email_token_that_corresponds_to_user_allows_from_channel(self):
        user = create_user()
        url = "/unsubscribe?" + urllib.urlencode({
            'action': 'remixed',
            'token': util.token(user.email),
            'email': user.email,
        })

        self.assertTrue(user.kv.subscriptions.can_receive('remixed'))
        self.assertStatus(200, url, user=AnonymousUser())
        self.assertFalse(user.kv.subscriptions.can_receive('remixed'))
    def test_user_id_token_allows_unsubscribe(self):
        user = create_user()
        url = "/unsubscribe?" + urllib.urlencode({
            'action': 'remixed',
            'token': util.token(user.id),
            'user_id': user.id,
        })

        self.assertTrue(user.kv.subscriptions.can_receive('remixed'))
        self.assertStatus(200, url, user=AnonymousUser())
        self.assertFalse(user.kv.subscriptions.can_receive('remixed'))
Esempio n. 13
0
 def make_action_unsubscribe_link(self, action, recipient):
     if settings.PROJECT == 'drawquest':
         #TODO individual action unsubscriptions: action instead of 'ALL'
         return '{}/unsubscribe?action={}&token={}&email={}'.format("http://" + settings.DOMAIN, 'ALL', util.token(recipient.email), recipient.email)
     else:
         return string.Template("$absolute_path/unsubscribe?action=$action&token=$token&user_id=$user_id").substitute(
             dict(absolute_path="http://" + settings.DOMAIN,
                  action=action,
                  user_id=recipient.id,
                  token=util.token(recipient.id)),
         )
Esempio n. 14
0
    def test_user_id_token_allows_unsubscribe(self):
        user = create_user()
        url = "/unsubscribe?" + urllib.urlencode({
            'action': 'remixed',
            'token': util.token(user.id),
            'user_id': user.id,
        })

        self.assertTrue(user.kv.subscriptions.can_receive('remixed'))
        self.assertStatus(200, url, user=AnonymousUser())
        self.assertFalse(user.kv.subscriptions.can_receive('remixed'))
Esempio n. 15
0
    def test_email_token_that_corresponds_to_user_allows_from_channel(self):
        user = create_user()
        url = "/unsubscribe?" + urllib.urlencode(
            {
                'action': 'remixed',
                'token': util.token(user.email),
                'email': user.email,
            })

        self.assertTrue(user.kv.subscriptions.can_receive('remixed'))
        self.assertStatus(200, url, user=AnonymousUser())
        self.assertFalse(user.kv.subscriptions.can_receive('remixed'))
Esempio n. 16
0
def unsubscribe(request):
    token = request.REQUEST.get('token', '')
    email = request.REQUEST.get('email')
    user_id = request.REQUEST.get('user_id')

    token_user = User.objects.get_or_none(id=user_id) if user_id else None

    unsubscribed = False
    unsubscribed_on_get = False

    if user_id and util.token(user_id) == token and token_user:
        user = token_user

    elif email and util.token(email) == token:
        # No user_id associated with the sent email, unsubscribe this email address from all email
        find_user = User.objects.filter(email=email)
        # If there is one and only one user with that email address, then pick them, otherwise we'll fall back to just an email address
        user = find_user[0] if find_user.count() == 1 else None

    elif request.user.is_authenticated():
        # Token mismatch, but we have a logged in user.
        user = request.user

    else:
        error = True
        return r2r('unsubscribe.django.html', locals())

    all_actions = EmailChannel.all_handled_actions()

    if user:
        subscriptions = user.kv.subscriptions

        # We need to handle any posts that are passed in the URL
        comment_id = request.GET.get('post')
        if comment_id:
            try:
                unsubscribed_post = Comment.objects.get(pk=int(comment_id))
            except ObjectDoesNotExist:
                pass
            else:
                user.redis.mute_thread(unsubscribed_post)
                unsubscribed_from_thread = unsubscribed_on_get = unsubscribed = True
                Metrics.mute_thread.record(request)

        # Support for unsubscribe headers.
        # We support passing in 'actions'
        action = request.REQUEST.get('action')
        if action and action in EmailChannel.all_handled_actions():
            unsubscribed_on_get = unsubscribed = True
            user.kv.subscriptions.unsubscribe(action)
            Metrics.unsubscribe_action.record(request, action=action, method=request.method)

        if request.method == 'POST':
            # Handle the 'ALL' case separately because the semantics for it are inverted.
            # ie, if ALL is checked, it means to DISABLE. While if REMIXED is checked, it means ENABLE.
            handle_unsubscribe_post(user, request.REQUEST, request)

        # We use this dictionary to render the checkboxes in the html.
        unsubscribed = unsubscribed or get_unsubscriptions(user, all_actions)

        unsubscribed_settings = get_unsubscriptions(user)
    else:
        unsubscribe_newsletter(email)
        unsubscribed = True
        Metrics.unsubscribe_email_address.record(request)

    return r2r('unsubscribe.django.html', locals())