Exemple #1
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.')
Exemple #2
0
    def checkPermission(self, info):
        """ Does user have permission to author content in the given context?

        Uses ACL security policy to test.
        """
        users = find_users(self.context)
        for target in info['targets']:
            if 'error' in target:
                continue
            report_name = target.get('report')
            if report_name is not None:
                pd = find_peopledirectory(self.context)
                context = find_model(pd, report_name.split('+'))
                permission = "email"
            else:
                communities = find_communities(self.context)
                community = communities[target['community']]
                context = community[target['tool']]
                permission = "create"   # XXX In theory could depend on target
            user = users.get_by_id(info['author'])
            if user is not None:
                user = dict(user)
                user['repoze.who.userid'] = info['author']

            # BFG Security API always assumes http request, so we fabricate a
            # fake request.
            request = webob.Request.blank('/')
            request.environ['repoze.who.identity'] = user

            if not has_permission(permission, context, request):
                target['error'] = 'Permission Denied'
Exemple #3
0
    def checkPermission(self, info):
        """ Does user have permission to author content in the given context?

        Uses ACL security policy to test.
        """
        users = find_users(self.context)
        for target in info['targets']:
            if 'error' in target:
                continue
            report_name = target.get('report')
            if report_name is not None:
                pd = find_peopledirectory(self.context)
                context = find_resource(pd, report_name.split('+'))
                permission = "email"
            else:
                communities = find_communities(self.context)
                community = communities[target['community']]
                context = community[target['tool']]
                permission = "create"  # XXX In theory could depend on target
            user = users.get_by_id(info['author'])
            if user is not None:
                user = dict(user)
                # XXX check this!
                user['karl.identity'] = {'id': info['author']}

            # BFG Security API always assumes http request, so we fabricate a
            # fake request.
            request = Request.blank('/')
            request.environ['karl.identity'] = user
            request.context = self.context

            if not has_permission(permission, context, request):
                target['error'] = 'Permission Denied'
Exemple #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.')
Exemple #5
0
    def __call__(self):
        context, request = self.context, self.request
        api = AdminTemplateAPI(context, request, "Admin UI: Send Email")
        admin_email = get_setting(context, "admin_email")
        system_name = get_setting(context, "system_name")
        profiles = find_profiles(context)
        admin = profiles[authenticated_userid(request)]
        from_emails = [
            ("self", "%s <%s>" % (admin.title, admin.email)),
            ("admin", "%s Administrator <%s>" % (system_name, admin_email)),
        ]

        if "send_email" in request.params:
            mailer = getUtility(IMailDelivery)
            group = request.params["to_group"]
            users = find_users(context)
            search = ICatalogSearch(context)
            count, docids, resolver = search(interfaces=[IProfile])
            n = 0
            for docid in docids:
                profile = resolver(docid)
                if getattr(profile, "security_state", None) == "inactive":
                    continue
                userid = profile.__name__
                if group and not users.member_of_group(userid, group):
                    continue

                message = Message()
                if request.params["from_email"] == "self":
                    message["From"] = from_emails[0][1]
                    message_from = admin.email
                else:
                    message["From"] = from_emails[1][1]
                    message_from = admin_email
                message["To"] = "%s <%s>" % (profile.title, profile.email)
                message["Subject"] = request.params["subject"]
                body = u"<html><body>%s</body></html>" % (request.params["text"])
                message.set_payload(body.encode("UTF-8"), "UTF-8")
                message.set_type("text/html")

                mailer.send([profile.email], message)
                n += 1

            status_message = "Sent message to %d users." % n
            if has_permission(ADMINISTER, context, request):
                redirect_to = model_url(context, request, "admin.html", query=dict(status_message=status_message))
            else:
                redirect_to = model_url(
                    find_communities(context),
                    request,
                    "all_communities.html",
                    query=dict(status_message=status_message),
                )

            return HTTPFound(location=redirect_to)

        return dict(api=api, menu=_menu_macro(), to_groups=self.to_groups, from_emails=from_emails)
Exemple #6
0
def jquery_edit_preferred_view(context, request):
    request.response.cache_expires = 0
    communities_folder = find_communities(context)
    communities = get_my_communities(communities_folder,
                                     request,
                                     ignore_preferred=True)
    preferred = get_preferred_communities(communities_folder, request)
    return { 'api': TemplateAPI(context, request),
             'my_communities': communities,
             'preferred': preferred }
Exemple #7
0
def jquery_edit_preferred_view(context, request):
    request.response_headerlist = [('Cache-Control',
        'max-age=0, no-cache, no-store, private, must-revalidate')]
    communities_folder = find_communities(context)
    communities = get_my_communities(communities_folder,
                                     request,
                                     ignore_preferred=True)
    preferred = get_preferred_communities(communities_folder, request)
    return { 'api': TemplateAPI(context, request),
             'my_communities': communities,
             'preferred': preferred }
Exemple #8
0
def jquery_clear_preferred_view(context, request):
    request.response.cache_expires = 0
    communities_folder = find_communities(context)
    set_preferred_communities(communities_folder, request, None)
    updated_communities = get_my_communities(communities_folder, request)
    return { 'api': TemplateAPI(context, request),
             'my_communities': updated_communities,
             'preferred': None,
             'show_all': False,
             'profile': None,
             'status_message': 'Cleared preferred communities.'}
Exemple #9
0
def jquery_list_preferred_view(context, request):
    request.response.cache_expires = 0
    communities_folder = find_communities(context)
    communities = get_my_communities(communities_folder, request)
    preferred = get_preferred_communities(communities_folder, request)
    return { 'api': TemplateAPI(context, request),
             'my_communities': communities,
             'preferred': preferred,
             'show_all': False,
             'profile': None,
             'status_message': None}
Exemple #10
0
def jquery_clear_preferred_view(context, request):
    request.response.cache_expires = 0
    communities_folder = find_communities(context)
    set_preferred_communities(communities_folder, request, None)
    updated_communities = get_my_communities(communities_folder, request)
    return {'api': TemplateAPI(context, request),
            'my_communities': updated_communities,
            'preferred': None,
            'show_all': False,
            'profile': None,
            'status_message': _(u'Cleared preferred communities.')}
Exemple #11
0
def jquery_list_preferred_view(context, request):
    request.response_headerlist = [('Cache-Control',
        'max-age=0, no-cache, no-store, private, must-revalidate')]
    communities_folder = find_communities(context)
    communities = get_my_communities(communities_folder, request)
    preferred = get_preferred_communities(communities_folder, request)
    return { 'api': TemplateAPI(context, request),
             'my_communities': communities,
             'preferred': preferred,
             'show_all': False,
             'profile': None,
             'status_message': None}
Exemple #12
0
def jquery_set_preferred_view(context, request):
    request.response.cache_expires = 0
    communities_folder = find_communities(context)
    communities = request.params.getall('preferred[]')
    set_preferred_communities(communities_folder, request, communities)
    updated_communities = get_my_communities(communities_folder, request)
    return { 'api': TemplateAPI(context, request),
             'my_communities': updated_communities,
             'preferred': communities,
             'show_all': False,
             'profile': None,
             'status_message': 'Set preferred communities.'}
Exemple #13
0
def jquery_set_preferred_view(context, request):
    request.response.cache_expires = 0
    communities_folder = find_communities(context)
    communities = request.params.getall('preferred[]')
    set_preferred_communities(communities_folder, request, communities)
    updated_communities = get_my_communities(communities_folder, request)
    return {'api': TemplateAPI(context, request),
            'my_communities': updated_communities,
            'preferred': communities,
            'show_all': False,
            'profile': None,
            'status_message': _(u'Set preferred communities.')}
