Example #1
0
    def latest(self, limit=None, ignore_privileges=False, ignore_blocked=True):
        """Filter the list of non blocked comments for anonymous users or
        all comments for admin users.
        """
        query = self

        # only the approved if blocked are ignored
        if ignore_blocked:
            query = query.approved()

        # otherwise if we don't ignore the privileges we only want
        # the approved if the user does not have the MODERATE_COMMENTS
        # privileges.
        elif not ignore_privileges:
            req = get_request()
            if req:
                user = req.user
                if not user.has_privilege(MODERATE_COMMENTS |
                                          MODERATE_OWN_ENTRIES |
                                          MODERATE_OWN_PAGES):
                    query = query.approved()

                elif user.has_privilege(MODERATE_OWN_ENTRIES |
                                        MODERATE_OWN_PAGES):
                    query = query.for_user(user)

        return query
Example #2
0
 def make_visible_for_request(self, request=None):
     """Make the comment visible for the current request."""
     if request is None:
         request = get_request()
     comments = set(request.session.get('visible_comments', ()))
     comments.add(self.id)
     request.session['visible_comments'] = tuple(comments)
Example #3
0
    def published(self, ignore_privileges=False, user=None):
        """Return a queryset for only published posts."""
        if not user:
            req = get_request()
            user = req and req.user

        if ignore_privileges or not user:
            # Anonymous. Return only public entries.
            return self.filter(
                (Post.status == STATUS_PUBLISHED) &
                (Post.pub_date <= datetime.utcnow())
            )
        elif not user.has_privilege(VIEW_PROTECTED):
            # Authenticated user without protected viewing privilege
            # Return public and their own private entries
            return self.filter(
                ((Post.status == STATUS_PUBLISHED) |
                 ((Post.status == STATUS_PRIVATE) &
                  (Post.author_id == user.id))) &
                (Post.pub_date <= datetime.utcnow())
            )
        else:
            # Authenticated and can view protected.
            # Return public, protected and their own private
            return self.filter(
                ((Post.status == STATUS_PUBLISHED) |
                 (Post.status == STATUS_PROTECTED) |
                 ((Post.status == STATUS_PRIVATE) &
                  (Post.author_id == user.id))) &
                (Post.pub_date <= datetime.utcnow())
            )
Example #4
0
    def can_read(self, user=None):
        """Check if the current user or the user provided can read-access
        this post. If there is no user there must be a request object
        for this thread defined.
        """
        # published posts are always accessible
        if self.status == STATUS_PUBLISHED and self.pub_date is not None and \
           self.pub_date <= datetime.utcnow():
            return True

        if user is None:
            user = get_request().user

        # users that are allowed to look at drafts may pass
        if user.has_privilege(VIEW_DRAFTS):
            return True

        # if this is protected and user can view protected, allow them
        if self.status == STATUS_PROTECTED and self.pub_date is not None and \
            self.pub_date <= datetime.utcnow() and \
            user.has_privilege(VIEW_PROTECTED):
             return True

        # if we have the privilege to edit other entries or if we are
        # a blog administrator we can always look at posts.
        if user.has_privilege(self.EDIT_OTHER_PRIVILEGE):
            return True

        # otherwise if the user has the EDIT_OWN_PRIVILEGE and the
        # author of the post, he may look at it as well
        if user.id == self.author_id and \
           user.has_privilege(self.EDIT_OWN_PRIVILEGE):
            return True

        return False
Example #5
0
    def can_read(self, user=None):
        """Check if the current user or the user provided can read-access
        this post. If there is no user there must be a request object
        for this thread defined.
        """
        # published posts are always accessible
        if self.status == STATUS_PUBLISHED and self.pub_date is not None and \
           self.pub_date <= datetime.utcnow():
            return True

        if user is None:
            user = get_request().user

        # users that are allowed to look at drafts may pass
        if user.has_privilege(VIEW_DRAFTS):
            return True

        # if this is protected and user can view protected, allow them
        if self.status == STATUS_PROTECTED and self.pub_date is not None and \
            self.pub_date <= datetime.utcnow() and \
            user.has_privilege(VIEW_PROTECTED):
            return True

        # if we have the privilege to edit other entries or if we are
        # a blog administrator we can always look at posts.
        if user.has_privilege(self.EDIT_OTHER_PRIVILEGE):
            return True

        # otherwise if the user has the EDIT_OWN_PRIVILEGE and the
        # author of the post, he may look at it as well
        if user.id == self.author_id and \
           user.has_privilege(self.EDIT_OWN_PRIVILEGE):
            return True

        return False
