Example #1
0
def all_forums_view(context, request):
    page_title = "Message Boards"
    api = TemplateAPI(context, request, page_title)

    # Don't use the forums folder as the starting point, use its
    # parent (the community) to allow recursion
    context_path = model_path(context.__parent__)

    searcher = ICatalogSearch(context)
    total, docids, resolver = searcher(
        interfaces=[ICommunity],
        path={'query': context_path, 'include_path': True},
        allowed={'query': effective_principals(request),
                 'operator': 'or'},
        sort_index='title',
    )

    community_data = []

    for docid in docids:
        community = resolver(docid)
        if community is not None:
            forum_data = get_forum_data(community, request)
            if forum_data:
                community_data.append({'title': community.title,
                                       'forum_data': forum_data})

    return render_to_response(
        'templates/all_forums.pt',
        {'api': api,
         'community_data': community_data},
        request=request
    )
Example #2
0
def evolve(context):
    # Need to fix up acl's for blog entries in 'inherits' state.
    # See LP #407011
    search = ICatalogSearch(context)
    cnt, docids, resolver = search(interfaces=[IBlogEntry])
    for docid in docids:
        doc = resolver(docid)
        if (getattr(doc, 'security_state', 'inherits') == 'inherits'):
            print model_path(doc)
            doc.__acl__ = [
                (Allow, 'group.KarlAdmin', ADMINISTRATOR_PERMS),
                (Allow, doc.creator, MEMBER_PERMS),
                (Deny, Everyone, ('edit', 'delete')),
            ]
            doc.security_state = 'inherits'
            _reindex(doc)
Example #3
0
def main(argv=sys.argv):
    parser =  create_karl_argparser(
        description='Add a fake blog tool to community for receiving mailin '
        'trace emails.'
        )
    parser.add_argument('community', help='Community name.')
    parser.add_argument('file', help='Path to file to touch when a tracer '
                                     'email is received.')
    args = parser.parse_args(argv[1:])
    env = args.bootstrap(args.config_uri)
    root, closer = env['root'], env['closer']
    root, closer = args.get_root(args.inst)
    community = find_communities(root).get(args.community)
    if community is None:
        args.parser.error('Could not find community: %s' % args.community)

    blog = community.get('blog')
    if blog is not None:
        if len(blog) > 0:
            args.parser.error('Cannot replace blog with blog entries.')
        else:
            del community['blog']

    community['blog'] = blog = MailinTraceBlog()
    out = args.out
    print >> out, 'Added mailin trace tool at: %s' % model_path(blog)

    settings = root._p_jar.root.instance_config
    settings['mailin_trace_file'] = args.file
    print >> out, 'The mailin trace file is: %s' % args.file

    transaction.commit()
    print >> out, ('You must restart the mailin daemon in order for the new '
                   'settings to take effect.')
Example #4
0
def main(argv=sys.argv):
    parser = create_karl_argparser(
        description='Add a fake blog tool to community for receiving mailin '
        'trace emails.')
    parser.add_argument('community', help='Community name.')
    parser.add_argument('file',
                        help='Path to file to touch when a tracer '
                        'email is received.')
    args = parser.parse_args(argv[1:])
    env = args.bootstrap(args.config_uri)
    root, closer = env['root'], env['closer']
    root, closer = args.get_root(args.inst)
    community = find_communities(root).get(args.community)
    if community is None:
        args.parser.error('Could not find community: %s' % args.community)

    blog = community.get('blog')
    if blog is not None:
        if len(blog) > 0:
            args.parser.error('Cannot replace blog with blog entries.')
        else:
            del community['blog']

    community['blog'] = blog = MailinTraceBlog()
    out = args.out
    print >> out, 'Added mailin trace tool at: %s' % model_path(blog)

    settings = root._p_jar.root.instance_config
    settings['mailin_trace_file'] = args.file
    print >> out, 'The mailin trace file is: %s' % args.file

    transaction.commit()
    print >> out, ('You must restart the mailin daemon in order for the new '
                   'settings to take effect.')
