Beispiel #1
0
def favorite(request):
    """
    Add this item to the user's favorites. Return OK.
    """

    action = request.POST.get('action', 'favorite')

    asset_id = request.POST.get('asset_id')
    if not asset_id:
        raise http.Http404

    typepad.client.batch_request()
    request.typepad_user = get_user(request)
    asset = models.Asset.get_by_url_id(asset_id)
    typepad.client.complete_batch()

    if action == 'favorite':
        fav = models.Favorite()
        fav.in_reply_to = asset.asset_ref
        request.typepad_user.favorites.post(fav)
        signals.favorite_created.send(sender=favorite, instance=fav, parent=asset,
            group=request.group)
    else:
        typepad.client.batch_request()
        fav = models.Favorite.get_by_user_asset(request.typepad_user.url_id, asset_id)
        typepad.client.complete_batch()
        fav.delete()
        signals.favorite_deleted.send(sender=favorite, instance=fav,
            parent=asset, group=request.group)

    return http.HttpResponse('OK')
Beispiel #2
0
def upload_complete(request):
    """
    Callback after uploading directly to TypePad which verifies the response
    as 'okay' or displays an error message page to the user.
    """
    status = request.GET['status']
    if status == '201' or status == '200':
        # Signal that a new object has been created
        parts = urlparse(request.GET['asset_url'])
        instance = models.Asset.get(parts[2], batch=False)
        request.flash.add('notices', _('Thanks for the %(type)s!') \
            % { 'type': instance.type_label.lower() })
        signals.asset_created.send(sender=upload_complete, instance=instance,
            group=request.group)
        # Redirect to clear the GET data
        if settings.FEATURED_MEMBER:
            typepad.client.batch_request()
            user = get_user(request)
            typepad.client.complete_batch()
            if not user.is_authenticated() or not user.is_featured_member:
                return HttpResponseRedirect(reverse('group_events'))
        return HttpResponseRedirect(reverse('home'))
    return render_to_response('motion/error.html', {
        'message': request.GET['error'],
    }, context_instance=RequestContext(request))
Beispiel #3
0
def direct_to_template(request, template, extra_context=None, mimetype=None, **kwargs):
    """
    Render a given template with any extra URL parameters in the context as
    ``{{ params }}``.
    """
    if extra_context is None: extra_context = {}
    dictionary = {'params': kwargs}
    for key, value in extra_context.items():
        if callable(value):
            dictionary[key] = value()
        else:
            dictionary[key] = value
    c = RequestContext(request, dictionary)

    if not hasattr(request, 'typepad_user') or not request.typepad_user:
        typepad.client.batch_request()
        user = get_user(request)
        typepad.client.complete_batch()
        request.typepad_user = user

    c.update({
        'user': _PlainUserWarningProxy(request.typepad_user),
        'typepad_user': request.typepad_user,
        'request': request,
    })

    t = loader.get_template(template)
    return HttpResponse(t.render(c), mimetype=mimetype)
Beispiel #4
0
def crosspost_options(request):
    """
    Add this option to the user's preferred crossposting options.
    Return OK.
    """

    typepad.client.batch_request()
    request.typepad_user = get_user(request)
    typepad.client.complete_batch()

    # Current crossposting options
    co = motion.models.CrosspostOptions.get(request.typepad_user.url_id)
    if co is None:
        co = motion.models.CrosspostOptions(user_id=request.typepad_user.url_id)
    if co.crosspost:
        options = json.loads(co.crosspost)
    else:
        options = []

    # Get checkbox value and if it is checked or unchecked
    value = request.POST.get('option_value')
    if not value:
        raise http.Http404
    checked = request.POST.get('checked') == 'true'

    # Update crossposting options
    if checked and not value in options:
        options.append(value)
    elif value in options:
        options.remove(value)

    co.crosspost = json.dumps(options)
    co.save()

    return http.HttpResponse('OK')
