Source

tgapp-tgcomments / tgcomments / controllers / root.py

# -*- coding: utf-8 -*-
"""Main Controller"""
from sqlalchemy.exc import IntegrityError

from tg import TGController
from tg import expose, flash, require, url, lurl, request, redirect, validate, config
from tg.exceptions import HTTPForbidden, HTTPRedirection
from tg.i18n import ugettext as _, lazy_ugettext as l_

from tgcomments import model
from tgcomments.model import DBSession, Comment, CommentVote
from tgcomments.lib import get_user_gravatar, notify_comment_on_facebook, make_fake_comment_entity, FakeCommentEntity
import transaction

try:
    from tg import predicates
except ImportError:
    from repoze.what import predicates

from tgext.pluggable import app_model

from formencode.validators import Email, String, Invalid, Int
from tgext.datahelpers.validators import SQLAEntityConverter
from tgext.datahelpers.utils import fail_with

def back_to_referer(*args, **kw):
    if not kw.get('success'):
        flash('Failed to post comment', 'error')
    if request.referer is not None:
        raise redirect(request.referer)
    raise redirect(request.host_url)

class RootController(TGController):
    @expose()
    @validate({'entity_type':String(not_empty=True),
               'entity_id':String(not_empty=True),
               'body':String(not_empty=True)},
              error_handler=back_to_referer)
    def new(self, **kw):
        entity_type = getattr(app_model, kw['entity_type'], None)
        entity_id = kw['entity_id']
        if entity_type is None or entity_id is None:
            return back_to_referer()

        if issubclass(entity_type, FakeCommentEntity):
            entity = make_fake_comment_entity(entity_type, entity_id)
        else:
            entity = DBSession.query(entity_type).get(entity_id)
            if not entity:
                return back_to_referer()

        if not request.identity:
            try:
                user = {'name':String(not_empty=True).to_python(kw.get('author')),
                        'avatar':get_user_gravatar(Email(not_empty=True).to_python(kw.get('email')))}
            except Invalid:
                return back_to_referer()
        else:
            user = request.identity['user']

        c = Comment.add_comment(entity, user, kw['body'])
        notify_comment_on_facebook(request.referer, c)
        flash(_('Comment Added'))
        return back_to_referer(success=True)

    @expose()
    @require(predicates.in_group('tgcmanager'))
    @validate({'comment':SQLAEntityConverter(Comment)},
              error_handler=fail_with(404))
    def delete(self, comment):
        DBSession.delete(comment)
        flash(_('Comment Deleted'))
        return back_to_referer(success=True)

    @expose()
    @require(predicates.in_group('tgcmanager'))
    @validate({'comment':SQLAEntityConverter(Comment)},
              error_handler=fail_with(404))
    def hide(self, comment):
        comment.hidden = not comment.hidden
        if comment.hidden:
            flash(_('Comment Hidden'))
        else:
            flash(_('Comment Displayed'))
        return back_to_referer(success=True)

    @expose()
    @require(predicates.not_anonymous())
    @validate({'comment':SQLAEntityConverter(Comment),
               'value':Int(not_empty=True)},
              error_handler=fail_with(403))
    def vote(self, comment, value):
        transaction.begin()
        user = request.identity['user']
        vote = DBSession.query(CommentVote).filter_by(comment=comment, user=user).first()
        if vote is None:
            vote = CommentVote(comment=comment, user=user)
            DBSession.add(vote)

        votes_range = config['_pluggable_tgcomments_config'].get('votes_range', (-1, 1))
        min_vote_value = votes_range[0]
        max_vote_value = votes_range[1]

        vote.value = min(max(min_vote_value, value), max_vote_value)

        try:
            DBSession.flush()
            transaction.commit()
        except IntegrityError:
            return back_to_referer(success=False)

        flash(_('Thanks for your vote!'))
        return back_to_referer(success=True)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.