Exemple #14
0
    def processMessage(self, message, info, text, attachments):
        community = find_communities(self.root)[info["community"]]
        target = tool = community[info["tool"]]

        # XXX this should be more like:
        if info["in_reply_to"] is not None:
            docid = int(hex_to_docid(info["in_reply_to"]))
            catalog = find_catalog(target)
            path = catalog.document_map.address_for_docid(docid)
            item = find_model(self.root, path)
            target = item

        IMailinHandler(target).handle(message, info, text, attachments)
Exemple #15
0
def get_user_home(context, request):
    # Respect user's home_path, if set
    home, extra_path = _get_user_home_path(context, request)
    if home is not None:
        return home, extra_path

    # If user is member of only one community, home is that community
    communities = find_communities(context)
    community_names = get_user_community_names(context, request)
    if len(community_names) == 1:
        community = communities.get(community_names.pop(), None)
        if community is not None:
            return community, []

    return communities, []
Exemple #16
0
def get_user_home(context, request):
    # Respect user's home_path, if set
    home, extra_path = _get_user_home_path(context, request)
    if home is not None:
        return home, extra_path

    # If user is member of only one community, home is that community
    communities = find_communities(context)
    community_names = get_user_community_names(context, request)
    if len(community_names) == 1:
        community = communities.get(community_names.pop(), None)
        if community is not None:
            return community, []

    return communities, []
Exemple #17
0
def get_user_home(context, request):
    # Respect user's home_path, if set
    home, extra_path = _get_user_home_path(context, request)
    if home is not None:
        return home, extra_path

    communities = find_communities(context)
    behavior = get_setting(context, 'default_home_behavior', 'one_community')
    if behavior == 'one_community':
        # If user is member of only one community, home is that community
        community_names = get_user_community_names(context, request)
        if len(community_names) == 1:
            community = communities.get(community_names.pop(), None)
            if community is not None:
                return community, []

    return communities, []
Exemple #18
0
def get_user_home(context, request):
    # Respect user's home_path, if set
    home, extra_path = _get_user_home_path(context, request)
    if home is not None:
        return home, extra_path

    communities = find_communities(context)
    behavior = get_setting(context, 'default_home_behavior', 'one_community')
    if behavior == 'one_community':
        # If user is member of only one community, home is that community
        community_names = get_user_community_names(context, request)
        if len(community_names) == 1:
            community = communities.get(community_names.pop(), None)
            if community is not None:
                return community, []

    return communities, []
Exemple #19
0
    def process_message(self, message, info, target, text, attachments):
        report_name = target.get('report')
        if report_name is not None:
            pd = find_peopledirectory(self.root)
            context = find_model(pd, report_name.split('+'))
        else:
            community = find_communities(self.root)[target['community']]
            context = tool = community[target['tool']]

            if target['in_reply_to'] is not None:
                docid = int(hex_to_docid(target['in_reply_to']))
                catalog = find_catalog(context)
                path = catalog.document_map.address_for_docid(docid)
                item = find_model(self.root, path)
                context = item

        IMailinHandler(context).handle(message, info, text, attachments)
Exemple #20
0
    def processMessage(self, message, info, text, attachments):
        report_name = info.get('report')
        if report_name is not None:
            pd = find_peopledirectory(self.root)
            target = find_model(pd, report_name.split('+'))
        else:
            community = find_communities(self.root)[info['community']]
            target = tool = community[info['tool']]

            # XXX this should be more like:
            if info['in_reply_to'] is not None:
                docid = int(hex_to_docid(info['in_reply_to']))
                catalog = find_catalog(target)
                path = catalog.document_map.address_for_docid(docid)
                item = find_model(self.root, path)
                target = item

        IMailinHandler(target).handle(message, info, text, attachments)
Exemple #21
0
    def process_message(self, message, info, target, text, attachments):
        report_name = target.get('report')
        if report_name is not None:
            pd = find_peopledirectory(self.root)
            context = find_resource(pd, report_name.split('+'))
        else:
            community = find_communities(self.root)[target['community']]
            context = community[target['tool']]

            if target['in_reply_to'] is not None:
                docid = int(hex_to_docid(target['in_reply_to']))
                catalog = find_catalog(context)
                path = catalog.document_map.address_for_docid(docid)
                if path is None:
                    # replied-to content doesn't exist anymore.
                    # Do not process.
                    return 'Content no longer exists.'
                item = find_resource(self.root, path)
                context = item

        IMailinHandler(context).handle(message, info, text, attachments)
Exemple #22
0
    def process_message(self, message, info, target, text, attachments):
        report_name = target.get('report')
        if report_name is not None:
            pd = find_peopledirectory(self.root)
            context = find_resource(pd, report_name.split('+'))
        else:
            community = find_communities(self.root)[target['community']]
            context = community[target['tool']]

            if target['in_reply_to'] is not None:
                docid = int(hex_to_docid(target['in_reply_to']))
                catalog = find_catalog(context)
                path = catalog.document_map.address_for_docid(docid)
                if path is None:
                    # replied-to content doesn't exist anymore.
                    # Do not process.
                    return 'Content no longer exists.'
                item = find_resource(self.root, path)
                context = item

        IMailinHandler(context).handle(message, info, text, attachments)
Exemple #23
0
    def checkPermission(self, info):
        """
        Uses ACL security policy to determine whether user has permission to
        author content in the given context.
        """
        communities = find_communities(self.context)
        community = communities[info['community']]
        target = community[info['tool']]
        users = find_users(self.context)
        user = users.get_by_id(info['author'])
        if user is not None:
            user['repoze.who.userid'] = info['author']
        permission = "create"   # XXX In theory could depend on target

        # BFG Security API always assumes http request, so we fabricate a fake
        # request.
        request = webob.Request.blank('/')
        request.environ['repoze.who.identity'] = user

        info = {}
        if not has_permission(permission, target, request):
            info['error'] = 'Permission Denied'
        return info
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.')
Exemple #25
0
def show_profile_view(context, request):
    """Show a profile with actions if the current user"""
    page_title = 'View Profile'
    api = TemplateAPI(context, request, page_title)

    # Create display values from model object
    profile = {}
    for name in [name for name in context.__dict__.keys()
                 if not name.startswith("_")]:
        profile_value = getattr(context, name)
        if profile_value is not None:
            # Don't produce u'None'
            profile[name] = unicode(profile_value)
        else:
            profile[name] = None

    if 'fax' not in profile:
        profile['fax'] = '' # BBB

    # 'websites' is a property, so the loop above misses it
    profile["websites"] = context.websites

    # ditto for 'title'
    profile["title"] = context.title

    if profile.has_key("languages"):
        profile["languages"] = context.languages

    if profile.has_key("department"):
        profile["department"] = context.department

    if profile.get("last_login_time"):
        stamp = context.last_login_time.strftime('%Y-%m-%dT%H:%M:%SZ')
        profile["last_login_time"] = stamp

    if profile.has_key("country"):
        # translate from country code to country name
        country_code = profile["country"]
        country = countries.as_dict.get(country_code, u'')
        profile["country"] = country

    # Display portrait
    photo = context.get('photo')
    display_photo = {}
    if photo is not None:
        display_photo["url"] = thumb_url(photo, request, PROFILE_THUMB_SIZE)
    else:
        display_photo["url"] = api.static_url + "/images/defaultUser.gif"
    profile["photo"] = display_photo

    # provide client data for rendering current tags in the tagbox
    client_json_data = dict(
        tagbox = get_tags_client_data(context, request),
        )

    # Get communities this user is a member of, along with moderator info
    #
    communities = {}
    communities_folder = find_communities(context)
    user_info = find_users(context).get_by_id(context.__name__)
    if user_info is not None:
        for group in user_info["groups"]:
            if group.startswith("group.community:"):
                unused, community_name, role = group.split(":")
                if (communities.has_key(community_name) and
                    role != "moderators"):
                    continue

                community = communities_folder.get(community_name, None)
                if community is None:
                    continue

                if has_permission('view', community, request):
                    communities[community_name] = {
                        "title": community.title,
                        "moderator": role == "moderators",
                        "url": resource_url(community, request),
                    }

    communities = communities.values()
    communities.sort(key=lambda x:x["title"])

    preferred_communities = []
    my_communities = None
    name = context.__name__
    # is this the current user's profile?
    if authenticated_userid(request) == name:
        preferred_communities = get_preferred_communities(communities_folder,
                                                          request)
        my_communities = get_my_communities(communities_folder, request)

    tagger = find_tags(context)
    if tagger is None:
        tags = ()
    else:
        tags = []
        names = tagger.getTags(users=[context.__name__])
        for name, count in sorted(tagger.getFrequency(names,
                                                      user=context.__name__),
                                  key=lambda x: x[1],
                                  reverse=True,
                                 )[:10]:
            tags.append({'name': name, 'count': count})

    # List recently added content
    num, docids, resolver = ICatalogSearch(context)(
        sort_index='creation_date', reverse=True,
        interfaces=[IContent], limit=5, creator=context.__name__,
        allowed={'query': effective_principals(request), 'operator': 'or'},
        )
    recent_items = []
    for docid in docids:
        item = resolver(docid)
        if item is None:
            continue
        adapted = getMultiAdapter((item, request), IGridEntryInfo)
        recent_items.append(adapted)

    return render_to_response(
        'templates/profile.pt',
        dict(api=api,
             profile=profile,
             actions=get_profile_actions(context, request),
             photo=photo,
             head_data=convert_to_script(client_json_data),
             communities=communities,
             my_communities=my_communities,
             preferred_communities=preferred_communities,
             tags=tags,
             recent_items=recent_items),
        request=request,
        )