Beispiel #5
0
def upload_complete(request):
    """
    Callback after uploading directly to TypePad which verifies the response
    as 'okay' or displays an error message page to the user.
    """
    status = request.GET['status']
    if status == '201' or status == '200':
        # Signal that a new object has been created
        parts = urlparse(request.GET['asset_url'])
        instance = models.Asset.get(parts[2], batch=False)
        request.flash.add('notices', _('Thanks for the %(type)s!') \
            % { 'type': instance.type_label.lower() })
        signals.asset_created.send(sender=upload_complete,
                                   instance=instance,
                                   group=request.group)
        # Redirect to clear the GET data
        if settings.FEATURED_MEMBER:
            typepad.client.batch_request()
            user = get_user(request)
            typepad.client.complete_batch()
            if not user.is_authenticated() or not user.is_featured_member:
                return HttpResponseRedirect(reverse('group_events'))
        return HttpResponseRedirect(reverse('home'))
    return render_to_response('motion/error.html', {
        'message': request.GET['error'],
    },
                              context_instance=RequestContext(request))
Beispiel #6
0
def home(request, page=1, **kwargs):
    """Display the home page view, based on local configuration.

    The home page may be the list of recent member activity, a featured user's
    profile page, or the recent activity in the group of people you are
    following. Which home page is shown depends on the related settings:

    * If the `FEATURED_MEMBER` setting is set, the home page is the
      `FeaturedMemberView`.
    * Otherwise, if `HOME_MEMBER_EVENTS` is ``True`` and the viewer is logged
      in, the home page is the viewer's `FollowingEventsView`.
    * Otherwise, the home page is the `GroupEventsView`.

    By default there's no `FEATURED_MEMBER` and `HOME_MEMBER_EVENTS` is
    ``False``, so the home page view is the group events view. To always use a
    certain view instead of these rules, change your urlconf to use a
    different view for the home page.

    """
    if settings.FEATURED_MEMBER:
        # Home page is a featured user.
        return FeaturedMemberView(request, settings.FEATURED_MEMBER,
            page=page, view='home', **kwargs)
    if settings.HOME_MEMBER_EVENTS:
        typepad.client.batch_request()
        user = get_user(request)
        typepad.client.complete_batch()
        if user.is_authenticated():
            # Home page is the user's inbox.
            return FollowingEventsView(request, page=page, view='home', **kwargs)
    # Home page is group events.
    return GroupEventsView(request, page=page, view='home', **kwargs)
def browser_upload(request):
    if not hasattr(request, 'typepad_user'):
        typepad.client.batch_request()
        user = get_user(request)
        typepad.client.complete_batch()

        request.typepad_user = user

    if not request.method == 'POST':
        status = moderation_status(request)

        if status == Queue.APPROVED:
            import motion.ajax
            return motion.ajax.upload_url(request)

        url = reverse('moderated_upload_url')
        url = 'for(;;);%s' % url # no third party sites allowed.
        return HttpResponse(url)

    if not request.typepad_user.is_authenticated():
        return HttpResponseForbidden("invalid request")

    data = json.loads(request.POST['asset'])
    tp_asset = typepad.Asset.from_dict(data)

    moderate_post(request, tp_asset)

    return HttpResponseRedirect(reverse('home'))
Beispiel #8
0
def more_comments(request):
    """
    Fetch more comments for the asset and return the HTML
    for the additional comments.
    """

    asset_id = request.GET.get('asset_id')
    offset = int(request.GET.get('offset')) or 1
    if not asset_id or not offset:
        raise http.Http404

    # Fetch more comments!
    typepad.client.batch_request()
    request.typepad_user = get_user(request)
    asset = models.Asset.get_by_url_id(asset_id)
    comments = asset.comments.filter(start_index=offset,
                                     max_results=settings.COMMENTS_PER_PAGE)
    typepad.client.complete_batch()

    ### Moderation
    if moderation:
        id_list = [comment.url_id for comment in comments]
        if id_list:
            approved = moderation.Approved.objects.filter(asset_id__in=id_list)
            approved_ids = [a.asset_id for a in approved]

            suppressed = moderation.Queue.objects.filter(
                asset_id__in=id_list, status=moderation.Queue.SUPPRESSED)
            suppressed_ids = [a.asset_id for a in suppressed]

            flags = moderation.Flag.objects.filter(
                tp_asset_id__in=id_list, user_id=request.typepad_user.url_id)
            flag_ids = [f.tp_asset_id for f in flags]

            for comment in comments:
                if comment.url_id in suppressed_ids:
                    comment.suppress = True
                if comment.url_id in approved_ids:
                    comment.moderation_approved = True
                if comment.url_id in flag_ids:
                    comment.moderation_flagged = True

    # Render HTML for comments
    comment_string = ''
    for comment in comments:
        comment_string += render_to_string(
            'motion/assets/comment.html', {
                'comment': comment,
                'view': 'permalink',
            },
            context_instance=RequestContext(request))

    # Return HTML
    return http.HttpResponse(comment_string)