Example #6
0
 def make_visible_for_request(self, request=None):
     """Make the comment visible for the current request."""
     if request is None:
         request = get_request()
     comments = set(request.session.get('visible_comments', ()))
     comments.add(self.id)
     request.session['visible_comments'] = tuple(comments)
Example #7
0
 def visible_for_user(self, user=None):
     """Check if the current user or the user given can see this comment"""
     if not self.blocked:
         return True
     if user is None:
         user = get_request().user
     return user.has_privilege(MODERATE_COMMENTS)
Example #8
0
 def __init__(self, id, message, user=Ellipsis):
     self.message = parse_zeml(message, 'system')
     self.id = id
     self.sent_date = datetime.utcnow()
     if user is Ellipsis:
         self.user = get_request().user
     else:
         self.user = user
Example #9
0
    def can_edit(self, user=None):
        """Checks if the given user (or current user) can edit this post."""
        if user is None:
            user = get_request().user

        return (user.has_privilege(self.EDIT_OTHER_PRIVILEGE)
                or (self.author == user
                    and user.has_privilege(self.EDIT_OWN_PRIVILEGE)))
Example #10
0
 def __init__(self, id, message, user=Ellipsis):
     self.message = parse_zeml(message, 'system')
     self.id = id
     self.sent_date = datetime.utcnow()
     if user is Ellipsis:
         self.user = get_request().user
     else:
         self.user = user
Example #11
0
    def __init__(self, post, user, initial=None):
        forms.Form.__init__(self, initial)
        self.req = get_request()
        self.post = post
        self.user = user

        # if the user is logged in the form is a bit smaller
        if user.is_somebody:
            del self.fields['author'], self.fields['email'], self.fields['www']
Example #12
0
 def visible(self):
     """Check the current session it can see the comment or check against the
     current user.  To display a comment for a request you can use the
     `make_visible_for_request` function.  This is useful to show a comment
     to a user that submitted a comment which is not yet moderated.
     """
     request = get_request()
     if request is None:
         return True
     return self.visible_for_user(request.user)
Example #13
0
    def can_edit(self, user=None):
        """Checks if the given user (or current user) can edit this post."""
        if user is None:
            user = get_request().user

        return (
            user.has_privilege(self.EDIT_OTHER_PRIVILEGE) or
            (self.author == user and
             user.has_privilege(self.EDIT_OWN_PRIVILEGE))
        )
Example #14
0
 def for_user(self, user=None):
     request = get_request()
     user = user or request.user
     if user.has_privilege(MODERATE_COMMENTS):
         return self
     elif user.has_privilege(MODERATE_OWN_ENTRIES | MODERATE_OWN_PAGES):
         return self.filter(Comment.post_id.in_(
             db.session.query(Post.id).filter(Post.author_id==user.id))
         )
     return self
Example #15
0
 def visible(self):
     """Check the current session it can see the comment or check against the
     current user.  To display a comment for a request you can use the
     `make_visible_for_request` function.  This is useful to show a comment
     to a user that submited a comment which is not yet moderated.
     """
     request = get_request()
     if self.id in request.session.get('visible_comments', ()):
         return True
     return self.visible_for_user(request.user)
Example #16
0
 def cursor_execute(self, execute, cursor, statement, parameters, context,
                    executemany):
     start = _timer()
     try:
         return execute(cursor, statement, parameters, context)
     finally:
         from zine.application import get_request
         from zine.utils.debug import find_calling_context
         request = get_request()
         if request is not None:
             request.queries.append((statement, parameters, start, _timer(),
                                     find_calling_context()))
Example #17
0
 def cursor_execute(self, execute, cursor, statement, parameters,
                    context, executemany):
     start = _timer()
     try:
         return execute(cursor, statement, parameters, context)
     finally:
         from zine.application import get_request
         from zine.utils.debug import find_calling_context
         request = get_request()
         if request is not None:
             request.queries.append((statement, parameters, start,
                                     _timer(), find_calling_context()))