Exemple #26
0
def manage_communities_view(context, request):
    page_title = 'Manage Communities'
    api = TemplateAPI(context, request, page_title)

    users = find_users(context)
    communities_folder = find_communities(context)
    userid = context.__name__

    # Handle cancel
    if request.params.get("form.cancel", False):
        return HTTPFound(location=resource_url(context, request))

    # Handle form submission
    if request.params.get("form.submitted", False):
        for key in request.params:
            if key.startswith("leave_"):
                community_name = key[6:]
                community = communities_folder[community_name]

                # Not concerned about catching this exception, since checkbox
                # should not have been displayed in form unless user allowed
                # to leave.  Assert merely guards integrity of the system.
                assert may_leave(userid, community)

                if userid in community.moderator_names:
                    users.remove_group(userid, community.moderators_group_name)
                if userid in community.member_names:
                    users.remove_group(userid, community.members_group_name)

            elif key.startswith("alerts_pref_"):
                community_name = key[12:]
                preference = int(request.params.get(key))
                context.set_alerts_preference(community_name, preference)

        context.alert_attachments = request.params.get('attachments', 'link')

        path = resource_url(context, request)
        msg = '?status_message=Community+preferences+updated.'
        return HTTPFound(location=path + msg)

    # XXX Iterating over every community in the system isn't a particularly
    #     efficient solution.  Should use catalog.
    communities = []
    for community in communities_folder.values():
        if (userid in community.member_names
                or userid in community.moderator_names):
            alerts_pref = context.get_alerts_preference(community.__name__)
            display_community = {
                'name':
                community.__name__,
                'title':
                community.title,
                'alerts_pref': [
                    {
                        "value": IProfile.ALERT_IMMEDIATELY,
                        "label": "Immediately",
                        "selected": alerts_pref == IProfile.ALERT_IMMEDIATELY,
                    },
                    {
                        "value": IProfile.ALERT_DAILY_DIGEST,
                        "label": "Daily Digest",
                        "selected": alerts_pref == IProfile.ALERT_DAILY_DIGEST,
                    },
                    {
                        "value": IProfile.ALERT_NEVER,
                        "label": "Never",
                        "selected": alerts_pref == IProfile.ALERT_NEVER,
                    },
                    {
                        "value": IProfile.ALERT_WEEKLY_DIGEST,
                        "label": "Weekly Digest",
                        "selected":
                        alerts_pref == IProfile.ALERT_WEEKLY_DIGEST,
                    },
                    {
                        "value": IProfile.ALERT_BIWEEKLY_DIGEST,
                        "label": "Every two weeks Digest",
                        "selected":
                        alerts_pref == IProfile.ALERT_BIWEEKLY_DIGEST,
                    },
                ],
                'may_leave':
                may_leave(userid, community),
            }
            communities.append(display_community)

    if len(communities) > 1:
        communities.sort(key=lambda x: x["title"])

    return render_to_response(
        'karl.views:templates/manage_communities.pt',
        dict(api=api,
             communities=communities,
             post_url=request.url,
             formfields=api.formfields,
             attachments=context.alert_attachments),
        request=request,
    )
Exemple #27
0
def show_profile_view(context, request):
    """Show a profile with actions if the current user"""
    page_title = "Profile: %s" % context.title
    api = TemplateAPI(context, request, page_title)

    # Create display values from model object
    profile = {}
    for name in [
            name for name in context.__dict__.keys()
            if not name.startswith("_")
    ]:
        profile_value = getattr(context, name)
        if profile_value is not None:
            # Don't produce u'None'
            profile[name] = unicode(profile_value)
        else:
            profile[name] = None

    if 'fax' not in profile:
        profile['fax'] = ''  # BBB

    # 'websites' is a property, so the loop above misses it
    profile["websites"] = context.websites

    # ditto for 'title'
    profile["title"] = context.title

    if profile.has_key("languages"):
        profile["languages"] = context.languages

    if profile.has_key("department"):
        profile["department"] = context.department

    if profile.get("last_login_time"):
        stamp = context.last_login_time.strftime('%Y-%m-%dT%H:%M:%SZ')
        profile["last_login_time"] = stamp

    if profile.has_key("country"):
        # translate from country code to country name
        country_code = profile["country"]
        country = countries.as_dict.get(country_code, u'')
        profile["country"] = country

    # Display portrait
    photo = context.get('photo')
    display_photo = {}
    if photo is not None:
        display_photo["url"] = thumb_url(photo, request, PROFILE_THUMB_SIZE)
    else:
        display_photo["url"] = api.static_url + "/images/defaultUser.gif"
    profile["photo"] = display_photo

    # provide client data for rendering current tags in the tagbox
    client_json_data = dict(tagbox=get_tags_client_data(context, request), )

    # Get communities this user is a member of, along with moderator info
    #
    communities = {}
    communities_folder = find_communities(context)
    user_info = find_users(context).get_by_id(context.__name__)
    if user_info is not None:
        for group in user_info["groups"]:
            if group.startswith("group.community:"):
                unused, community_name, role = group.split(":")
                if (communities.has_key(community_name)
                        and role != "moderators"):
                    continue

                community = communities_folder.get(community_name, None)
                if community is None:
                    continue

                if has_permission('view', community, request):
                    communities[community_name] = {
                        "title": community.title,
                        "moderator": role == "moderators",
                        "url": resource_url(community, request),
                    }

    communities = communities.values()
    communities.sort(key=lambda x: x["title"])

    preferred_communities = []
    my_communities = None
    name = context.__name__
    # is this the current user's profile?
    if authenticated_userid(request) == name:
        preferred_communities = get_preferred_communities(
            communities_folder, request)
        my_communities = get_my_communities(communities_folder, request)

    tagger = find_tags(context)
    if tagger is None:
        tags = ()
    else:
        tags = []
        names = tagger.getTags(users=[context.__name__])
        for name, count in sorted(
                tagger.getFrequency(names, user=context.__name__),
                key=lambda x: x[1],
                reverse=True,
        )[:10]:
            tags.append({'name': name, 'count': count})

    # List recently added content
    num, docids, resolver = ICatalogSearch(context)(
        sort_index='creation_date',
        reverse=True,
        interfaces=[IContent],
        limit=5,
        creator=context.__name__,
        allowed={
            'query': effective_principals(request),
            'operator': 'or'
        },
    )
    recent_items = []
    for docid in docids:
        item = resolver(docid)
        if item is None:
            continue
        adapted = getMultiAdapter((item, request), IGridEntryInfo)
        recent_items.append(adapted)
    recent_url = request.resource_url(context, 'recent_content.html')

    return dict(api=api,
                profile=profile,
                actions=get_profile_actions(context, request),
                photo=photo,
                head_data=convert_to_script(client_json_data),
                communities=communities,
                my_communities=my_communities,
                preferred_communities=preferred_communities,
                tags=tags,
                recent_items=recent_items,
                recent_url=recent_url)