Beispiel #9
0
def more_comments(request):
    """
    Fetch more comments for the asset and return the HTML
    for the additional comments.
    """

    asset_id = request.GET.get('asset_id')
    offset = int(request.GET.get('offset')) or 1
    if not asset_id or not offset:
        raise http.Http404

    # Fetch more comments!
    typepad.client.batch_request()
    request.typepad_user = get_user(request)
    asset = models.Asset.get_by_url_id(asset_id)
    comments = asset.comments.filter(start_index=offset,
        max_results=settings.COMMENTS_PER_PAGE)
    typepad.client.complete_batch()

    ### Moderation
    if moderation:
        id_list = [comment.url_id for comment in comments]
        if id_list:
            approved = moderation.Approved.objects.filter(asset_id__in=id_list)
            approved_ids = [a.asset_id for a in approved]

            suppressed = moderation.Queue.objects.filter(asset_id__in=id_list,
                status=moderation.Queue.SUPPRESSED)
            suppressed_ids = [a.asset_id for a in suppressed]

            flags = moderation.Flag.objects.filter(tp_asset_id__in=id_list,
                user_id=request.typepad_user.url_id)
            flag_ids = [f.tp_asset_id for f in flags]

            for comment in comments:
                if comment.url_id in suppressed_ids:
                    comment.suppress = True
                if comment.url_id in approved_ids:
                    comment.moderation_approved = True
                if comment.url_id in flag_ids:
                    comment.moderation_flagged = True

    # Render HTML for comments
    comment_string = ''
    for comment in comments:
        comment_string += render_to_string('motion/assets/comment.html', {
            'comment': comment,
            'view': 'permalink',
        }, context_instance=RequestContext(request))

    # Return HTML
    return http.HttpResponse(comment_string)
Beispiel #10
0
 def select_typepad_user(self, request):
     """
     If a session token is found, returns the authenticated TypePad user,
     otherwise, returns the Django AnonymousUser. Replaces any authentication
     middleware.
     """
     from typepadapp.auth import get_user
     request.typepad_user = get_user(request)
     self.context.update({
         'user': _PlainUserWarningProxy(request.typepad_user),
         'typepad_user': request.typepad_user,
         'request': request,
     })
Beispiel #11
0
def edit_profile(request):

    typepad.client.batch_request()
    user = get_user(request)
    typepad.client.complete_batch()

    profile = user.get_profile()
    profileform = typepadapp.forms.LocalProfileForm(request.POST, instance=profile)

    if profileform.is_valid():
        profileform.save()
        return http.HttpResponse(json.dumps({'status': 'success', 'data': 'OK'}))
    else:
        errorfields = [k for k, v in profileform.errors.items()]
        return http.HttpResponse(json.dumps({'status': 'error', 'data': ','.join(errorfields)}))
Beispiel #12
0
def home(request, page=1, **kwargs):
    """Display the home page view, based on local configuration.

    The home page may be the list of recent member activity, a featured user's
    profile page, or the recent activity in the group of people you are
    following. Which home page is shown depends on the related settings:

    * If the `FEATURED_MEMBER` setting is set, the home page is the
      `FeaturedMemberView`.
    * Otherwise, if `HOME_MEMBER_EVENTS` is ``True`` and the viewer is logged
      in, the home page is the viewer's `FollowingEventsView`.
    * Otherwise, the home page is the `GroupEventsView`.

    By default there's no `FEATURED_MEMBER` and `HOME_MEMBER_EVENTS` is
    ``False``, so the home page view is the group events view. To always use a
    certain view instead of these rules, change your urlconf to use a
    different view for the home page.

    """
    if settings.FEATURED_MEMBER:
        # Home page is a featured user.
        return FeaturedMemberView(request,
                                  settings.FEATURED_MEMBER,
                                  page=page,
                                  view='home',
                                  **kwargs)
    if settings.HOME_MEMBER_EVENTS:
        typepad.client.batch_request()
        user = get_user(request)
        typepad.client.complete_batch()
        if user.is_authenticated():
            # Home page is the user's inbox.
            return FollowingEventsView(request,
                                       page=page,
                                       view='home',
                                       **kwargs)
    # Home page is group events.
    return GroupEventsView(request, page=page, view='home', **kwargs)