Example #18
0
 def drafts(self, ignore_user=False, user=None):
     """Return a query that returns all drafts for the current user.
     or the user provided or no user at all if `ignore_user` is set.
     """
     if user is None and not ignore_user:
         req = get_request()
         if req and req.user:
             user = req.user
     query = self.filter(Post.status == STATUS_DRAFT)
     if user is not None:
         query = query.filter(Post.author_id == user.id)
     return query
Example #19
0
 def drafts(self, ignore_user=False, user=None):
     """Return a query that returns all drafts for the current user.
     or the user provided or no user at all if `ignore_user` is set.
     """
     if user is None and not ignore_user:
         req = get_request()
         if req and req.user:
             user = req.user
     query = self.filter(Post.status == STATUS_DRAFT)
     if user is not None:
         query = query.filter(Post.author_id == user.id)
     return query
Example #20
0
    def comment_count(self):
        """The number of visible comments."""
        req = get_request()

        # if the model was loaded with .lightweight() there are no comments
        # but a _comment_count we can use.
        if not db.attribute_loaded(self, 'comments'):
            return self._comment_count

        # otherwise the comments are already available and we can savely
        # filter it.
        if req.user.is_manager:
            return len(self.comments)
        return len([x for x in self.comments if not x.blocked])
Example #21
0
    def comment_count(self):
        """The number of visible comments."""
        req = get_request()

        # if the model was loaded with .lightweight() there are no comments
        # but a _comment_count we can use.
        if not db.attribute_loaded(self, 'comments'):
            return self._comment_count

        # otherwise the comments are already available and we can savely
        # filter it.
        if req and req.user.is_manager:
            return len(self.comments)
        return len([x for x in self.comments if not x.blocked])
def validate_session_captcha(req, comment):
    req = get_request()
    if 'captcha' not in req.session:
        return
    captcha = req.session.pop("captcha")
    if 'captcha_mangled' in req.session:
        del req.session['captcha_mangled']
    if 'captcha' not in req.form:
        comment.status = COMMENT_BLOCKED_SPAM
        comment.blocked_msg = SKIPPED_TEST_MSG
        return
    if req.form['captcha'] != captcha:
        comment.status = COMMENT_BLOCKED_SPAM
        comment.blocked_msg = FAILED_TEST_MSG
        return
Example #23
0
    def __init__(self, post=None, initial=None):
        self.app = get_application()
        self.post = post

        if post is not None:
            initial = forms.fill_dict(initial,
                title=post.title,
                text=post.text,
                status=post.status,
                pub_date=post.pub_date,
                slug=post.slug,
                author=post.author,
                tags=[x.name for x in post.tags],
                categories=[x.id for x in post.categories],
                parser=post.parser,
                comments_enabled=post.comments_enabled,
                pings_enabled=post.pings_enabled,
                ping_links=not post.parser_missing
            )
        else:
            initial = forms.fill_dict(initial, status=STATUS_DRAFT)

            # if we have a request, we can use the current user as a default
            req = get_request()
            if req and req.user:
                initial['author'] = req.user

        initial.setdefault('parser', self.app.cfg['default_parser'])

        self.author.choices = [x.username for x in User.query.all()]
        self.parser.choices = self.app.list_parsers()
        self.parser_missing = post and post.parser_missing
        if self.parser_missing:
            self.parser.choices.append((post.parser, _('%s (missing)') %
                                        post.parser.title()))

        self.categories.choices = [(c.id, c.name) for c in
                                   Category.query.all()]

        forms.Form.__init__(self, initial)

        # if we have have an old post and the parser is not missing and
        # it was published when the form was created we collect the old
        # posts so that we don't have to ping them another time.
        self._old_links = set()
        if self.post is not None and not self.post.parser_missing and \
           self.post.is_published:
            self._old_links.update(self.post.find_urls())