Exemple #28
0
def collect_profile_stats(context):
    """
    Returns an iterator where for each user profile a dict is returned with the
    following keys::

        + first_name
        + last_name
        + userid
        + date_created
        + is_staff
        + num_communities
        + num_communities_moderator
        + location
        + department
        + roles
        + num_documents
        + num_tags
        + documents_this_month
    """
    communities = find_communities(context)
    search = ICatalogSearch(context)
    profiles = find_profiles(context)
    users = find_users(context)

    # Collect community membership
    membership = {}
    moderatorship = {}
    for community in communities.values():
        for name in community.member_names:
            if name not in membership:
                membership[name] = 1
            else:
                membership[name] += 1
        for name in community.moderator_names:
            if name not in moderatorship:
                moderatorship[name] = 1
            else:
                moderatorship[name] += 1

    for profile in profiles.values():
        info = users.get_by_id(profile.__name__)
        if info is not None:
            groups = info['groups']
        else:
            groups = []
        name = profile.__name__
        stats = dict(
            first_name=profile.firstname,
            last_name=profile.lastname,
            userid=name,
            date_created=profile.created,
            location=profile.location,
            department=profile.department,
            is_staff='group.KarlStaff' in groups,
            roles=','.join(groups),
            num_communities=membership.get(name, 0),
            num_communities_moderator=moderatorship.get(name, 0),
        )

        count, docids, resolver = search(creator=name)
        stats['num_documents'] = count

        begin = coarse_datetime_repr(datetime.datetime.now() - THIRTY_DAYS)
        count, docids, resolver = search(
            creator=name, creation_date=(begin, None),
        )
        stats['documents_this_month'] = count

        tags = find_tags(context)
        stats['num_tags'] = len(tags.getTags(users=(name,)))

        yield stats
Exemple #29
0
def collect_community_stats(context):
    """
    Returns an iterator of dicts where for each community in the site a dict
    is returned containing the following keys::

      + 'community': The community's full title.
      + 'id': The community's name, used in the path to the community.
      + 'security state': The name of the community's current security state.
        Will be 'custom' if acl has been manually changed with edit_acl.html.
      + 'members': Total number of members, including moderators.
      + 'moderators': Number of moderators.
      + 'last_activity': Date of last time some content was added to or edited
         in this community.
      + 'create_date': Date community was created.
      + 'wiki_pages': Number of wiki pages in this community.
      + 'blog_entries': Number of blog entries in this community.
      + 'comments': Number of comments in this community.
      + 'files': Number of files in this community.
      + 'calendar_events': Number of calendar events in this community.
      + 'community_tags': Number of tags used in this community.  Includes tags
        on content contained by the community.
      + 'percent_engaged': Percentage of community members that have
        contributed 2 items or more in the last 30 days.
    """
    now = datetime.datetime.now()
    communities = find_communities(context)
    for community in communities.values():
        stats = dict(
            community=community.title,
            id=community.__name__,
            members=len(community.member_names),
            moderators=len(community.moderator_names),
            last_activity=community.content_modified,
            create_date=community.created,
            wiki_pages=0,
            blog_entries=0,
            comments=0,
            files=0,
            calendar_events=0,
        )

        active_users = {}

        def count(node):
            from pyramid.traversal import resource_path
            if IWikiPage.providedBy(node):
                stats['wiki_pages'] += 1
            elif IBlogEntry.providedBy(node):
                stats['blog_entries'] += 1
            elif IComment.providedBy(node):
                stats['comments'] += 1
            elif ICommunityFile.providedBy(node):
                stats['files'] += 1
            elif ICalendarEvent.providedBy(node):
                stats['calendar_events'] += 1

            created = getattr(node, 'created', None)
            if created is not None and now - created < THIRTY_DAYS:
                creator = getattr(node, 'creator', None)
                if creator is not None:
                    if creator not in active_users:
                        active_users[creator] = 1
                    else:
                        active_users[creator] += 1

            if hasattr(node, '__getitem__') and hasattr(node, 'values'):
                for child in node.values():
                    count(child)

            if hasattr(node, '_p_deactivate'):
                node._p_deactivate()

        count(community)

        tags = find_tags(context)
        stats['community_tags'] = len(tags.getTags(
            community=community.__name__
        ))

        if hasattr(community, '__custom_acl__'):
            stats['security_state'] = 'custom'
        else:
            workflow = get_workflow(ICommunity, 'security', community)
            stats['security_state'] = workflow.state_of(community)

        if stats['members'] != 0:
            engaged_users = len([v for v in active_users.values() if v >= 2])
            stats['percent_engaged'] = 100.0 * engaged_users / stats['members']
        else:
            stats['percent_engaged'] = 0

        yield stats
Exemple #30
0
    def __call__(self):
        context, request = self.context, self.request
        request.layout_manager.use_layout('admin')
        api = AdminTemplateAPI(context, request, 'Admin UI: Send Email')
        admin_email = get_setting(context, 'admin_email')
        system_name = get_setting(context, 'system_name')
        profiles = find_profiles(context)
        admin = profiles[authenticated_userid(request)]
        from_emails = [
            ('self', '%s <%s>' % (admin.title, admin.email)),
            ('admin', '%s Administrator <%s>' % (system_name, admin_email)),
        ]

        if 'send_email' in request.params or 'submit' in request.params:
            mailer = getUtility(IMailDelivery)
            group = request.params['to_group']
            users = find_users(context)
            search = ICatalogSearch(context)
            count, docids, resolver = search(interfaces=[IProfile])
            n = 0
            for docid in docids:
                profile = resolver(docid)
                if getattr(profile, 'security_state', None) == 'inactive':
                    continue
                userid = profile.__name__
                if group and not users.member_of_group(userid, group):
                    continue

                message = Message()
                if request.params['from_email'] == 'self':
                    message['From'] = from_emails[0][1]
                    message_from = admin.email
                else:
                    message['From'] = from_emails[1][1]
                    message_from = admin_email
                message['To'] = '%s <%s>' % (profile.title, profile.email)
                message['Subject'] = request.params['subject']
                body = u'<html><body>%s</body></html>' % (
                    request.params['text']
                )
                message.set_payload(body.encode('UTF-8'), 'UTF-8')
                message.set_type('text/html')

                mailer.send([profile.email], message)
                n += 1

            status_message = "Sent message to %d users." % n
            if has_permission(ADMINISTER, context, request):
                redirect_to = resource_url(
                    context, request, 'admin.html',
                    query=dict(status_message=status_message))
            else:
                redirect_to = resource_url(
                    find_communities(context), request, 'all_communities.html',
                    query=dict(status_message=status_message))

            return HTTPFound(location=redirect_to)

        return dict(
            api=api,
            menu=_menu_macro(),
            to_groups = self.to_groups,
            from_emails=from_emails,
        )