Beispiel #13
0
def edit_profile(request):

    typepad.client.batch_request()
    user = get_user(request)
    typepad.client.complete_batch()

    profile = user.get_profile()
    profileform = typepadapp.forms.LocalProfileForm(request.POST,
                                                    instance=profile)

    if profileform.is_valid():
        profileform.save()
        return http.HttpResponse(
            json.dumps({
                'status': 'success',
                'data': 'OK'
            }))
    else:
        errorfields = [k for k, v in profileform.errors.items()]
        return http.HttpResponse(
            json.dumps({
                'status': 'error',
                'data': ','.join(errorfields)
            }))
Beispiel #14
0
def favorite(request):
    """
    Add this item to the user's favorites. Return OK.
    """

    action = request.POST.get('action', 'favorite')

    asset_id = request.POST.get('asset_id')
    if not asset_id:
        raise http.Http404

    typepad.client.batch_request()
    request.typepad_user = get_user(request)
    asset = models.Asset.get_by_url_id(asset_id)
    typepad.client.complete_batch()

    if action == 'favorite':
        fav = models.Favorite()
        fav.in_reply_to = asset.asset_ref
        request.typepad_user.favorites.post(fav)
        signals.favorite_created.send(sender=favorite,
                                      instance=fav,
                                      parent=asset,
                                      group=request.group)
    else:
        typepad.client.batch_request()
        fav = models.Favorite.get_by_user_asset(request.typepad_user.url_id,
                                                asset_id)
        typepad.client.complete_batch()
        fav.delete()
        signals.favorite_deleted.send(sender=favorite,
                                      instance=fav,
                                      parent=asset,
                                      group=request.group)

    return http.HttpResponse('OK')
Beispiel #15
0
def crosspost_options(request):
    """
    Add this option to the user's preferred crossposting options.
    Return OK.
    """

    typepad.client.batch_request()
    request.typepad_user = get_user(request)
    typepad.client.complete_batch()

    # Current crossposting options
    co = motion.models.CrosspostOptions.get(request.typepad_user.url_id)
    if co is None:
        co = motion.models.CrosspostOptions(
            user_id=request.typepad_user.url_id)
    if co.crosspost:
        options = json.loads(co.crosspost)
    else:
        options = []

    # Get checkbox value and if it is checked or unchecked
    value = request.POST.get('option_value')
    if not value:
        raise http.Http404
    checked = request.POST.get('checked') == 'true'

    # Update crossposting options
    if checked and not value in options:
        options.append(value)
    elif value in options:
        options.remove(value)

    co.crosspost = json.dumps(options)
    co.save()

    return http.HttpResponse('OK')
Beispiel #16
0
def asset_post(request):
    """Ajax interface for creating a post or comment."""

    post_type = request.POST.get('post_type', None)
    if post_type is None:
        raise Exception("post_type is a required parameter")

    if post_type == 'comment':
        frm = CommentForm(request.POST)
        if frm.is_valid():
            postid = request.POST.get('parent', None)
            if postid is None:
                raise Exception("parent is a required parameter")

            typepad.client.batch_request()
            user = get_user(request)
            asset = models.Asset.get_by_url_id(postid)
            typepad.client.complete_batch()

            if not user.is_authenticated():
                raise Exception("not authorized")

            request.typepad_user = user
            comment = frm.save()
            comment.in_reply_to = asset.asset_ref

            ### Moderation
            if moderation:
                from moderation import views as mod_view
                if mod_view.moderate_post(request, comment):
                    html = render_to_string(
                        'motion/assets/comment.html', {
                            'comment': comment,
                            'view': 'permalink',
                        },
                        context_instance=RequestContext(request))
                    return http.HttpResponse(json.dumps({
                        'status':
                        'moderated',
                        'data':
                        'Your comment is held for moderation.'
                    }),
                                             mimetype='application/json')

            try:
                asset.comments.post(comment)
            except Exception, e:
                return http.HttpResponse(json.dumps({
                    'status': 'error',
                    'data': str(e),
                }),
                                         mimetype='application/json')

            signals.asset_created.send(sender=asset_post,
                                       instance=comment,
                                       parent=asset,
                                       group=request.group)

            # render response
            html = render_to_string('motion/assets/comment.html', {
                'comment': comment,
                'view': 'permalink',
            },
                                    context_instance=RequestContext(request))

            return http.HttpResponse(json.dumps({
                'status': 'posted',
                'data': html,
                'xid': comment.xid
            }),
                                     mimetype='application/json')
        else:
            errorfields = [k for k, v in frm.errors.items()]
            return http.HttpResponse(json.dumps({
                'status': 'error',
                'data': ','.join(errorfields)
            }),
                                     mimetype='application/json')