Example #24
0
 def visible_for_user(self, user=None):
     """Check if the current user or the user given can see this comment"""
     request = get_request()
     if user is None:
         user = request.user
     if self.post.author is user and \
        user.has_privilege(MODERATE_OWN_ENTRIES | MODERATE_OWN_PAGES):
         return True
     elif user.has_privilege(MODERATE_COMMENTS):
         # User is able to manage comments. It's visible.
         return True
     elif self.id in request.session.get('visible_comments', ()):
         # Comment was made visible for current request. It's visible
         return True
     # Finally, comment is visible if not blocked
     return not self.blocked
Example #25
0
def bind_privileges(container, privileges, user=None):
    """Binds the privileges to the container.  The privileges can be a list
    of privilege names, the container must be a set.  This is called for
    the HTTP round-trip in the form validation.
    """
    if not user:
        user = get_request().user
    app = get_application()
    notification_types = app.notification_manager.notification_types
    current_map = dict((x.name, x) for x in container)
    currently_attached = set(x.name for x in container)
    new_privileges = set(privileges)

    # remove out-dated privileges
    for name in currently_attached.difference(new_privileges):
        container.remove(current_map[name])
        # remove any privilege dependencies that are not attached to other
        # privileges
        if current_map[name].dependencies:
            for privilege in current_map[name].dependencies.iter_privileges():
                try:
                    container.remove(privilege)
                except KeyError:
                    # privilege probably already removed
                    pass

        # remove notification subscriptions that required the privilege
        # being deleted.
        for notification in user.notification_subscriptions:
            privs = notification_types[notification.notification_id].privileges
            if current_map[name] in privs.iter_privileges():
                db.session.delete(notification)
                break
            for privilege in current_map[name].dependencies:
                if privilege in privs.iter_privileges():
                    db.session.delete(notification)

    # add new privileges
    for name in new_privileges.difference(currently_attached):
        privilege = app.privileges[name]
        container.add(privilege)
        # add dependable privileges
        if privilege.dependencies:
            for privilege in privilege.dependencies.iter_privileges():
                container.add(privilege)
Example #26
0
def bind_privileges(container, privileges, user=None):
    """Binds the privileges to the container.  The privileges can be a list
    of privilege names, the container must be a set.  This is called for
    the HTTP round-trip in the form validation.
    """
    if not user:
        user = get_request().user
    app = get_application()
    notification_types = app.notification_manager.notification_types
    current_map = dict((x.name, x) for x in container)
    currently_attached = set(x.name for x in container)
    new_privileges = set(privileges)

    # remove out-dated privileges
    for name in currently_attached.difference(new_privileges):
        container.remove(current_map[name])
        # remove any privilege dependencies that are not attached to other
        # privileges
        if current_map[name].dependencies:
            for privilege in current_map[name].dependencies.iter_privileges():
                try:
                    container.remove(privilege)
                except KeyError:
                    # privilege probably already removed
                    pass

        # remove notification subscriptions that required the privilege
        # being deleted.
        for notification in user.notification_subscriptions:
            privs = notification_types[notification.notification_id].privileges
            if current_map[name] in privs.iter_privileges():
                db.session.delete(notification)
                break
            for privilege in current_map[name].dependencies:
                if privilege in privs.iter_privileges():
                    db.session.delete(notification)

    # add new privileges
    for name in new_privileges.difference(currently_attached):
        privilege = app.privileges[name]
        container.add(privilege)
        # add dependable privileges
        if privilege.dependencies:
            for privilege in privilege.dependencies.iter_privileges():
                container.add(privilege)
Example #27
0
def get_redirect_target(invalid_targets=(), request=None):
    """Check the request and get the redirect target if possible.
    If not this function returns just `None`.  The return value of this
    function is suitable to be passed to `_redirect`
    """
    if request is None:
        request = get_request()
    check_target = request.values.get('_redirect_target') or \
                   request.args.get('next') or \
                   request.environ.get('HTTP_REFERER')

    # if there is no information in either the form data
    # or the wsgi environment about a jump target we have
    # to use the target url
    if not check_target:
        return

    # otherwise drop the leading slash
    check_target = check_target.lstrip('/')

    blog_url = request.app.cfg['blog_url']
    blog_parts = urlparse(blog_url)
    check_parts = urlparse(urljoin(blog_url, check_target))

    # if the jump target is on a different server we probably have
    # a security problem and better try to use the target url.
    if blog_parts[:2] != check_parts[:2]:
        return

    # if the jump url is the same url as the current url we've had
    # a bad redirect before and use the target url to not create a
    # infinite redirect.
    current_parts = urlparse(urljoin(blog_url, request.path))
    if check_parts[:5] == current_parts[:5]:
        return

    # if the `check_target` is one of the invalid targets we also
    # fall back.
    for invalid in invalid_targets:
        if check_parts[:5] == urlparse(urljoin(blog_url, invalid))[:5]:
            return

    return check_target