Exemple #31
0
def myprofile_ajax_view(context, request):
    results = {}
    # template provision
    if request.params.get('needsTemplate', 'false') in ('true', 'True'):
        # We need the template. So, let's fetch it.
        layout = request.layout_manager.layout
        results['microtemplate'] = layout.microtemplates['myprofile']
        results['partials'] = []
    # Fetch the data

    # 2nd column: my communities (preferred communities)
    communities_folder = find_communities(context)
    communities = get_my_communities(communities_folder, request)
    communities = sorted(communities,
                         key=attrgetter('last_activity_date'),
                         reverse=True)
    communities_info = [
        dict(
            title=community.title,
            description=community.description,
            url=community.url,
            actions=[dict(
                url=community.url + (a_name if a_name != 'overview' else 'view.html'),
                title=a_name.capitalize(),
                last=a_name == 'wiki',
                ) for a_name in ('overview', 'blog', 'calendar', 'files', 'wiki')],
        )
        for community in communities[:5]
    ]

    # 3rd column: My Recent Activity
    recent_items = []
    recent_items_batch = get_catalog_batch(context, request, batch_size=5,
        interfaces=[ICommunityContent], sort_index="modified_date",
        reverse=True, modified_by=authenticated_userid(request),
        allowed={'query': effective_principals(request), 'operator': 'or'})

    for item in recent_items_batch["entries"]:
        adapted = getMultiAdapter((item, request), IGridEntryInfo)
        community = find_community(item)
        if community is not None:
            community_adapter = getMultiAdapter((community, request),
                                                ICommunityInfo)
            community_info = dict(
                url=community_adapter.url,
                title=community_adapter.title,
            )
        else:
            community_info = None
        # Since this is json, we need a real dict...
        recent_items.append(dict(
            title=adapted.title,
            url=adapted.url,
            modified=item.modified.strftime('%Y-%m-%dT%H:%M:%S'),
            creator_title=adapted.creator_title,
            type=adapted.type,
            community=community_info,
            ))

    profiles = find_profiles(request.context)
    userid = authenticated_userid(request)
    profile = profiles.get(userid)

    photo = profile.get('photo')
    if photo is not None:
        icon_url = thumb_url(photo, request, (45,60))
    else:
        icon_url = request.static_url('karl.views:static/images/defaultUser.gif')
    # Assemble the final result.
    results['data'] = {
        'profile_name': profile.title,
        'profile_url': request.resource_url(profile),
        'icon_url': icon_url,
        'logout_url': "%s/logout.html" % request.application_url,
        'department': profile.department,
        'position': profile.position,
        'email': profile.email,
        'extension': profile.extension,
        'phone': profile.phone,
        'panels': [{
            'class': 'mycommunities',
            'title': 'My Active Communities',
            'communities': communities_info,
            }, {
            'class': 'myrecentitems',
            'title': 'My Recent Activity',
            'contexts': recent_items,
            }],
        }

    return results
Exemple #32
0
def radar_ajax_view(context, request):
    # Example result set, for demonstrating the widget without
    # a real server database.
    results = {}
    # Datetime of the current search. (The client will pass it back
    # to us the next time, and we can decide if an update is needed)
    now = datetime.datetime.now()
    now_iso = now.isoformat()
    results['ts'] = now_iso
    ts_iso = request.params.get('ts', '')
    # template provision
    if request.params.get('needsTemplate', 'false') in ('true', 'True'):
        # We need the template. So, let's fetch it.
        layout = request.layout_manager.layout
        results['microtemplate'] = layout.microtemplates['radar']
        results['partials'] = []
    # Sometimes there is no need for an update. The server can just return
    # empty data. A condition is that a ts parameter is sent to us. The
    # other condition (does the client need an update?) is now simulated
    # with a random choice.
    if ts_iso and random.choice([False, True]):
        results['data'] = None
    else:
        # Fetch the data

        # 2nd column: my communities (preferred communities)
        communities_folder = find_communities(context)
        communities = get_my_communities(communities_folder, request)
        communities_info = [
            dict(
                title=community.title,
                description=community.description,
                url=community.url,
                actions=[
                    dict(
                        url=community.url +
                        (a_name if a_name != 'overview' else 'view.html'),
                        title=a_name.capitalize(),
                        last=a_name == 'files',
                    ) for a_name in ('overview', 'blog', 'calendar', 'files',
                                     'wiki')
                ],
            ) for community in communities[:5]
        ]

        # 3rd column: My Recent Activity
        recent_items = []
        recent_items_batch = get_catalog_batch(
            context,
            request,
            batch_size=5,
            interfaces=[ICommunityContent],
            sort_index="modified_date",
            reverse=True,
            modified_by=authenticated_userid(request),
            allowed={
                'query': effective_principals(request),
                'operator': 'or'
            })

        for item in recent_items_batch["entries"]:
            adapted = getMultiAdapter((item, request), IGridEntryInfo)
            community = find_community(item)
            if community is not None:
                community_adapter = getMultiAdapter((community, request),
                                                    ICommunityInfo)
                community_info = dict(
                    url=community_adapter.url,
                    title=community_adapter.title,
                )
            else:
                community_info = None
            # Since this is json, we need a real dict...
            recent_items.append(
                dict(
                    title=adapted.title,
                    url=adapted.url,
                    modified=adapted.modified,
                    creator_title=adapted.creator_title,
                    type=adapted.type,
                    community=community_info,
                ))

        # Provide fake "approval items" for the "approvals" tab.

        approval_waitinglist_items = [{
            'title':
            'Approval Waiting List',
            'group': [{
                'title': 'e-Payment',
                'count': 0,
                'id': 'table1'
            }, {
                'title': 'Grant Payment',
                'count': 2,
                'id': 'table2'
            }, {
                'title': 'Contract Review',
                'count': 3,
            }, {
                'title': 'Contract Approval',
                'count': 2,
            }, {
                'title': 'Contract Payment',
                'count': 1,
            }, {
                'title': 'Hardware / Software Request',
                'count': 4,
            }]
        }, {
            'title':
            'Payment Waiting List',
            'group': [{
                'title': 'e-Payment',
                'count': 0,
            }, {
                'title': 'Grant Payment',
                'count': 133,
            }, {
                'title': 'Contract Payment',
                'count': 116,
            }]
        }, {
            'title':
            'Accrual Waiting List',
            'group': [{
                'title': 'Grant Accrual',
                'count': 7,
            }]
        }, {
            'title':
            'Fixed Assets Waiting List',
            'group': [{
                'title': 'e-Approval',
                'count': 7,
            }, {
                'title': 'e-Bridge for Posting',
                'count': 3,
            }]
        }]

        approval_table1_items = [{
            'amt': '45.09',
            'via': 'Check',
            'approvedBy': 'Some Person',
            'status': 'Approved',
            'statusDate': '02/09/2012',
            'overdueBy': '13',
        }, {
            'amt': '13.00',
            'via': 'Wire',
            'approvedBy': 'Another Person',
            'status': 'Submitted',
            'statusDate': '02/14/2012',
            'overdueBy': '16',
        }, {
            'amt': '71.21',
            'via': 'Check',
            'approvedBy': 'Last Person',
            'status': 'Approved',
            'statusDate': '02/13/2012',
            'overdueBy': '18',
        }]

        for i, row in enumerate(approval_table1_items):
            row['rowClass'] = 'even' if i % 2 else 'odd'

        import copy
        approval_table2_items = 2 * copy.deepcopy(approval_table1_items)
        for i, row in enumerate(approval_table2_items):
            row['rowClass'] = 'even' if i % 2 else 'odd'

        # Assemble the final result.
        results['data'] = {
            # home section
            'home': [{
                'class': 'homepanel1',
                'title': 'My Communities',
                'communities': communities_info,
            }, {
                'class': 'homepanel2',
                'title': 'My Recent Activity',
                'contexts': recent_items,
            }],
            # approvals section
            'approvals': [{
                'class': 'approvalpanel1',
                'waitinglist': {
                    'items': approval_waitinglist_items,
                },
            }, {
                'class':
                'approvalpanel2',
                'tables': [{
                    'id': 'table1',
                    'title': 'Open Project Project',
                    'items': approval_table1_items,
                }, {
                    'id': 'table2',
                    'title': 'Very Open Project',
                    'items': approval_table2_items,
                }],
            }],
        }

        results['state'] = {
            'chart1': {
                'options': {
                    'title': 'Company Performance',
                    'hAxis': {
                        'title': 'Year',
                        'titleTextStyle': {
                            'color': 'red'
                        },
                    },
                    'width': 200,  # Must have fixed width! (matching css)
                },
                'columns': [
                    ['string', 'Year'],
                    ['number', 'Sales'],
                    ['number', 'Expenses'],
                ],
                'rows': [
                    ['2004', 1000, 400],
                    ['2005', 1170, 460],
                    ['2006', 660, 1120],
                    ['2007', 1030, 540],
                ],
            },
            'chart2': {
                'options': {
                    'title': 'Monthly Operating Revenue',
                    'hAxis': {
                        'title': 'Project',
                        'titleTextStyle': {
                            'color': 'red'
                        },
                    },
                    'width': 400,  # Must have fixed width! (matching css)
                },
                'columns': [
                    ['string', 'Project'],
                    ['number', 'Budgeted'],
                    ['number', 'Actual'],
                ],
                'rows': [
                    ['My First Project', 1000, 400],
                    ['Another Project', 1170, 460],
                    ['A Third Project', 660, 1120],
                ],
            },
        }

    return results