Beispiel #17
0
def moderation_report(request):
    asset_id = request.POST['asset-id']
    try:
        reason_code = int(request.POST.get('reason', 0))
    except ValueError:
        reason_code = 0
    note = request.POST.get('note', None)
    return_to = request.POST.get('return_to', reverse('home'))
    return_to = re.sub('.*?/', '/', return_to)

    ip = request.META['REMOTE_ADDR']

    typepad.client.batch_request()
    user = get_user(request)
    asset = typepad.Asset.get_by_url_id(asset_id)
    try:
        typepad.client.complete_batch()
    except typepad.Asset.NotFound:
        if request.is_ajax():
            return HttpResponse(_("The requested post was not found."), mimetype='text/plain')
        else:
            return HttpResponse('ERROR', mimetype='text/plain')

    # TODO: Should we behave differently if the user is an admin?

    queue = Queue.objects.filter(asset_id=asset_id)
    if not queue:
        queue = Queue()
        queue.asset_id = asset_id
        queue.summary = unicode(asset)
        queue.asset_type = asset.type_id
        queue.user_id = asset.user.url_id
        queue.user_display_name = asset.user.display_name
        queue.user_userpic = asset.user.userpic
        queue.flag_count = 1
        queue.status = Queue.FLAGGED
        queue.last_flagged = datetime.now()
    else:
        queue = queue[0]
        queue.flag_count += 1

    approved = Approved.objects.filter(asset_id=asset_id)

    if len(approved):
        if request.is_ajax():
            return HttpResponse(_("This post has been approved by the site moderator."), mimetype='text/plain')
        else:
            request.flash.add('notices', _('This post has been approved by the site moderator.'))
            return HttpResponseRedirect(return_to)


    # determine if this report is going to suppress the asset or not.
    if queue.status != Queue.SUPPRESSED:
        # count # of flags for this reason and asset:
        if len(settings.REPORT_OPTIONS[reason_code]) > 1:
            trigger = settings.REPORT_OPTIONS[reason_code][1]
            count = Flag.objects.filter(tp_asset_id=asset_id, reason_code=reason_code).count()
            if count + 1 >= trigger:
                queue.status = Queue.SUPPRESSED


    queue.save()

    # to avoid having to hit typepad for viewing this content,
    # save a local copy to make moderation as fast as possible
    # this data is removed once the post is processed.
    if not queue.content:
        content = QueueContent()
        content.data = json.dumps(asset.to_dict())
        content.queue = queue
        content.user_token = 'none'
        content.ip_addr = '0.0.0.0'
        content.save()


    flag = Flag.objects.filter(user_id=user.url_id, queue=queue)
    if not flag:
        # lets not allow a single user to repeat a report on the same asset
        flag = Flag()
        flag.queue = queue
        flag.tp_asset_id = asset_id
        flag.user_id = user.url_id
        flag.user_display_name = user.display_name
        if reason_code is not None:
            flag.reason_code = reason_code
        if note is not None:
            flag.note = note
        flag.ip_addr = ip
        flag.save()
    else:
        flag = flag[0]
        if reason_code and flag.reason_code != reason_code:
            flag.reason_code = reason_code
            flag.ip_addr = ip
            if note is not None:
                flag.note = note
            flag.save()

    if request.is_ajax():
        return HttpResponse('OK', mimetype='text/plain')
    else:
        request.flash.add('notices', _('Thank you for your report.'))
        if queue.status == Queue.SUPPRESSED:
            return HttpResponseRedirect(reverse('home'))
        else:
            return HttpResponseRedirect(return_to)