Example #28
0
def get_redirect_target(invalid_targets=(), request=None):
    """Check the request and get the redirect target if possible.
    If not this function returns just `None`.  The return value of this
    function is suitable to be passed to `_redirect`
    """
    if request is None:
        request = get_request()
    check_target = request.values.get('_redirect_target') or \
                   request.args.get('next') or \
                   request.environ.get('HTTP_REFERER')

    # if there is no information in either the form data
    # or the wsgi environment about a jump target we have
    # to use the target url
    if not check_target:
        return

    # otherwise drop the leading slash
    check_target = check_target.lstrip('/')

    blog_url = request.app.cfg['blog_url']
    blog_parts = urlparse(blog_url)
    check_parts = urlparse(urljoin(blog_url, check_target))

    # if the jump target is on a different server we probably have
    # a security problem and better try to use the target url.
    if blog_parts[:2] != check_parts[:2]:
        return

    # if the jump url is the same url as the current url we've had
    # a bad redirect before and use the target url to not create a
    # infinite redirect.
    current_parts = urlparse(urljoin(blog_url, request.path))
    if check_parts[:5] == current_parts[:5]:
        return

    # if the `check_target` is one of the invalid targets we also
    # fall back.
    for invalid in invalid_targets:
        if check_parts[:5] == urlparse(urljoin(blog_url, invalid))[:5]:
            return

    return check_target
Example #29
0
    def latest(self, limit=None, ignore_privileges=False, ignore_blocked=True):
        """Filter the list of non blocked comments for anonymous users or
        all comments for admin users.
        """
        query = self

        # only the approved if blocked are ignored
        if ignore_blocked:
            query = query.approved()

        # otherwise if we don't ignore the privileges we only want
        # the approved if the user does not have the MODERATE_COMMENTS
        # privileges.
        elif not ignore_privileges:
            req = get_request()
            if req:
                user = req.user
                if not user.has_privilege(MODERATE_COMMENTS):
                    query = query.approved()

        return query
Example #30
0
def redirect(url,
             code=302,
             allow_external_redirect=False,
             force_scheme_change=False):
    """Return a redirect response.  Like Werkzeug's redirect but this
    one checks for external redirects too.  If a redirect to an external
    target was requested `BadRequest` is raised unless
    `allow_external_redirect` was explicitly set to `True`.

    Leading slashes are ignored which makes it unsuitable to redirect
    to URLs returned from `url_for` and others.  Use `redirect_to`
    to redirect to arbitrary endpoints or `_redirect` to redirect to
    unchecked resources outside the URL root.

    By default the redirect will not change the URL scheme of the current
    request (if there is one).  This behavior can be changed by setting
    the force_scheme_change to False.
    """
    # leading slashes are ignored, if we redirect to "/foo" or "foo"
    # does not matter, in both cases we want to be below our blog root.
    url = url.lstrip('/')

    if not allow_external_redirect:
        #: check if the url is on the same server
        #: and make it an external one
        try:
            url = check_external_url(get_application(), url)
        except ValueError:
            raise BadRequest()

    # keep the current URL schema if we have an active request if we
    # should.  If https enforcement is set we suppose that the blog_url
    # is already set to an https value.
    request = get_request()
    if request and not force_scheme_change and \
       not request.app.cfg['force_https']:
        url = request.environ['wsgi.url_scheme'] + ':' + url.split(':', 1)[1]

    return _redirect(url, code)