Example #5
0
def get_resource_url(resource):
    """
    Returns the URL for the given resource.
    """
    path = model_path(resource)
    parsed = list(urlparse(path))
    parsed[1] = ""
    return urlunparse(parsed)
Example #6
0
def get_resource_url(resource):
    """
    Returns the URL for the given resource.
    """
    path = model_path(resource)
    parsed = list(urlparse(path))
    parsed[1] = ""
    return urlunparse(parsed)
Example #7
0
def evolve(context):
    for path in exceptions:
        d = traverse(context, path)
        ob = d['context']
        if model_path(ob) == path:
            if hasattr(ob, '__acl__'):
                ob.__custom_acl__ = ob.__acl__
    reset_security_workflow(context)
Example #8
0
def get_forum_data(community, request):
    karldates = getUtility(IKarlDates)
    searcher = ICatalogSearch(community)
    total, docids, resolver = searcher(
        interfaces=[IForum],
        path={'query': model_path(community), 'depth': 2},
        allowed={'query': effective_principals(request),
                 'operator': 'or'},
        sort_index='title',
    )

    if not total:
        return None

    forum_data = []

    profiles = find_profiles(community)
    profiles_href = model_url(profiles, request)

    for docid in docids:
        forum = resolver(docid)
        if forum is not None:
            D = {}
            D['title'] = forum.title
            D['url'] = model_url(forum, request)
            D['number_of_topics'] = len(forum)
            D['number_of_comments'] = number_of_comments(forum, request)

            latest = latest_object(forum, request)

            _NOW = datetime.datetime.now()

            if latest:
                D['latest_activity_url'] = model_url(latest, request)
                D['latest_activity_link'] = getattr(latest, 'title', None)
                creator = getattr(latest, 'creator', None)
                D['latest_activity_byhref'] = profiles_href + creator
                profile = profiles[creator]
                D['latest_activity_byname'] = profile.title
                modified = getattr(latest, 'modified_date', _NOW)
                modified_str = karldates(modified, 'longform')
                D['latest_activity_at'] = modified_str
            else:
                D['latest_activity_url'] = None
                D['latest_activity_link'] = None
                D['latest_activity_by'] = None
                D['latest_activity_at'] = None

            forum_data.append(D)

    return forum_data
Example #9
0
    def make_type_counter(community):
        path = model_path(community)

        def count(content_type, creation_date):
            n, _, _ = search(path=path,
                             interfaces=[content_type],
                             creation_date=creation_date)
            return n

        def count_type(content_type):
            return (count(content_type,
                          (begin, end)), count(content_type, (None, end)))

        return count_type
Example #10
0
def fix_wiki_links(site):
    """
    Check wiki pages for malformed links.

    """
    searcher = ICatalogSearch(site)
    total, docids, resolver = searcher(interfaces=[
        IWikiPage,
    ], )

    for docid in docids:
        doc = resolver(docid)
        changes = doc.fix_links()
        if changes:
            # log the changes
            path = model_path(doc)
            for old_link, new_link in changes:
                log.info("Replaced wiki link at %s: ((%s)) -> ((%s))", path,
                         old_link, new_link)
Example #11
0
def evolve(context):
    """
    Remove any people directory categories set for non-Staff users.
    """
    profiles = find_profiles(context)
    users = find_users(context)
    catalog = find_peopledirectory_catalog(context)
    docid_for_address = catalog.document_map.docid_for_address
    for profile in profiles.values():
        user = users.get_by_id(profile.__name__)
        if user is None:
            continue

        if 'group.KarlStaff' not in user['groups']:
            if getattr(profile, 'categories', None):
                print "Removing categories for", profile.__name__
                profile.categories = {}
                docid = docid_for_address(model_path(profile))
                catalog.reindex_doc(docid, profile)
def main(args):
    root, closer = args.get_root(args.inst)
    community = find_communities(root).get(args.community)
    if community is None:
        args.parser.error('Could not find community: %s' % args.community)

    blog = community.get('blog')
    if blog is not None:
        if len(blog) > 0:
            args.parser.error('Cannot replace blog with blog entries.')
        else:
            del community['blog']

    community['blog'] = blog = MailinTraceBlog()
    out = args.out
    print >> out, 'Added mailin trace tool at: %s' % model_path(blog)

    settings = root._p_jar.root.instance_config
    settings['mailin_trace_file'] = args.file
    print >> out, 'The mailin trace file is: %s' % args.file

    transaction.commit()
    print >> out, ('You must restart the mailin daemon in order for the new '
                   'settings to take effect.')