Beispiel #18
0
def asset_post(request):
    """Ajax interface for creating a post or comment."""

    post_type = request.POST.get('post_type', None)
    if post_type is None:
        raise Exception("post_type is a required parameter")

    if post_type == 'comment':
        frm = CommentForm(request.POST)
        if frm.is_valid():
            postid = request.POST.get('parent', None)
            if postid is None:
                raise Exception("parent is a required parameter")

            typepad.client.batch_request()
            user = get_user(request)
            asset = models.Asset.get_by_url_id(postid)
            typepad.client.complete_batch()

            if not user.is_authenticated():
                raise Exception("not authorized")

            request.typepad_user = user
            comment = frm.save()
            comment.in_reply_to = asset.asset_ref

            ### Moderation
            if moderation:
                from moderation import views as mod_view
                if mod_view.moderate_post(request, comment):
                    html = render_to_string('motion/assets/comment.html', {
                        'comment': comment,
                        'view': 'permalink',
                    }, context_instance=RequestContext(request))
                    return http.HttpResponse(json.dumps({
                        'status': 'moderated',
                        'data': 'Your comment is held for moderation.'}),
                        mimetype='application/json')

            try:
                asset.comments.post(comment)
            except Exception, e:
                return http.HttpResponse(json.dumps({
                    'status': 'error',
                    'data': str(e),
                }), mimetype='application/json')

            signals.asset_created.send(sender=asset_post, instance=comment,
                parent=asset, group=request.group)

            # render response
            html = render_to_string('motion/assets/comment.html', {
                'comment': comment,
                'view': 'permalink',
            }, context_instance=RequestContext(request))

            return http.HttpResponse(json.dumps({
                'status': 'posted', 'data': html, 'xid':comment.xid}),
                mimetype='application/json')
        else:
            errorfields = [k for k, v in frm.errors.items()]
            return http.HttpResponse(json.dumps({'status': 'error',
                'data': ','.join(errorfields)}), mimetype='application/json')
Beispiel #19
0
def moderate(request):
    """
    Moderation actions for the moderation queue. Approve or delete. Return OK.
    """

    if not hasattr(request, 'typepad_user'):
        typepad.client.batch_request()
        request.typepad_user = get_user(request)
        typepad.client.complete_batch()

    if not (request.typepad_user.is_authenticated() and \
        request.typepad_user.is_superuser):
        return http.HttpResponseForbidden()

    res = 'OK'

    item_ids = request.POST.getlist('item_id')

    if item_ids is None:
        raise http.Http404

    action = request.POST.get('action', None)

    success = []
    fail = []
    ban_list = []
    for item_id in item_ids:
        queue = None
        user = None
        if action.endswith('_user'):
            try:
                user = Blacklist.objects.get(user_id=item_id)
            except Blacklist.DoesNotExist:
                if action == 'approve_user':
                    success.append(item_id)
                    continue
                else:
                    fail.append(item_id)
                    continue
        else:
            try:
                queue = Queue.objects.get(id=item_id)
            except:
                fail.append(item_id)
                continue

        if action == 'approve':
            queue.approve()
            success.append(item_id)

        elif action in ('delete', 'ban'):
            # outright delete it?? or do we have a status for this?
            if action == 'ban':
                if queue.user_id not in ban_list:
                    # also ban this user
                    typepad.client.batch_request()
                    user_memberships = User.get_by_url_id(queue.user_id).memberships.filter(by_group=request.group)
                    typepad.client.complete_batch()

                    try:
                        user_membership = user_memberships[0]

                        if user_membership.is_admin():
                            # cannot ban/unban another admin
                            fail.append(item_id)
                            continue

                        user_membership.block()
                        signals.member_banned.send(sender=moderate,
                            membership=user_membership, group=request.group)
                        ban_list.append(queue.user_id)

                    except IndexError:
                        pass # no membership exists; ignore ban

            tp_asset = None

            if queue.asset_id:
                # we need to remove from typepad
                typepad.client.batch_request()
                tp_asset = typepad.Asset.get_by_url_id(queue.asset_id)
                try:
                    typepad.client.complete_batch()
                except typepad.Asset.NotFound:
                    # already deleted on TypePad...
                    tp_asset = None

                if tp_asset:
                    tp_asset.delete()

            content = queue.content
            if content is not None:
                if content.attachment is not None and content.attachment.name:
                    # delete the attachment ourselves; this handles
                    # the case where the file may not actually still be
                    # on disk; we'll just ignore that since we're deleting
                    # the row anyway
                    try:
                        content.attachment.delete()
                    except IOError, ex:
                        # something besides "file couldn't be opened"; reraise
                        if ex.errno != 2:
                            raise ex
                    content.attachment = None
                    content.save()

            queue.delete()
            success.append(item_id)

            if tp_asset is not None:
                signals.asset_deleted.send(sender=moderate, instance=tp_asset, group=request.group)

        elif action == 'view':
            if queue.status in (Queue.MODERATED, Queue.SPAM):
                content = QueueContent.objects.get(queue=queue)
                data = json.loads(content.data)
                # supplement with a fake author member, since this isn't
                # populated into the POSTed data for pre-moderation/spam assets
                data['author'] = {
                    'displayName': queue.user_display_name,
                    'links': [{
                        'rel': 'avatar',
                        'href': queue.user_userpic,
                        'width': 50,
                        'height': 50
                    }]
                }
                tp_asset = typepad.Asset.from_dict(data)
                tp_asset.published = queue.ts
            else:
                typepad.client.batch_request()
                tp_asset = typepad.Asset.get_by_url_id(queue.asset_id)
                typepad.client.complete_batch()

            event = typepad.Event()
            event.object = tp_asset
            event.actor = tp_asset.author
            event.published = tp_asset.published

            # 'view' of 'permalink' causes the full content to render
            data = { 'entry': tp_asset, 'event': event, 'view': 'permalink' }
            res = render_to_string("motion/assets/asset.html", data,
                context_instance=RequestContext(request))

            return http.HttpResponse(res)