Example #31
0
def redirect(url, code=302, allow_external_redirect=False,
             force_scheme_change=False):
    """Return a redirect response.  Like Werkzeug's redirect but this
    one checks for external redirects too.  If a redirect to an external
    target was requested `BadRequest` is raised unless
    `allow_external_redirect` was explicitly set to `True`.

    Leading slashes are ignored which makes it unsuitable to redirect
    to URLs returned from `url_for` and others.  Use `redirect_to`
    to redirect to arbitrary endpoints or `_redirect` to redirect to
    unchecked resources outside the URL root.

    By default the redirect will not change the URL scheme of the current
    request (if there is one).  This behavior can be changed by setting
    the force_scheme_change to False.
    """
    # leading slashes are ignored, if we redirect to "/foo" or "foo"
    # does not matter, in both cases we want to be below our blog root.
    url = url.lstrip('/')

    if not allow_external_redirect:
        #: check if the url is on the same server
        #: and make it an external one
        try:
            url = check_external_url(get_application(), url)
        except ValueError:
            raise BadRequest()

    # keep the current URL schema if we have an active request if we
    # should.  If https enforcement is set we suppose that the blog_url
    # is already set to an https value.
    request = get_request()
    if request and not force_scheme_change and \
       not request.app.cfg['force_https']:
        url = request.environ['wsgi.url_scheme'] + ':' + url.split(':', 1)[1]

    return _redirect(url, code)
Example #32
0
    def published(self, ignore_privileges=None, user=None):
        """Return a queryset for only published posts."""
        if not user:
            req = get_request()
            user = req and req.user

        if not user:
            # Anonymous. Return only public entries.
            return self.filter((Post.status == STATUS_PUBLISHED)
                               & (Post.pub_date <= datetime.utcnow()))
        elif not user.has_privilege(VIEW_PROTECTED):
            # Authenticated user without protected viewing privilege
            # Return public and their own private entries
            return self.filter(((Post.status == STATUS_PUBLISHED) | (
                (Post.status == STATUS_PRIVATE) & (Post.author_id == user.id)))
                               & (Post.pub_date <= datetime.utcnow()))
        else:
            # Authenticated and can view protected.
            # Return public, protected and their own private
            return self.filter(((Post.status == STATUS_PUBLISHED)
                                | (Post.status == STATUS_PROTECTED) | (
                                    (Post.status == STATUS_PRIVATE) &
                                    (Post.author_id == user.id)))
                               & (Post.pub_date <= datetime.utcnow()))
Example #33
0
 def __init__(self, comment, initial=None):
     self.req = get_request()
     _CommentBoundForm.__init__(self, comment, initial)
Example #34
0
def assert_privilege(expr):
    """Like the `require_privilege` decorator but for asserting."""
    if not get_request().user.has_privilege(expr):
        raise Forbidden()
Example #35
0
 def mark_as_spam(self):
     emit_event('before-comment-mark-spam', self.comment)
     self.comment.status = COMMENT_BLOCKED_SPAM
     self.comment.blocked_msg = _("Comment reported as spam by %s" %
                                 get_request().user.display_name)
Example #36
0
 def block_selection(self):
     for comment in self.iter_selection():
         emit_event('before-comment-blocked', comment)
         comment.status = COMMENT_BLOCKED_USER
         comment.blocked_msg = _("Comment blocked by %s" %
                                 get_request().user.display_name)
def set_session_captcha(post):
    req = get_request()
    req.session['captcha'] = random.choice(choices)
    req.session['captcha_mangled'] = req.session['captcha'].replace("o", "0").replace("a", "A").replace("i", "1").replace("e", "3")
Example #38
0
 def types(self, user=None):
     if not user:
         user = get_request().user
     for notification in self.notification_types.itervalues():
         if user.has_privilege(notification.privileges):
             yield notification
Example #39
0
 def mark_selection_as_spam(self):
     for comment in self.iter_selection():
         emit_event('before-comment-mark-spam', comment)
         comment.status = COMMENT_BLOCKED_SPAM
         comment.blocked_msg = _("Comment marked as spam by %s" %
                                 get_request().user.display_name)
Example #40
0
 def types(self, user=None):
     if not user:
         user = get_request().user
     for notification in self.notification_types.itervalues():
         if user.has_privilege(notification.privileges):
             yield notification
Example #41
0
def assert_privilege(expr):
    """Like the `require_privilege` decorator but for asserting."""
    if not get_request().user.has_privilege(expr):
        raise Forbidden()