Example #13
0
def _fix_link_traverser(context, traversed, subpath):
    if not subpath:
        # We're done, return traversed path
        return '/' + '/'.join(traversed)

    next = subpath.pop(0)

    # Easy case, normal traversal
    if hasattr(context, '__getitem__') and next in context:
        traversed.append(next)
        return _fix_link_traverser(context[next], traversed, subpath)

    # Karl2 site was actually rooted at /Plone/public
    # Although you wouldn't normally include that in a link url,
    # because of acquisition you could!
    # If we find this or some variation at the beginning of a link
    # just try to skip it.
    skippable = (
        'Plone',
        'public',
    )
    if not traversed and next in skippable:
        return _fix_link_traverser(context, traversed, subpath)

    # An 'index_html' at the end is not necessary and skippable.
    # Some links inexplicably end with a '/&', which is also
    # skippable.
    skippable2 = (
        'index_html',
        '&',
    )
    if next in skippable2:
        return _fix_link_traverser(context, traversed, subpath)

    # Can't find next element.  Maybe it is a view
    if _check_view(context, next):
        # We can stop here, traversed path with view
        traversed.append(next)
        return '/' + '/'.join(traversed + subpath)

    # In Karl2 there was a content type for images that used a view
    # In Karl3, these are just files, so where we might have had a
    # view named 'image' in Karl2, we just have the 'dl' view in Karl3
    if next == 'image' and _check_view(context, 'dl'):
        # Got the view, we can stop here
        traversed.append('dl')
        return '/' + '/'.join(traversed + subpath)

    # Maybe next was resolved via acquisition in Karl2
    aq_context = _acquire(context, next)
    if aq_context:
        # Rewrite the leading part of this path as the model_path of the
        # acquired context.
        aq_path = model_path(aq_context)
        log.debug("Acquisition: rewrote path: %s -> %s", traversed, aq_path)
        traversed = aq_path[1:].split('/')
        return _fix_link_traverser(aq_context, traversed, subpath)

    # Next may have been processed through make_name in Karl3.  Try
    # processing the name and see if that finds the next element.
    if hasattr(context, '__getitem__'):
        # This fix only makes sense if current node is traversable
        try:
            name = make_name({}, urllib.unquote(next))
            if name in context:
                traversed.append(name)
                return _fix_link_traverser(context[name], traversed, subpath)
        except ValueError:
            # make_name will throw ValueError if there are no alphanumerics
            # in next
            pass

    # Some links in Karl2 are to /profile/<user> rather than
    # /profiles/<user>.  Try changing profile to profiles and
    # see if that fixes the problem.
    if next == 'profile':
        subpath.insert(0, 'profiles')
        return _fix_link_traverser(context, traversed, subpath)

    # Links to /osipeople_*.html can be rewritten as just /people
    if next.startswith('osipeople_') and next.endswith('.html'):
        subpath.insert(0, 'people')
        return _fix_link_traverser(context, traversed, subpath)

    # There are some links to just /network-news and /network-events.
    # These are located in /offices/files
    if next in ('network-news', 'network-events'):
        subpath.insert(0, next)
        subpath.insert(0, 'files')
        subpath.insert(0, 'offices')
        return _fix_link_traverser(context, traversed, subpath)

    # Out of tricks, give up
    log.debug("Couldn't fix")
    log.debug("Traversed: %s", traversed)
    log.debug("Not found: %s", next)

    return None