Beispiel #20
0
def generate_members_csv(request):
    """CSV file generator for member data."""

    # file-like obj for csv writing
    mfile = StringIO.StringIO()
    writer = csv.writer(mfile)

    # label header row
    labels = ["id", "display name", "email", "joined", "gender", "location", "about me", "homepage", "interests"]
    if settings.AUTH_PROFILE_MODULE:
        profile_form = typepadapp.forms.LocalProfileForm()
        for field in profile_form:
            labels.append(field.label)
    writer.writerow(labels)

    # start the download prompt!
    yield mfile.getvalue()

    # fetch typepad api data
    offset = 1
    typepad.client.batch_request()
    request.typepad_user = get_user(request)
    kwargs = {"start_index": offset, "member": True, "batch": False}
    members = request.group.memberships.filter(**kwargs)
    typepad.client.complete_batch()

    # verify the user is an admin
    if request.typepad_user.is_superuser:

        # convert to user list
        ids = [member.target.id for member in members]

        # output csv
        mfile = get_members_csv(members)
        yield mfile.getvalue()

        # wiggle room
        new_offset = len(ids) - 4

        # more pages of members
        while new_offset > offset:

            offset = new_offset

            # fetch typepad api data
            kwargs["start_index"] = offset
            more = request.group.memberships.filter(**kwargs)

            # stop if the result is an empty list
            if not more.entries:
                break

            # add members to list
            members = []
            for m in more:
                if m.target.id not in ids:  # remove dupes
                    members.append(m)
                    ids.append(m.target.id)

            # output csv
            mfile = get_members_csv(members)
            yield mfile.getvalue()

            new_offset = len(ids) - 4