Exemple #33
0
    def __call__(self):
        context, request = self.context, self.request
        api = AdminTemplateAPI(context, request, 'Admin UI: Send Email')
        admin_email = get_setting(context, 'admin_email')
        system_name = get_setting(context, 'system_name')
        profiles = find_profiles(context)
        admin = profiles[authenticated_userid(request)]
        from_emails = [
            ('self', '%s <%s>' % (admin.title, admin.email)),
            ('admin', '%s Administrator <%s>' % (system_name, admin_email)),
        ]

        if 'send_email' in request.params:
            mailer = getUtility(IMailDelivery)
            group = request.params['to_group']
            users = find_users(context)
            search = ICatalogSearch(context)
            count, docids, resolver = search(interfaces=[IProfile])
            n = 0
            for docid in docids:
                profile = resolver(docid)
                if getattr(profile, 'security_state', None) == 'inactive':
                    continue
                userid = profile.__name__
                if group and not users.member_of_group(userid, group):
                    continue

                message = Message()
                if request.params['from_email'] == 'self':
                    message['From'] = from_emails[0][1]
                    message_from = admin.email
                else:
                    message['From'] = from_emails[1][1]
                    message_from = admin_email
                message['To'] = '%s <%s>' % (profile.title, profile.email)
                message['Subject'] = request.params['subject']
                body = u'<html><body>%s</body></html>' % (
                    request.params['text'])
                message.set_payload(body.encode('UTF-8'), 'UTF-8')
                message.set_type('text/html')

                mailer.send([profile.email], message)
                n += 1

            status_message = "Sent message to %d users." % n
            if has_permission(ADMINISTER, context, request):
                redirect_to = resource_url(
                    context,
                    request,
                    'admin.html',
                    query=dict(status_message=status_message))
            else:
                redirect_to = resource_url(
                    find_communities(context),
                    request,
                    'all_communities.html',
                    query=dict(status_message=status_message))

            return HTTPFound(location=redirect_to)

        return dict(
            api=api,
            menu=_menu_macro(),
            to_groups=self.to_groups,
            from_emails=from_emails,
        )
Exemple #34
0
 def test_find_communities(self):
     from karl.utils import find_communities
     context = testing.DummyModel()
     self.assertEqual(find_communities(context), None)
     cf = context['communities'] = testing.DummyModel()
     self.failUnless(find_communities(context) is cf)
