def participants_json_data(self): """ Return a json object with participant data. Will return json with this structure: .. code-block :: py {'userid':{'userinfo': <html structure with firstname, lastname and userid>, 'email': '<email>', 'extras: {'extra_data': '<extra_data>',}, 'role_discuss': '<bool>', #<etc...>, } """ users = self.api.root.users results = {} #Find the users for userid in security.find_authorized_userids(self.context, (security.VIEW,)): user = users.get(userid, None) if user: results[userid] = dict( userinfo = self.api.get_creators_info((userid,), portrait = False), email = user.get_field_value('email', u""), #Make sure context is meeting here! roles = self.context.get_groups(userid) ) return results
def scout_participants_json_data(self): """ Return a json object with participant data. Will return json with this structure: .. code-block :: py {'userid':{'first_name': '<name>', 'last_name': '<name>', 'email': '<email>', 'extras: {'scout_group': '<scout_group>',}, 'role_discuss': '<bool>', #<etc...>, } """ users = self.api.root.users results = {} #Find the users for userid in security.find_authorized_userids(self.context, (security.VIEW, )): user = users.get(userid, None) if user: results[userid] = dict( first_name=user.get_field_value('first_name', u""), last_name=user.get_field_value('last_name', u""), email=user.get_field_value('email', u""), extras=dict(scout_group=user.get_field_value( 'scout_group', u""), ), #Make sure context is meeting here! roles=self.context.get_groups(userid)) return results
def participants_json_data(self): """ Return a json object with participant data. Will return json with this structure: .. code-block :: py {'userid':{'userinfo': <html structure with firstname, lastname and userid>, 'email': '<email>', 'extras: {'extra_data': '<extra_data>',}, 'role_discuss': '<bool>', #<etc...>, } """ users = self.api.root.users results = {} #Find the users for userid in security.find_authorized_userids(self.context, (security.VIEW, )): user = users.get(userid, None) if user: results[userid] = dict( userinfo=self.api.get_creators_info((userid, ), portrait=False), email=user.get_field_value('email', u""), #Make sure context is meeting here! roles=self.context.get_groups(userid)) return results
def scout_participants_json_data(self): """ Return a json object with participant data. Will return json with this structure: .. code-block :: py {'userid':{'first_name': '<name>', 'last_name': '<name>', 'email': '<email>', 'extras: {'scout_group': '<scout_group>',}, 'role_discuss': '<bool>', #<etc...>, } """ users = self.api.root.users results = {} #Find the users for userid in security.find_authorized_userids(self.context, (security.VIEW,)): user = users.get(userid, None) if user: results[userid] = dict( first_name = user.get_field_value('first_name', u""), last_name = user.get_field_value('last_name', u""), email = user.get_field_value('email', u""), extras = dict(scout_group = user.get_field_value('scout_group', u""),), #Make sure context is meeting here! roles = self.context.get_groups(userid) ) return results
def __call__(self, node, value): #First, check for bad chars, since it requires less CPU html_string_validator(node, value) invalid = set() matched_userids = set() #Note: First match object will be blankspace, second the userid. [ matched_userids.add(x[1]) for x in re.findall(AT_USERID_PATTERN, value) ] if not matched_userids: return #Check that user exists in meeting meeting = find_interface(self.context, IMeeting) valid_userids = find_authorized_userids(meeting, (VIEW, )) for userid in matched_userids: #Check if requested userid has permission in meeting if not userid in valid_userids: invalid.add(userid) if invalid: userids = ", ".join(invalid) raise colander.Invalid( node, _(u"userid_validator_error", default= u"The following userids is invalid: ${userids}. Remember that userids are case sensitive.", mapping={'userids': userids}))
def unread_storage(self): try: return self.context.__unread_storage__ except AttributeError: #This is basically init self.context.__unread_storage__ = OOSet( find_authorized_userids(self.context, (VIEW, ))) return self.context.__unread_storage__
def __call__(self, node, value): if value not in security.find_authorized_userids(self.context, [security.VIEW]): raise colander.Invalid(node, _("${userid} doesn't exist in this meeting.", mapping = {'userid': value})) if security.ROLE_VOTER in self.context.get_groups(value): raise colander.Invalid(node, _("${userid} is already a voter.", mapping = {'userid': value}))
def get_view_meeting_userids(obj, default): """ Userids that are allowed to view a meeting. Only index meeting contexts. """ if not IMeeting.providedBy(obj): return default try: userids = find_authorized_userids(obj, [VIEW]) return userids and userids or default except ComponentLookupError: # pragma : no cover #This is to avoid having security fixture for each catalog test. return default
def get_view_meeting_userids(object, default): """ Userids that are allowed to view a meeting. Only index meeting contexts. """ if not IMeeting.providedBy(object): return default try: userids = find_authorized_userids(object, [VIEW]) return userids and userids or default except ComponentLookupError: # pragma : no cover #This is to avoid having security fixture for each catalog test. return default
def contact(self): """ Contact moderators of the meeting """ recipients = [] for userid in find_role_userids(self.context, ROLE_MODERATOR): user = self.api.get_user(userid) email = user.get_field_value('email') if email: recipients.append(email) if not recipients: for userid in find_authorized_userids(self.context, (MODERATE_MEETING, )): user = self.api.get_user(userid) email = user.get_field_value('email') if email: recipients.append(email) schema = createSchema('ContactSchema').bind(context=self.context, request=self.request, api=self.api) form = Form(schema, buttons=(button_send, )) self.api.register_form_resources(form) post = self.request.POST if self.request.method == 'POST': controls = post.items() try: appstruct = form.validate(controls) except ValidationFailure, e: self.response['form'] = e.render() return self.response if appstruct.get('email', None): sender = appstruct['email'] if self.api.user_profile: sender += " <%s>" % self.api.user_profile.title else: sender = None response = { 'api': self.api, 'meeting': self.context, 'name': appstruct['name'], 'email': appstruct['email'], 'subject': appstruct['subject'], 'message': appstruct['message'], } body_html = render('templates/email/help_contact.pt', response, request=self.request) subject = "[%s] %s" % (self.context.title, appstruct['subject']) send_email(subject, recipients, body_html, sender=sender, request=self.request) self.api.flash_messages.add(_(u"Message sent to the moderators")) url = self.request.resource_url(self.context) return HTTPFound(location=url)
def participants_emails(self): """ List all participants emails in this meeting. """ users = self.request.root.users results = [] for userid in security.find_authorized_userids(self.context, (security.VIEW,)): user = users.get(userid, None) if user: results.append(user) def _sorter(obj): return obj.email return {'users': tuple(sorted(results, key = _sorter)), 'title': _("Participants emails")}
def participants_emails(self): """ List all participants emails in this meeting. """ users = self.api.root.users results = [] for userid in security.find_authorized_userids(self.context, (security.VIEW,)): user = users.get(userid, None) if user: results.append(user) def _sorter(obj): return obj.get_field_value('email') self.response['users'] = tuple(sorted(results, key = _sorter)) self.response['title'] = _(u"Email addresses of participants") return self.response
def participants_emails(self): """ List all participants emails in this meeting. """ users = self.api.root.users results = [] for userid in security.find_authorized_userids(self.context, (security.VIEW,)): user = users.get(userid, None) if user: results.append(user) def _sorter(obj): return obj.get_field_value('email') self.response['users'] = tuple(sorted(results, key = _sorter)) self.response['title'] = _(u"Email addresses of participants") return self.response
def get_recipients(self): recipients = [] for userid in find_role_userids(self.context, ROLE_MODERATOR): user = self.api.get_user(userid) email = user.get_field_value('email') if email: recipients.append(email) if not recipients: for userid in find_authorized_userids(self.context, (MODERATE_MEETING,)): user = self.api.get_user(userid) email = user.get_field_value('email') if email: recipients.append(email) return recipients
def email_voters_about_ongoing_poll(poll, request=None): """ Email voters about that a poll they have voting permission in is open. I.e. in state ongoing. This function is triggered by a workflow subscriber, so not all functionality is nested in the workflow callback. (It would make permission tests very annoying and hard to write otherwise) Note that there's a setting on the meeting called poll_notification_setting that controls wether this should be executed or not. """ meeting = find_interface(poll, IMeeting) assert meeting if not meeting.get_field_value('poll_notification_setting', True): return if request is None: request = get_current_request() userids = security.find_authorized_userids(poll, (security.ADD_VOTE, )) root = find_root(meeting) users = root['users'] email_addresses = set() for userid in userids: #In case user is deleted, they won't have the required permission either #find_authorized_userids loops through the users folder email = users[userid].get_field_value('email') if email: email_addresses.add(email) response = {} response['meeting'] = meeting response['meeting_url'] = resource_url(meeting, request) response['poll_url'] = resource_url(poll, request) sender = "%s <%s>" % (meeting.get_field_value('meeting_mail_name'), meeting.get_field_value('meeting_mail_address')) #FIXME: This should be detatched into a view component body_html = render('../views/templates/email/ongoing_poll_notification.pt', response, request=request) #Since subject won't be part of a renderer, we need to translate it manually #Keep the _ -syntax otherwise Babel/lingua won't pick up the string localizer = get_localizer(request) subject = localizer.translate(_(u"VoteIT: Open poll")) mailer = get_mailer(request) #We need to send individual messages anyway for email in email_addresses: msg = Message(subject=subject, sender=sender, recipients=[ email, ], html=body_html) mailer.send(msg)
def moderators_emails(self): """ List all moderators emails. """ userids = set() for meeting in self.context.get_content(content_type = 'Meeting', states = ('ongoing', 'upcoming')): userids.update(security.find_authorized_userids(meeting, (security.MODERATE_MEETING,))) users = [] for userid in userids: user = self.context.users.get(userid, None) if user: users.append(user) def _sorter(obj): return obj.get_field_value('email') self.response['users'] = tuple(sorted(users, key = _sorter)) self.response['title'] = _(u"Email addresses of moderators with upcoming or ongoing meetings") return self.response
def user_info(self): """ Special view to allow other meeting participants to see information about a user who's in the same meeting as them. Normally called via AJAX and included in a popup or similar, but also a part of the users profile page. Note that a user might have participated within a meeting, and after that lost their permission. This view has to at least display the username of that person. """ info_userid = self.request.GET['userid'] if not info_userid in find_authorized_userids(self.context, (VIEW,)): msg = _(u"userid_not_registered_within_meeting_error", default = u"Couldn't find any user with userid '${info_userid}' within this meeting.", mapping = {'info_userid': info_userid}) return self.api.translate(msg) user = self.api.get_user(info_userid) return self.api.render_view_group(user, self.request, 'user_info', api = self.api)
def statisticts_view(self): """ Show statistics for all users that have view permission in this meeting. This might be a CPU expensive view, so be carefull. """ userids = find_authorized_userids(self.api.meeting, [VIEW]) ctypes = self.request.registry.settings.get('statistics.ctypes', 'Proposal\nDiscussionPost\nVote') ctypes = ctypes.strip().splitlines() results = [] for ctype in ctypes: factory = self.api.get_content_factory(ctype) results.append(dict(stats = self.get_user_stats(userids, ctype), ctype = ctype, display_name = getattr(factory._callable, 'display_name', ctype))) self.response['userids'] = userids self.response['results'] = results return self.response
def __call__(self): """ List all moderators emails. """ #FIXME: This method is way to expensive to use on a site with lots of users. userids = set() for meeting in self.catalog_search(resolve = True, type_name = 'Meeting', workflow_state = ('ongoing', 'upcoming')): userids.update(security.find_authorized_userids(meeting, (security.MODERATE_MEETING,))) users = [] for userid in userids: user = self.context.users.get(userid, None) if user: users.append(user) def _sorter(obj): return obj.email response = {} response['users'] = tuple(sorted(users, key = _sorter)) response['title'] = _(u"Email addresses of moderators with upcoming or ongoing meetings") return response
def email_voters_about_ongoing_poll(poll, request=None): """ Email voters about that a poll they have voting permission in is open. I.e. in state ongoing. This function is triggered by a workflow subscriber, so not all functionality is nested in the workflow callback. (It would make permission tests very annoying and hard to write otherwise) Note that there's a setting on the meeting called poll_notification_setting that controls wether this should be executed or not. """ meeting = find_interface(poll, IMeeting) assert meeting if not meeting.get_field_value('poll_notification_setting', True): return if request is None: request = get_current_request() userids = security.find_authorized_userids(poll, (security.ADD_VOTE,)) root = find_root(meeting) users = root['users'] email_addresses = set() for userid in userids: #In case user is deleted, they won't have the required permission either #find_authorized_userids loops through the users folder email = users[userid].get_field_value('email') if email: email_addresses.add(email) response = {} response['meeting'] = meeting response['meeting_url'] = request.resource_url(meeting) response['poll_url'] = request.resource_url(poll) sender = "%s <%s>" % (meeting.get_field_value('meeting_mail_name'), meeting.get_field_value('meeting_mail_address')) #FIXME: This should be detatched into a view component body_html = render('../views/templates/email/ongoing_poll_notification.pt', response, request=request) #Since subject won't be part of a renderer, we need to translate it manually #Keep the _ -syntax otherwise Babel/lingua won't pick up the string localizer = get_localizer(request) subject = localizer.translate(_(u"VoteIT: Open poll")) mailer = get_mailer(request) #We need to send individual messages anyway for email in email_addresses: msg = Message(subject = subject, sender = sender, recipients=[email,], html=body_html) mailer.send(msg)
def contact(self): """ Contact moderators of the meeting """ recipients = [] for userid in find_role_userids(self.context, ROLE_MODERATOR): user = self.api.get_user(userid) email = user.get_field_value('email') if email: recipients.append(email) if not recipients: for userid in find_authorized_userids(self.context, (MODERATE_MEETING,)): user = self.api.get_user(userid) email = user.get_field_value('email') if email: recipients.append(email) schema = createSchema('ContactSchema').bind(context = self.context, request = self.request, api = self.api) form = Form(schema, buttons=(button_send,)) self.api.register_form_resources(form) post = self.request.POST if self.request.method == 'POST': controls = post.items() try: appstruct = form.validate(controls) except ValidationFailure, e: self.response['form'] = e.render() return self.response if appstruct.get('email', None): sender = appstruct['email'] if self.api.user_profile: sender += " <%s>" % self.api.user_profile.title else: sender = None response = {'api': self.api, 'meeting': self.context, 'name': appstruct['name'], 'email': appstruct['email'], 'subject': appstruct['subject'], 'message': appstruct['message'],} body_html = render('templates/email/help_contact.pt', response, request=self.request) subject = "[%s] %s" % (self.context.title, appstruct['subject']) send_email(subject, recipients, body_html, sender = sender, request = self.request) self.api.flash_messages.add(_(u"Message sent to the moderators")) url = self.request.resource_url(self.context) return HTTPFound(location = url)
def userinfo(self): """ Special view to allow other meeting participants to see information about a user who's in the same meeting as them. Normally called via AJAX and included in a popup or similar, but also a part of the users profile page. Note that a user might have participated within a meeting, and after that lost their permission. This view has to at least display the username of that person. """ try: info_userid = self.request.subpath[0] except IndexError: info_userid = None if not info_userid in security.find_authorized_userids(self.context, (security.VIEW,)): msg = _(u"userid_not_registered_within_meeting_error", default = u"Couldn't find any user with userid '${info_userid}' within this meeting.", mapping = {'info_userid': info_userid}) raise HTTPForbidden( self.request.localizer.translate(msg) ) user = self.request.root['users'].get(info_userid) return {'contents': render_view_group(user, self.request, 'user_info', view = self)}
def __call__(self, node, value): #First, check for bad chars, since it requires less CPU html_string_validator(node, value) invalid = set() matched_userids = set() #Note: First match object will be blankspace, second the userid. [matched_userids.add(x[1]) for x in re.findall(AT_USERID_PATTERN, value)] if not matched_userids: return #Check that user exists in meeting meeting = find_interface(self.context, IMeeting) valid_userids = find_authorized_userids(meeting, (VIEW,)) for userid in matched_userids: #Check if requested userid has permission in meeting if not userid in valid_userids: invalid.add(userid) if invalid: userids = ", ".join(invalid) raise colander.Invalid(node, _(u"userid_validator_error", default=u"The following userids is invalid: ${userids}. Remember that userids are case sensitive.", mapping={'userids': userids}))
def moderators_emails(self): """ List all moderators emails. """ userids = set() for meeting in self.context.get_content(content_type='Meeting', states=('ongoing', 'upcoming')): userids.update( security.find_authorized_userids( meeting, (security.MODERATE_MEETING, ))) users = [] for userid in userids: user = self.context.users.get(userid, None) if user: users.append(user) def _sorter(obj): return obj.get_field_value('email') self.response['users'] = tuple(sorted(users, key=_sorter)) self.response['title'] = _( u"Email addresses of moderators with upcoming or ongoing meetings") return self.response
def user_info(self): """ Special view to allow other meeting participants to see information about a user who's in the same meeting as them. Normally called via AJAX and included in a popup or similar, but also a part of the users profile page. Note that a user might have participated within a meeting, and after that lost their permission. This view has to at least display the username of that person. """ info_userid = self.request.GET['userid'] if not info_userid in find_authorized_userids(self.context, (VIEW, )): msg = _( u"userid_not_registered_within_meeting_error", default= u"Couldn't find any user with userid '${info_userid}' within this meeting.", mapping={'info_userid': info_userid}) return self.api.translate(msg) user = self.api.get_user(info_userid) return self.api.render_view_group(user, self.request, 'user_info', api=self.api)
def poll_listing(context, request, va, **kw): """ This is a view of a poll when it's displayed within an agenda item. It's not the listing for when a user votes. """ api = kw['api'] #The poll query doesn't have to care about path and such since we already have the uids query = Any('uid', context.proposal_uids) get_metadata = api.root.catalog.document_map.get_metadata count, docids = api.root.catalog.query(query, sort_index='created') results = [] for docid in docids: results.append(get_metadata(docid)) response = {} response['proposals'] = tuple(results) response['api'] = api response['poll_plugin'] = context.get_poll_plugin() response['can_vote'] = api.context_has_permission(security.ADD_VOTE, context) response['has_voted'] = api.userid in context response['wf_state'] = wf_state = context.get_workflow_state() response[ 'context'] = context #make sure context within the template is this context and nothing else if wf_state in ('ongoing', 'closed'): response['voted_count'] = len(context.get_voted_userids()) if wf_state == 'ongoing': response['voters_count'] = len( security.find_authorized_userids(context, [security.ADD_VOTE])) else: response['voters_count'] = len(context.voters_mark_closed) try: response['voted_percentage'] = round( 100 * float(response['voted_count']) / float(response['voters_count']), 1) except ZeroDivisionError: response['voted_percentage'] = 0 return render('templates/polls/poll.pt', response, request=request)
def test_find_authorized_userids_admin(self): root = self._fixture() res = security.find_authorized_userids(root, (security.ROLE_ADMIN,)) self.assertEqual(res, set(('admin',)))
def unread_storage(self): try: return self.context.__unread_storage__ except AttributeError: #This is basically init self.context.__unread_storage__ = OOSet( find_authorized_userids(self.context, (VIEW, )) ) return self.context.__unread_storage__
def get_meeting_participants(meeting): """ Return all userids who're part of this meeting. This should be cached later on. """ return security.find_authorized_userids(meeting, [security.VIEW])
def test_find_authorized_userids_admin(self): res = security.find_authorized_userids(self.root, (security.ROLE_ADMIN, )) self.assertEqual(res, set(('admin', )))
def get_meeting_participants(meeting): """ Return all userids who're part of this meeting. This should be cached later on. """ return security.find_authorized_userids(meeting, [security.VIEW])
def test_find_aithorized_userids_several_perms(self): self.root.add_groups('robin', ('role:Admin', )) res = security.find_authorized_userids( self.root, (security.VIEW, security.ROLE_ADMIN)) self.assertEqual(res, set(('admin', 'robin')))
def test_find_aithorized_userids_several_perms(self): root = self._fixture() root.add_groups('robin', ('role:Administrator',)) res = security.find_authorized_userids(root, (security.VIEW, security.ROLE_ADMIN)) self.assertEqual(res, set(('admin', 'robin')))