Beispiel #21
0
def asset_meta(request):
    """An AJAX method for returning metadata about a list of assets, in the
    context of the authenticated user.

    This method requires POST and accepts one or more asset_id parameters
    which should be a valid TypePad Asset XID, prefixed with either
    'asset-' or 'comment-' (the prefix informs the type of metadata to
    supply. Comments cannot be favorited, so there is no need to issue
    favorite requests for them).

    The response will be a JSON data structure, mapping the supplied IDs as a
    key to a dictionary containing "favorite" and "can_delete" members that
    are assigned a true value. If an asset is neither a favorite or can be
    deleted by the requesting user, the ID will not be present in the
    response. An example response would look like this:

        {
            "asset-asset_xid1": { "favorite": true },
            "comment-asset_xid2": { "can_delete": true }
        }
    """
    if not hasattr(request, 'typepad_user'):
        typepad.client.batch_request()
        request.typepad_user = get_user(request)
        typepad.client.complete_batch()

    ids = request.POST.getlist('asset_id')
    if not ids or not request.typepad_user.is_authenticated():
        return http.HttpResponse('{}', mimetype='application/json')

    user_id = request.typepad_user.url_id
    admin_user = request.typepad_user.is_superuser

    favs = []
    opts = []
    meta = {}
    typepad.client.batch_request()
    for id in ids:
        xid = re.sub(r'^(asset|comment)-', '', id)
        # deleted comments and assets can leave a 'asset-' or 'comment-' in the request
        if not len(xid): continue

        # request favorite status for assets
        if id.startswith('asset-'):
            favs.append((id, typepad.Favorite.head_by_user_asset(user_id,
                                                                 xid)))

        # for non-admins and only if this install permits asset deletion,
        # request if the user can delete this asset.
        if not admin_user and settings.ALLOW_USERS_TO_DELETE_POSTS:
            opts.append((id, typepad.Asset.get_by_url_id(xid).options()))
        if admin_user:
            meta[id] = {'can_delete': True}
    typepad.client.complete_batch()

    for f in favs:
        if f[1].found():
            if f[0] not in meta:
                meta[f[0]] = {}
            meta[f[0]]['favorite'] = True
    for o in opts:
        if o[1].status == 200:
            if o[1].can_delete():
                if o[0] not in meta:
                    meta[o[0]] = {}
                meta[o[0]]['can_delete'] = True
    return http.HttpResponse(json.dumps(meta), mimetype='application/json')
Beispiel #22
0
def asset_meta(request):
    """An AJAX method for returning metadata about a list of assets, in the
    context of the authenticated user.

    This method requires POST and accepts one or more asset_id parameters
    which should be a valid TypePad Asset XID, prefixed with either
    'asset-' or 'comment-' (the prefix informs the type of metadata to
    supply. Comments cannot be favorited, so there is no need to issue
    favorite requests for them).

    The response will be a JSON data structure, mapping the supplied IDs as a
    key to a dictionary containing "favorite" and "can_delete" members that
    are assigned a true value. If an asset is neither a favorite or can be
    deleted by the requesting user, the ID will not be present in the
    response. An example response would look like this:

        {
            "asset-asset_xid1": { "favorite": true },
            "comment-asset_xid2": { "can_delete": true }
        }
    """
    if not hasattr(request, 'typepad_user'):
        typepad.client.batch_request()
        request.typepad_user = get_user(request)
        typepad.client.complete_batch()

    ids = request.POST.getlist('asset_id')
    if not ids or not request.typepad_user.is_authenticated():
        return http.HttpResponse('{}', mimetype='application/json')

    user_id = request.typepad_user.url_id
    admin_user = request.typepad_user.is_superuser

    favs = []
    opts = []
    meta = {}
    typepad.client.batch_request()
    for id in ids:
        xid = re.sub(r'^(asset|comment)-', '', id)
        # deleted comments and assets can leave a 'asset-' or 'comment-' in the request
        if not len(xid): continue

        # request favorite status for assets
        if id.startswith('asset-'):
            favs.append((id, typepad.Favorite.head_by_user_asset(user_id, xid)))

        # for non-admins and only if this install permits asset deletion,
        # request if the user can delete this asset.
        if not admin_user and settings.ALLOW_USERS_TO_DELETE_POSTS:
            opts.append((id, typepad.Asset.get_by_url_id(xid).options()))
        if admin_user:
            meta[id] = {'can_delete': True}
    typepad.client.complete_batch()

    for f in favs:
        if f[1].found():
            if f[0] not in meta:
                meta[f[0]] = {}
            meta[f[0]]['favorite'] = True
    for o in opts:
        if o[1].status == 200:
            if o[1].can_delete():
                if o[0] not in meta:
                    meta[o[0]] = {}
                meta[o[0]]['can_delete'] = True
    return http.HttpResponse(json.dumps(meta), mimetype='application/json')