Exemple #35
0
def radar_ajax_view(context, request):
    # Example result set, for demonstrating the widget without
    # a real server database.
    results = {}
    # Datetime of the current search. (The client will pass it back
    # to us the next time, and we can decide if an update is needed)
    now = datetime.datetime.now()
    now_iso = now.isoformat()
    results['ts'] = now_iso
    ts_iso = request.params.get('ts', '')
    # template provision
    if request.params.get('needsTemplate', 'false') in ('true', 'True'):
        # We need the template. So, let's fetch it.
        layout = request.layout_manager.layout
        results['microtemplate'] = layout.microtemplates['radar']
        results['partials'] = []
    # Sometimes there is no need for an update. The server can just return
    # empty data. A condition is that a ts parameter is sent to us. The
    # other condition (does the client need an update?) is now simulated
    # with a random choice.
    if ts_iso and random.choice([False, True]):
        results['data'] = None
    else:
        # Fetch the data

        # 2nd column: my communities (preferred communities)
        communities_folder = find_communities(context)
        communities = get_my_communities(communities_folder, request)
        communities_info = [
            dict(
                title=community.title,
                description=community.description,
                url=community.url,
                actions=[dict(
                    url=community.url + (a_name if a_name != 'overview' else 'view.html'),
                    title=a_name.capitalize(),
                    last=a_name == 'files',
                    ) for a_name in ('overview', 'blog', 'calendar', 'files', 'wiki')],
            )
            for community in communities[:5]
        ]

        # 3rd column: My Recent Activity
        recent_items = []
        recent_items_batch = get_catalog_batch(context, request, batch_size=5,
            interfaces=[ICommunityContent], sort_index="modified_date",
            reverse=True, modified_by=authenticated_userid(request),
            allowed={'query': effective_principals(request), 'operator': 'or'})

        for item in recent_items_batch["entries"]:
            adapted = getMultiAdapter((item, request), IGridEntryInfo)
            community = find_community(item)
            if community is not None:
                community_adapter = getMultiAdapter((community, request), ICommunityInfo)
                community_info = dict(
                    url=community_adapter.url,
                    title=community_adapter.title,
                )
            else:
                community_info = None
            # Since this is json, we need a real dict...
            recent_items.append(dict(
                title=adapted.title,
                url=adapted.url,
                modified=adapted.modified,
                creator_title=adapted.creator_title,
                type=adapted.type,
                community=community_info,
                ))

        # Provide fake "approval items" for the "approvals" tab.

        approval_waitinglist_items = [{
            'title': 'Approval Waiting List',
            'group': [{
                'title': 'e-Payment',
                'count': 0,
                'id': 'table1'
                }, {
                'title': 'Grant Payment',
                'count': 2,
                'id': 'table2'
                }, {
                'title': 'Contract Review',
                'count': 3,
                }, {
                'title': 'Contract Approval',
                'count': 2,
                }, {
                'title': 'Contract Payment',
                'count': 1,
                }, {
                'title': 'Hardware / Software Request',
                'count': 4,
                }
            ]
        }, {
            'title': 'Payment Waiting List',
            'group': [{
                'title': 'e-Payment',
                'count': 0,
                }, {
                'title': 'Grant Payment',
                'count': 133,
                }, {
                'title': 'Contract Payment',
                'count': 116,
                }
            ]
        }, {
            'title': 'Accrual Waiting List',
            'group': [{
                'title': 'Grant Accrual',
                'count': 7,
                }
            ]

        }, {
            'title': 'Fixed Assets Waiting List',
            'group': [{
                'title': 'e-Approval',
                'count': 7,
                }, {
                'title': 'e-Bridge for Posting',
                'count': 3,
                }
            ]

        }];


        approval_table1_items = [{
            'amt': '45.09',
            'via': 'Check',
            'approvedBy': 'Some Person',
            'status': 'Approved',
            'statusDate': '02/09/2012',
            'overdueBy': '13',
            }, {
            'amt': '13.00',
            'via': 'Wire',
            'approvedBy': 'Another Person',
            'status': 'Submitted',
            'statusDate': '02/14/2012',
            'overdueBy': '16',
            }, {
            'amt': '71.21',
            'via': 'Check',
            'approvedBy': 'Last Person',
            'status': 'Approved',
            'statusDate': '02/13/2012',
            'overdueBy': '18',
            }]

        for i, row in enumerate(approval_table1_items):
            row['rowClass'] = 'even' if i % 2 else 'odd'

        import copy
        approval_table2_items = 2 * copy.deepcopy(approval_table1_items)
        for i, row in enumerate(approval_table2_items):
            row['rowClass'] = 'even' if i % 2 else 'odd'

        # Assemble the final result.
        results['data'] = {
            # home section
            'home': [{
                'class': 'homepanel1',
                'title': 'My Communities',
                'communities': communities_info,
                }, {
                'class': 'homepanel2',
                'title': 'My Recent Activity',
                'contexts': recent_items,
                }],
            # approvals section
            'approvals': [{
                'class': 'approvalpanel1',
                'waitinglist': {
                    'items': approval_waitinglist_items,
                    },
                }, {
                'class': 'approvalpanel2',
                'tables': [{
                    'id': 'table1',
                    'title': 'Open Project Project',
                    'items': approval_table1_items,
                    }, {
                    'id': 'table2',
                    'title': 'Very Open Project',
                    'items': approval_table2_items,
                    }],
                }],
            }

        results['state'] = {
            'chart1': {
                'options' : {
                    'title': 'Company Performance',
                    'hAxis': {
                        'title': 'Year',
                        'titleTextStyle': {'color': 'red'},
                        },
                    'width': 200,      # Must have fixed width! (matching css)
                    },
                'columns': [
                    ['string', 'Year'],
                    ['number', 'Sales'],
                    ['number', 'Expenses'],
                    ],
                'rows': [
                    ['2004', 1000, 400],
                    ['2005', 1170, 460],
                    ['2006', 660, 1120],
                    ['2007', 1030, 540],
                    ],
                },
            'chart2': {
                'options' : {
                    'title': 'Monthly Operating Revenue',
                    'hAxis': {
                        'title': 'Project',
                        'titleTextStyle': {'color': 'red'},
                        },
                    'width': 400,      # Must have fixed width! (matching css)
                    },
                'columns': [
                    ['string', 'Project'],
                    ['number', 'Budgeted'],
                    ['number', 'Actual'],
                    ],
                'rows': [
                    ['My First Project', 1000, 400],
                    ['Another Project', 1170, 460],
                    ['A Third Project', 660, 1120],
                    ],
                },
            }


    return results
Exemple #36
0
def manage_communities_view(context, request):
    assert IProfile.providedBy(context)

    page_title = 'Manage Communities'
    api = TemplateAPI(context, request, page_title)

    users = find_users(context)
    communities_folder = find_communities(context)
    userid = context.__name__

    # Handle cancel
    if request.params.get("form.cancel", False):
        return HTTPFound(location=resource_url(context, request))

    # Handle form submission
    if request.params.get("form.submitted", False):
        for key in request.params:
            if key.startswith("leave_"):
                community_name = key[6:]
                community = communities_folder[community_name]

                # Not concerned about catching this exception, since checkbox
                # should not have been displayed in form unless user allowed
                # to leave.  Assert merely guards integrity of the system.
                assert may_leave(userid, community)

                if userid in community.moderator_names:
                    users.remove_group(userid, community.moderators_group_name)
                if userid in community.member_names:
                    users.remove_group(userid, community.members_group_name)

            elif key.startswith("alerts_pref_"):
                community_name = key[12:]
                preference = int(request.params.get(key))
                context.set_alerts_preference(community_name, preference)

        context.alert_attachments = request.params.get('attachments', 'link')

        path = resource_url(context, request)
        msg = '?status_message=Community+preferences+updated.'
        return HTTPFound(location=path+msg)

    # XXX Iterating over every community in the system isn't a particularly
    #     efficient solution.  Should use catalog.
    communities = []
    for community in communities_folder.values():
        if (userid in community.member_names or
            userid in community.moderator_names):
            alerts_pref = context.get_alerts_preference(community.__name__)
            display_community = {
                'name': community.__name__,
                'title': community.title,
                'alerts_pref': [
                    { "value": IProfile.ALERT_IMMEDIATELY,
                      "label": "Immediately",
                      "selected": alerts_pref == IProfile.ALERT_IMMEDIATELY,
                    },
                    { "value": IProfile.ALERT_DIGEST,
                      "label": "Digest",
                      "selected": alerts_pref == IProfile.ALERT_DIGEST,
                    },
                    { "value": IProfile.ALERT_NEVER,
                      "label": "Never",
                      "selected": alerts_pref == IProfile.ALERT_NEVER,
                    }],
                'may_leave': may_leave(userid, community),
            }
            communities.append(display_community)

    if len(communities) > 1:
        communities.sort(key=lambda x: x["title"])

    return render_to_response(
        'karl.views:templates/manage_communities.pt',
        dict(api=api,
             communities=communities,
             post_url=request.url,
             formfields=api.formfields,
             attachments=context.alert_attachments),
        request=request,
    )