Example #14
0
def scrub(site):
    """
    Given root, find content with HTML body, look for bad links or other
    errors.

    """

    searcher = ICatalogSearch(site)
    total, docids, resolver = searcher(interfaces=[IContent], )

    log.info("Found a total of %d documents", total)
    for docid in docids:
        doc = resolver(docid)

        if not hasattr(doc, 'text'):
            continue

        path = model_path(doc)
        log.debug("Checking %s", path)

        text = doc.text

        if not text:
            # Some types we're expecting not to have text, so don't warn
            # about those
            if not (ICommunity.providedBy(doc)
                    or ICalendarEvent.providedBy(doc)):
                log.warn("No text: %s %s", type(doc), path)
            continue

        try:
            try:
                # Will throw ParserError if fragment doesn't have a single
                # root element.
                html = fragment_fromstring(doc.text)
            except ParserError:
                # Wrap in a single div to make the parser happy
                html = fragment_fromstring('<div>%s</div>' % doc.text)

        except XMLSyntaxError:
            log.error("Unparseable: %s", path, exc_info=True)

        # Check and fix links
        def callback(link):
            fixed = _rewrite_link(site, path, link)
            if fixed != link:
                log.info("Link rewritten at %s", path)
                log.info("Old link: %s", link)
                log.info("New link: %s", fixed)

            if not isinstance(fixed, unicode):
                fixed = unicode(fixed, 'utf-8')

            return fixed

        html.rewrite_links(callback)

        # Need to also change any instances of the 'mce_href' attribute to
        # match newly rewritten 'href' attribute.
        for element in html.getiterator():
            if 'mce_href' in element.keys():
                element.set('mce_href', element.get('href'))

        doc.text = unicode(lxml.html.tostring(html, 'utf-8'), 'utf-8')

    log.info("Done.")
    log.info("Unknown schemes: %s", ', '.join(unknown_schemes))
Example #15
0
 def path(self):
     """
     Returns the path to this resource in the tree of resources.
     """
     return model_path(self)
Example #16
0
 def get_success_url(self):
     return model_path(self.context)
Example #17
0
 def path(self):
     """
     Returns the path to this resource in the tree of resources.
     """
     return model_path(self)
Example #18
0
def make_non_staff(profile, inform_moderators=True):
    """
    When a user is removed from the KarlStaff role, their community
    memberships are removed. Moderators of their communities are optionally
    informed via email.
    """
    id = profile.__name__
    moderators = {}
    users = find_users(profile)
    profile.categories = {}
    for group in list(users.get_by_id(id)['groups']):
        if group.startswith('group.community'):
            # Remove user from group
            users.remove_user_from_group(id, group)
            if not inform_moderators:
                continue

            # Keep track of moderators we need to email making sure
            # each moderator is emailed only once and each community is
            # only mentioned once in any given email.
            community_name = group.split(':')[1]
            moderators_group = ('group.community:%s:moderators' %
                                community_name)
            for moderator in users.users_in_group(moderators_group):
                if moderator == id:
                    continue  # Really should only come up in unittests
                if moderator not in moderators:
                    moderators[moderator] = set()
                moderators[moderator].add(community_name)

    if not inform_moderators:
        return

    communities = find_communities(profile)
    profiles = profile.__parent__
    mailer = getUtility(IMailDelivery)
    for moderator_id in moderators:
        moderator = profiles[moderator_id]
        msg = Message()
        msg['From'] = get_setting(profile, 'admin_email')
        msg['To'] = '%s <%s>' % (moderator.title, moderator.email)
        msg['Subject'] = 'Notice that %s is now former staff' % profile.title
        former_communities = sorted(
            [communities[c] for c in moderators[moderator_id]],
            key=lambda x: x.title)
        app_url = get_setting(profile, 'offline_app_url')
        communities_info = [
            dict(title=c.title,
                 unremove_url='%s%s?user_id=%s' %
                 (app_url, model_path(c, 'members', 'add_existing.html'), id))
            for c in former_communities
        ]
        body = render(
            'templates/email_notify_former_staff.pt',
            dict(name=profile.title, communities=communities_info),
        )
        if isinstance(body, unicode):
            body = body.encode('UTF-8')
        msg.set_payload(body, 'UTF-8')
        msg.set_type('text/html')

        mailer.send([msg['To']], msg)
Example #19
0
 def _callFUT(self, model, *elements):
     from pyramid.traversal import model_path
     return model_path(model, *elements)