Exemple #37
0
def collect_community_stats(context):
    """
    Returns an iterator of dicts where for each community in the site a dict
    is returned containing the following keys::

      + 'community': The community's full title.
      + 'id': The community's name, used in the path to the community.
      + 'security state': The name of the community's current security state.
        Will be 'custom' if acl has been manually changed with edit_acl.html.
      + 'members': Total number of members, including moderators.
      + 'moderators': Number of moderators.
      + 'last_activity': Date of last time some content was added to or edited
         in this community.
      + 'create_date': Date community was created.
      + 'wiki_pages': Number of wiki pages in this community.
      + 'blog_entries': Number of blog entries in this community.
      + 'comments': Number of comments in this community.
      + 'files': Number of files in this community.
      + 'calendar_events': Number of calendar events in this community.
      + 'community_tags': Number of tags used in this community.  Includes tags
        on content contained by the community.
      + 'percent_engaged': Percentage of community members that have
        contributed 2 items or more in the last 30 days.
    """
    now = datetime.datetime.now()
    communities = find_communities(context)
    for community in communities.values():
        stats = dict(
            community=community.title,
            id=community.__name__,
            members=len(community.member_names),
            moderators=len(community.moderator_names),
            last_activity=community.content_modified,
            create_date=community.created,
            wiki_pages=0,
            blog_entries=0,
            comments=0,
            files=0,
            calendar_events=0,
        )

        active_users = {}

        def count(node):
            from repoze.bfg.traversal import model_path
            if IWikiPage.providedBy(node):
                stats['wiki_pages'] += 1
            elif IBlogEntry.providedBy(node):
                stats['blog_entries'] += 1
            elif IComment.providedBy(node):
                stats['comments'] += 1
            elif ICommunityFile.providedBy(node):
                stats['files'] += 1
            elif ICalendarEvent.providedBy(node):
                stats['calendar_events'] += 1

            created = getattr(node, 'created', None)
            if created is not None and now - created < THIRTY_DAYS:
                creator = getattr(node, 'creator', None)
                if creator is not None:
                    if creator not in active_users:
                        active_users[creator] = 1
                    else:
                        active_users[creator] += 1

            if hasattr(node, '__getitem__') and hasattr(node, 'values'):
                for child in node.values():
                    count(child)

            if hasattr(node, '_p_deactivate'):
                node._p_deactivate()

        count(community)

        tags = find_tags(context)
        stats['community_tags'] = len(tags.getTags(
            community=community.__name__
        ))

        if hasattr(community, '__custom_acl__'):
            stats['security_state'] = 'custom'
        else:
            workflow = get_workflow(ICommunity, 'security', community)
            stats['security_state'] = workflow.state_of(community)

        if stats['members'] != 0:
            engaged_users = len([v for v in active_users.values() if v >= 2])
            stats['percent_engaged'] = 100.0 * engaged_users / stats['members']
        else:
            stats['percent_engaged'] = 0

        yield stats
Exemple #38
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)
Exemple #39
0
def myprofile_ajax_view(context, request):
    results = {}
    # template provision
    if request.params.get('needsTemplate', 'false') in ('true', 'True'):
        # We need the template. So, let's fetch it.
        layout = request.layout_manager.layout
        results['microtemplate'] = layout.microtemplates['myprofile']
        results['partials'] = []
    # Fetch the data

    # 2nd column: my communities (preferred communities)
    communities_folder = find_communities(context)
    communities = get_my_communities(communities_folder, request)
    communities = sorted(communities,
                         key=attrgetter('last_activity_date'),
                         reverse=True)
    communities_info = [
        dict(
            title=community.title,
            description=community.description,
            url=community.url,
            actions=[
                dict(
                    url=community.url +
                    (a_name if a_name != 'overview' else 'view.html'),
                    title=a_name.capitalize(),
                    last=a_name == 'wiki',
                )
                for a_name in ('overview', 'blog', 'calendar', 'files', 'wiki')
            ],
        ) for community in communities[:5]
    ]

    # 3rd column: My Recent Activity
    recent_items = []
    recent_items_batch = get_catalog_batch(
        context,
        request,
        batch_size=5,
        interfaces=[ICommunityContent],
        sort_index="modified_date",
        reverse=True,
        modified_by=authenticated_userid(request),
        allowed={
            'query': effective_principals(request),
            'operator': 'or'
        })

    for item in recent_items_batch["entries"]:
        adapted = getMultiAdapter((item, request), IGridEntryInfo)
        community = find_community(item)
        if community is not None:
            community_adapter = getMultiAdapter((community, request),
                                                ICommunityInfo)
            community_info = dict(
                url=community_adapter.url,
                title=community_adapter.title,
            )
        else:
            community_info = None
        # Since this is json, we need a real dict...
        recent_items.append(
            dict(
                title=adapted.title,
                url=adapted.url,
                modified=item.modified.strftime('%Y-%m-%dT%H:%M:%S'),
                creator_title=adapted.creator_title,
                type=adapted.type,
                community=community_info,
            ))

    profiles = find_profiles(request.context)
    userid = authenticated_userid(request)
    profile = profiles.get(userid)

    photo = profile.get('photo')
    if photo is not None:
        icon_url = thumb_url(photo, request, (45, 60))
    else:
        icon_url = request.static_url(
            'karl.views:static/images/defaultUser.gif')
    # Assemble the final result.
    results['data'] = {
        'profile_name':
        profile.title,
        'profile_url':
        request.resource_url(profile),
        'icon_url':
        icon_url,
        'logout_url':
        "%s/logout.html" % request.application_url,
        'department':
        profile.department,
        'position':
        profile.position,
        'email':
        profile.email,
        'extension':
        profile.extension,
        'phone':
        profile.phone,
        'panels': [{
            'class': 'mycommunities',
            'title': 'My Active Communities',
            'communities': communities_info,
        }, {
            'class': 'myrecentitems',
            'title': 'My Recent Activity',
            'contexts': recent_items,
        }],
    }

    return results
Exemple #40
0
def collect_profile_stats(context):
    """
    Returns an iterator where for each user profile a dict is returned with the
    following keys::

        + first_name
        + last_name
        + userid
        + date_created
        + is_staff
        + num_communities
        + num_communities_moderator
        + location
        + department
        + roles
        + num_documents
        + num_tags
        + documents_this_month
    """
    communities = find_communities(context)
    search = ICatalogSearch(context)
    profiles = find_profiles(context)
    users = find_users(context)

    # Collect community membership
    membership = {}
    moderatorship = {}
    for community in communities.values():
        for name in community.member_names:
            if name not in membership:
                membership[name] = 1
            else:
                membership[name] += 1
        for name in community.moderator_names:
            if name not in moderatorship:
                moderatorship[name] = 1
            else:
                moderatorship[name] += 1

    for profile in profiles.values():
        info = users.get_by_id(profile.__name__)
        if info is not None:
            groups = info['groups']
        else:
            groups = []
        name = profile.__name__
        stats = dict(
            first_name=profile.firstname,
            last_name=profile.lastname,
            userid=name,
            date_created=profile.created,
            location=profile.location,
            department=profile.department,
            is_staff='group.KarlStaff' in groups,
            roles=','.join(groups),
            num_communities=membership.get(name, 0),
            num_communities_moderator=moderatorship.get(name, 0),
        )

        count, docids, resolver = search(creator=name)
        stats['num_documents'] = count

        begin = coarse_datetime_repr(datetime.datetime.now() - THIRTY_DAYS)
        count, docids, resolver = search(
            creator=name, creation_date=(begin, None),
        )
        stats['documents_this_month'] = count

        tags = find_tags(context)
        stats['num_tags'] = len(tags.getTags(users=(name,)))

        yield stats
Exemple #41
0
 def isCommunity(self, name):
     """ See IMailinDispatcher.
     """
     return name in find_communities(self.context)
Exemple #42
0
 def test_find_communities(self):
     from karl.utils import find_communities
     context = testing.DummyModel()
     self.assertEqual(find_communities(context), None)
     cf = context['communities'] = testing.DummyModel()
     self.failUnless(find_communities(context) is cf)
Exemple #43
0
 def isCommunity(self, name):
     """ See IMailinDispatcher.
     """
     return name in find_communities(self.context)
Exemple #44
0
def lookup_community(site, community_slug):
    communities = find_communities(site)
    return communities and communities.get(community_slug)