def __init__(self, context, profile, request): super(BlogAlert, self).__init__(context, profile, request) self._community = find_community(context) blogentry = find_interface(context, IBlogEntry) if blogentry is None: # Comments can also be made against forum topics blogentry = find_interface(context, IForumTopic) self._blogentry = blogentry
def overview(request): site_resource = find_resource(request.context, '/site/b') site_interface = find_interface(request.context, Site) camera = find_interface(request.context, Camera) txt = "{:s}\n{:s}\n{:s}\n{:s}".format(site_resource, site_interface, camera, request.context) response = Response(txt) response.content_type = 'text/plain' return response
def __acl__(self): meeting = find_interface(self, IMeeting) if meeting.get_workflow_state() == 'closed': return ACL['closed'] ai = find_interface(self, IAgendaItem) ai_state = ai.get_workflow_state() #If ai is private, use private if ai_state == 'private': return ACL['private'] return ACL['open']
def __init__(self, context, profile, request): super(CommentAlert, self).__init__(context, profile, request) assert IComment.providedBy(context) self.alert = None if find_interface(self.context, IBlogEntry) or find_interface(context, IForumTopic): # noqa # it is a blog alert self.alert = CommentBlogEntryAlert(self.context, self.profile, self.request) else: if find_interface(self.context, ICommunityFile): self.alert = CommunityFileCommentAlert(self.context, self.profile, self.request)
def __acl__(self): meeting = find_interface(self, IMeeting) acl = get_acl_registry() if meeting.get_workflow_state() == 'closed': return acl.get_acl('DiscussionPost:closed') ai = find_interface(self, IAgendaItem) ai_state = ai.get_workflow_state() #If ai is private, use private if ai_state == 'private': return acl.get_acl('DiscussionPost:private') return acl.get_acl('DiscussionPost:open')
def __init__(self, key=None, parent=None,**kwargs): self.__name__ = key self.__parent__ = parent # Reference request self.request = find_root(self).request # Reference app and site self.__app__ = find_interface(self, i.IApp) self.__site__ = find_interface(self, i.ISite) # Assign kwargs to self (used as self.XXX not self['xxx']) for key in kwargs: setattr(self, key, kwargs[key])
def _close_poll(self): request = self.request m = find_interface(self.poll, IMeeting) m.set_workflow_state(request, 'ongoing') ai = find_interface(self.poll, IAgendaItem) ai.set_workflow_state(request, 'upcoming') ai.set_workflow_state(request, 'ongoing') self.poll.set_workflow_state(request, 'upcoming') self.poll.set_workflow_state(request, 'ongoing') self.poll.set_workflow_state(request, 'closed')
def discussion_answer(self): content_type = 'DiscussionPost' ai = find_interface(self.context, IAgendaItem) add_permission = self.api.content_types_add_perm(content_type) if not has_permission(add_permission, ai, self.request): raise HTTPForbidden("You're not allowed to add '%s' in this context." % content_type) schema_name = self.api.get_schema_name(content_type, 'add') schema = createSchema(schema_name).bind(context = self.context, request = self.request, api = self.api) url = self.request.resource_url(self.context, 'answer') form = Form(schema, action=url, buttons=(button_add,), formid="answer-form-%s" % self.context.uid, use_ajax=False, ajax_options=ajax_options) self.api.register_form_resources(form) self.response['user_image_tag'] = self.api.user_profile.get_image_tag(request = self.request) self.response['content_type'] = content_type post = self.request.POST if 'add' in post: controls = post.items() try: #appstruct is deforms convention. It will be the submitted data in a dict. appstruct = form.validate(controls) except ValidationFailure, e: self.response['form'] = e.render() if self.request.is_xhr: return Response(render("templates/ajax_edit.pt", self.response, request = self.request)) return self.response kwargs = {} kwargs['text'] = appstruct['text'] if self.api.userid: kwargs['creators'] = [self.api.userid] ai = find_interface(self.context, IAgendaItem) obj = createContent(content_type, **kwargs) name = generate_slug(ai, obj.title) ai[name] = obj #Success, redirect url = self.request.resource_url(ai, anchor=obj.uid) if self.request.is_xhr: return Response(headers = [('X-Relocate', url)]) return HTTPFound(location=url)
def feed_discussion_post_added(obj, event): """ Will add a feed entry when a discussion post is added if agenda item is not private. """ request = get_current_request() userid = authenticated_userid(request) agenda_item = find_interface(obj, IAgendaItem) if agenda_item.get_workflow_state() == "private": return msg = _( u"${userid} has written a post in ${agenda_item}.", mapping={"userid": userid, "agenda_item": agenda_item.title} ) meeting = find_interface(obj, IMeeting) feed_handler = request.registry.getAdapter(meeting, IFeedHandler) feed_handler.add(obj.uid, msg, tags=("discussion_post", "added"))
def notify_subscribing_users(context, event): """ Send an email to any user subscribing to this folder. """ request = get_current_request() comments = find_interface(context, ICommentsFolder) subject = _("Notification") comments_context = comments.__parent__ for userid in comments.get_subscribers(): if userid == request.authenticated_userid: continue try: user = request.root['users'][userid] except KeyError: continue if not user.email: continue try: comment_user = request.root['users'][context.creator[0]] except (KeyError, IndexError): comment_user = None values = dict( user=user, body=context.body, comment_context=comments_context, comment_user=comment_user, unsubscribe_url=comments.unsubscribe_url(request, userid), ) body = render('arche_comments:templates/notification_email.pt', values, request=request) request.send_email(subject, [user.email], body)
def notify_policycompass(event): """Push comments of IExternalResource ressources to elastic search.""" comment = event.object external_resource = find_interface(comment, IExternalResource) if external_resource is None: return resource_name = get_sheet_field(external_resource, IName, 'name') match = re.match( '(?P<type>visualization|event|dataset|metric|model|indicator)' '_(?P<id>[0-9]+)', resource_name) # this is not a known policycompass external resource if match is None: return resource_type = match.group('type') resource_id = match.group('id') settings = event.registry.settings pcompass_endpoint = settings.get('adhocracy_pcompass.pcompass_endpoint', 'http://localhost:8000') url = '{base}/api/v1/searchmanager/updateindexitem/{res_type}/{res_id}' \ .format(base=pcompass_endpoint, res_type=resource_type, res_id=resource_id) r = requests.post(url) if r.status_code != 200: # indexing error on pcompass msg = 'Notifying policy compass about "{}_{}" failed with "{}"'.format( resource_type, resource_type, r.text) raise ValueError(msg)
def evolve(root): print "initial reindex of catalog to make sure everything is up to date" clear_and_reindex(root) registry = get_current_registry() print "extracting the last aid from poroposals" catalog = root.catalog result = catalog.search(content_type="Proposal")[1] for docid in result: print "--------------------------------------------------" proposal = resolve_catalog_docid(catalog, root, docid) meeting = find_interface(proposal, IMeeting) proposal_ids = registry.queryAdapter(meeting, IProposalIds) print "extracting from proposal %s" % proposal.__name__ # get aid from propsoal aid_int = proposal.get_field_value('aid_int') print "proposal aid %s" % aid_int # get the aid for the creator currently saved in the meeting creators = proposal.get_field_value('creators') current_aid = proposal_ids.get(creators[0]) print "current aid for creator %s" % current_aid # if current aid is empty or the aid from the proposal is # greater then the current one, save it in the meeting if not current_aid or aid_int > current_aid: proposal_ids.add(creators[0], aid_int)
def add_to_repo(obj, event): """ Add a newly created object to the version repository. Intended use is as an IObjectAddedEvent subscriber. """ if find_interface(obj, IIntranets): # Exclude /offices from repo return repo = find_repo(obj) if repo is None: return if not repo.history(obj.docid, True): # It is not in the repo, so add it adapter = queryAdapter(obj, IObjectVersion) if adapter is not None: if adapter.comment is None: adapter.comment = 'Content created.' repo.archive(adapter) container = event.parent adapter = queryAdapter(container, IContainerVersion) if adapter is not None: request = get_current_request() user = authenticated_userid(request) repo.archive_container(adapter, user) # Recurse into children if adding a subtree if IFolder.providedBy(obj): for name, child in obj.items(): fake_event = FakeEvent() fake_event.parent = obj add_to_repo(child, fake_event)
def manage_questions(self): manage_questions.need() post = self.request.POST if 'cancel' in self.request.POST: url = self.request.resource_url(self.context) return HTTPFound(location = url) if 'save' in post: self.process_question_ids(self.context) self.add_flash_message(_('Updated')) self.response['organisation'] = org = find_interface(self.context, IOrganisation) picked_questions = set() survey_sections = [] for section in self.context.values(): if not ISurveySection.providedBy(section): continue picked_questions.update(section.question_ids) survey_sections.append(section) self.response['survey_sections'] = survey_sections if not survey_sections: msg = _(u"no_sections_added_notice", default = u"You need to add survey sections and then use this view to manage the questions.") self.add_flash_message(msg) #Load all question objects that haven't been picked questions = org.questions self.response['available_questions'] = [questions[x] for x in questions if x not in picked_questions] return self.response
def discussion_redirect_to_agenda_item(context, request): root = find_root(context) ai = find_interface(context, IAgendaItem) if ai: path = resource_path(ai) query = dict(path = path, content_type='DiscussionPost', sort_index='created', reverse=True, limit=5, #FIXME: this should be globaly configurable? ) docids = root.catalog.search(**query)[1] # set to True if requested post is after the display limit after_limit = False get_metadata = root.catalog.document_map.get_metadata for docid in docids: brain = get_metadata(docid) if brain['uid'] == context.uid: after_limit = True break # post was not found among the displayed posts query = request.GET if not after_limit: query['discussions'] = 'all' url = request.resource_url(ai, query=query, anchor=context.uid) else: url = request.resource_url(ai, query=query, anchor=context.uid) return HTTPFound(location=url) raise NotFound("Couldn't locate Agenda Item from this context.")
def __acl__(self): poll = find_interface(self, IPoll) state = poll.get_workflow_state() acl = get_acl_registry() if state == 'ongoing': return acl.get_acl('Vote:ongoing') return acl.get_acl('Vote:closed')
def index_workflow_state_of_item(resource, default) -> [str]: """Find item and return it`s value for the workflow_state index.""" item = find_interface(resource, IItem) if item: return index_workflow_state(item, default) else: return default
def get_pastes(context, request, max): pastebin = find_interface(context, IPasteBin) pastes = [] app_url = request.application_url keys = list(pastebin.keys()) def byint(a, b): try: return cmp(int(a), int(b)) except TypeError: return cmp(a, b) keys.sort(byint) keys.reverse() keys = keys[:max] for name in keys: entry = pastebin[name] if entry.date is not None: pdate = entry.date.strftime('%x at %X') else: pdate = 'UNKNOWN' paste_url = urlparse.urljoin(app_url, name) new = { 'author': entry.author_name, 'date': pdate, 'url': paste_url, 'name': name } pastes.append(new) return pastes
def get_proposal_objects(self): """ Return proposal objects relevant to this poll. Will sort them in specified order. """ agenda_item = self.__parent__ if agenda_item is None: raise ValueError("Can't find any agenda item in the polls lineage") query = Any('uid', tuple(self.proposal_uids)) & Eq('type_name', 'Proposal') root = find_root(agenda_item) results = [] for docid in root.catalog.query(query)[1]: path = root.document_map.address_for_docid(docid) obj = find_resource(root, path) # Permission check shouldn't be needed at this point if obj: results.append(obj) if self.proposal_order: proposal_order = self.proposal_order else: meeting = find_interface(self, IMeeting) # During tests, we might not have a real meeting here :) proposal_order = getattr(meeting, 'poll_proposals_default_order', '') key_method = PROPOSAL_ORDER_KEY_METHODS.get( proposal_order, PROPOSAL_ORDER_KEY_METHODS[PROPOSAL_ORDER_DEFAULT] ) return sorted(results, key=key_method)
def intranet_layout(self): layout = get_renderer('karl.content.views:templates/intranet_layout.pt' ).implementation() intranet = find_interface(self.context, IIntranet) if intranet: layout.navigation = intranet.navigation return layout
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 proposal_redirect_to_agenda_item(context, request): ai = find_interface(context, IAgendaItem) if ai: query = request.GET url = request.resource_url(ai, query=query, anchor=context.uid) return HTTPFound(location=url) raise NotFound("Couldn't locate Agenda Item from this context.")
def recent_items(self): if self._recent_items is None: community = find_interface(self.context, ICommunity) if community is not None: stmt = """SELECT docid from pgtextindex WHERE community_docid='%s' AND content_type not in ('IInvitation', 'ICalendar', 'ICalendarLayer', 'ICalendarCategory', 'IBlog', 'ICommunityRootFolder', 'IWiki') ORDER BY modification_date DESC LIMIT 20""" catalog = find_catalog(self.context) index = catalog['texts'] docids = index.get_sql_catalog_results(stmt % community.docid) self._recent_items = [] for docid in docids: path = catalog.document_map.address_for_docid(docid[0]) try: model = find_resource(self.context, path) except (KeyError, TypeError): continue if not has_permission('view', model, self.request): continue try: adapted = getMultiAdapter((model, self.request), IGridEntryInfo) except ComponentLookupError: continue self._recent_items.append(adapted) return self._recent_items
def member_search_json_view(context, request): try: # Query parameter shall be 'term'. prefix = request.params['term'] except UnicodeDecodeError: # not utf8, just return empty list since tags can't have these chars return [] # case insensitive prefix = prefix.lower() community = find_interface(context, ICommunity) member_names = community.member_names moderator_names = community.moderator_names community_member_names = member_names.union(moderator_names) query = dict( member_name='%s*' % prefix, sort_index='title', limit=20, ) searcher = ICatalogSearch(context) try: total, docids, resolver = searcher(**query) profiles = filter(None, map(resolver, docids)) records = [dict( value = profile.__name__, label = profile.title, ) for profile in profiles if profile.__name__ not in community_member_names and profile.security_state != 'inactive'] except ParseError: records = [] return records
def claim_ticket(ticket, request, user_identifier): #Is the ticket open? if ticket.get_workflow_state() != 'open': raise HTTPForbidden("Access already granted with this ticket") #Find required resources and do some basic validation meeting = find_interface(ticket, IMeeting) root = find_root(ticket) assert meeting assert root if '@' in user_identifier: user = root['users'].get_user_by_email(user_identifier, None) else: user = root['users'].get(user_identifier, None) if user is None: raise HTTPForbidden("No user could be looked up via: %r" % user_identifier) meeting.add_groups(user.userid, ticket.roles) ticket.claimed_by = user.userid ticket.set_workflow_state(request, 'closed') ticket.closed = utcnow() #If ticket and user profile has the same email, consider that email validated #This will notify and perhaps fetch other tickets as well if user.email == ticket.email: user.email_validated = True return user
def get_info(self, request): """Generate a sequence for the letter box, highlighting current""" # Get the letterbox data. If the use has clicked on a letter, get # it from the URL and pass it into the function to get the data # for the letterbox macro, so we don't underline the current # letter. storage = find_interface(self.context, self.iface) current = request.params.get("titlestartswith", None) fmt = request.path_url + "?titlestartswith=%s" letters = [] for letter in string.uppercase: if getattr(storage, "alpha", None) and storage.alpha.get(letter): href = fmt % letter else: href = None if letter == current: css_class = "current" else: css_class = "notcurrent" letters.append({"name": letter, "href": href, "css_class": css_class, "is_current": letter == current}) letters.append( { "name": "Any", "href": current is not None and request.path_url or None, "css_class": current is None and "current" or "notcurrent", "is_current": current is None, } ) return letters
def community_info(self): if self._community_info is None: community = find_interface(self.context, ICommunity) if community is not None: self._community_info = getMultiAdapter( (community, self.request), ICommunityInfo) return self._community_info
def object_removed(obj, event): """ Remove an index for a base content object. Also, remove all contained.""" root = find_interface(obj, ISiteRoot) for child in find_all_base_content(obj): unindex_object(root.catalog, child) unindex_object(root.catalog, obj) _update_if_ai_parent(root.catalog, obj)
def jquery_member_search_view(context, request): prefix = request.params['val'].lower() community = find_interface(context, ICommunity) member_names = community.member_names moderator_names = community.moderator_names community_member_names = member_names.union(moderator_names) query = dict( member_name='%s*' % prefix, sort_index='title', limit=20, ) searcher = ICatalogSearch(context) try: total, docids, resolver = searcher(**query) profiles = filter(None, map(resolver, docids)) records = [dict( id = profile.__name__, text = profile.title, ) for profile in profiles if profile.__name__ not in community_member_names and profile.security_state != 'inactive'] except ParseError: records = [] result = JSONEncoder().encode(records) return Response(result, content_type="application/x-json")
def index_item_badge(resource, default) -> [str]: """Find item and return its badge names for the item_badge index.""" item = find_interface(resource, IItem) if item is None: return default badge_names = index_badge(item, default) return badge_names
def invite_ticket(context, request, va, **kw): """ Render invite ticket email html. Uses ticket as a context. Requires message to be passed as a keyword when using view_action """ #FIXME: Include meeting logo in mail? roles = dict(MEETING_ROLES) meeting = find_interface(context, IMeeting) root = find_root(meeting) assert meeting response = {} response['access_link'] = request.resource_url(meeting, 'ticket', query={ 'email': context.email, 'token': context.token }) response['message'] = kw['message'] response['meeting'] = meeting response['contact_mail'] = meeting.get_field_value('meeting_mail_address') response['sender_profile'] = root.users.get(context.sent_by) response['roles'] = [roles.get(x) for x in context.roles] return render('templates/email/invite_ticket_email.pt', response, request=request)
def get_navigation(context, request, links): items = [] for link in links: state = 'notcurrent' view_iface = link['view_iface'] nav_ifaces = link['nav_ifaces'] view_name = link['view_name'] if view_iface.providedBy(context): if request.view_name == view_name: state = 'current' else: for nav_iface in nav_ifaces: if nav_iface.providedBy(context): state = 'current' break viewcontext = find_interface(context, view_iface) if viewcontext is not None: items.append( {'state':state, 'href':resource_url(viewcontext, request, view_name), 'title':link['title'], }) return items
def allow_editing(self): user = find_interface(self.context, User) if user is not None \ and authenticated_userid(self.request) == user.name: return True else: return False
def __init__(self, request, parent, user_id): self.__parent__ = parent try: user_id = int(user_id) property_resource = find_interface(self, PropertyResource) if property_resource is None: raise KeyError(user_id) except ValueError: raise KeyError(user_id) q = DBSession.query(Review.user_id) q = q.filter( Review.property_id == property_resource.property_id, Review.user_id == user_id, ) exists = DBSession.query(q.exists()) if not exists: raise KeyError(user_id) self.property_id = property_resource.property_id self.user_id = user_id
def get_info(self, request): """Generate a sequence for the letter box, highlighting current""" # Get the letterbox data. If the use has clicked on a letter, get # it from the URL and pass it into the function to get the data # for the letterbox macro, so we don't underline the current # letter. storage = find_interface(self.context, self.iface) current = request.params.get('titlestartswith', None) fmt = request.path_url + "?titlestartswith=%s" letters = [] for letter in string.uppercase: if getattr(storage, 'alpha', None) and storage.alpha.get(letter): href = fmt % letter else: href = None if letter == current: css_class = 'current' else: css_class = 'notcurrent' letters.append({'name': letter, 'href': href, 'css_class': css_class, 'is_current': letter == current, }) letters.append({'name': 'Any', 'href': current is not None and request.path_url or None, 'css_class': current is None and 'current' or 'notcurrent', 'is_current': current is None, }) return letters
def at_userid_link(text, obj, request=None): """ Transform @userid to a link. """ users = find_root(obj).users meeting = find_interface(obj, IMeeting) assert meeting if not request: request = get_current_request() def handle_match(matchobj): # The pattern contains a space so we only find usernames that # has a whitespace in front, we save the spaced so we can but # it back after the transformation space, userid = matchobj.group(1, 2) #Force lowercase userid userid = userid.lower() if userid in users: user = users[userid] tag = {} tag['href'] = request.resource_url(meeting, '_userinfo', query={'userid': userid}).replace(request.application_url, '') tag['title'] = user.title tag['class'] = "inlineinfo" return space + HTML.a('@%s' % userid, **tag) else: return space + '@' + userid return re.sub(AT_PATTERN, handle_match, text)
def discussion_redirect_to_agenda_item(context, request): root = find_root(context) ai = find_interface(context, IAgendaItem) if ai: path = resource_path(ai) query = dict( path=path, content_type='DiscussionPost', sort_index='created', reverse=True, limit=5, #FIXME: this should be globaly configurable? ) docids = root.catalog.search(**query)[1] # set to True if requested post is after the display limit after_limit = False get_metadata = root.catalog.document_map.get_metadata for docid in docids: brain = get_metadata(docid) if brain['uid'] == context.uid: after_limit = True break # post was not found among the displayed posts query = request.GET if not after_limit: query['discussions'] = 'all' url = request.resource_url(ai, query=query, anchor=context.uid) else: url = request.resource_url(ai, query=query, anchor=context.uid) return HTTPFound(location=url) raise NotFound("Couldn't locate Agenda Item from this context.")
def render_invite_ticket(ticket, request, message="", **kw): """ Render invite ticket email html. Uses ticket as a context. """ assert IInviteTicket.providedBy(ticket) #FIXME: Include meeting logo in mail? roles = dict(security.MEETING_ROLES) meeting = find_interface(ticket, IMeeting) root = find_root(meeting) assert IMeeting.providedBy(meeting) response = { 'access_link': request.resource_url(meeting, 'ticket', query={ 'email': ticket.email, 'token': ticket.token }), 'message': message, 'meeting': meeting, 'context': ticket, 'contact_mail': meeting.get_field_value('meeting_mail_address'), 'sender_profile': root.users.get(ticket.sent_by), 'roles': [roles.get(x) for x in ticket.roles] } response['invite_common'] = render_invite_common(response, request) return render('voteit.core:templates/email/invite_ticket_email.pt', response, request=request)
def _is_proposal_creation_finished(proposal_version): proposal_item = find_interface(proposal_version, IProposal) versions_with_data = [ x for x in proposal_item.values() if IProposalVersion.providedBy(x) and has_annotation_sheet_data(x) ] return len(versions_with_data) == 1
def __init__(self, context, request): self.context = context self.request = request self.community = find_interface(context, ICommunity) self.profiles = find_profiles(context) self.api = TemplateAPI(context, request) self.filestore = get_filestore(context, request, 'accept-invitation')
def course_module(self): if self.request.has_permission('perm:Edit', self.context): jqueryui.need() touchpunch_js.need() response = {} response['course'] = find_interface(self.context, ICourse) response['course_modules'] = response['course'].items() response['in_course'] = self.fikaProfile.in_course(response['course']) response['course_module_toggle'] = self._render_course_module_toggle response['course_pagination'] = render_course_pagination response['module_segments'] = self.context.values() response['is_assessment'] = {} for segment in self.context.values(): response['is_assessment'][segment.__name__] = isinstance(segment, Assessment) if isinstance(segment, ImageSlideshow): lightbox_js.need() lightbox_css.need() break for segmentcontent in segment.values(): if isinstance(segmentcontent, ImageSlideshow): lightbox_js.need() lightbox_css.need() break response['addable_types'] = {} factories = get_content_factories(self.request.registry) for (obj, addable) in get_addable_content(self.request.registry).items(): if 'Segment' in addable: factory = factories.get(obj, None) response['addable_types'][obj] = getattr(factory, 'icon', 'file') return response
def intranet_layout(self): layout = get_renderer( 'karl.content.views:templates/intranet_layout.pt').implementation() intranet = find_interface(self.context, IIntranet) if intranet: layout.navigation = intranet.navigation return layout
def survey_dt(self): survey = find_interface(self.context, ISurvey) if not survey: return tz = survey.get_time_zone() loc = get_locale_name(self.request) return createObject('dt_helper', tz, loc)
def send(self, request, message = u""): if self.closed: #Just as a precaution return meeting = find_interface(self, IMeeting) html = render_view_action(self, request, 'email', 'invite_ticket', message = message) subject = _(u"Invitation to ${meeting_title}", mapping = {'meeting_title': meeting.title}) if send_email(subject = subject, recipients = self.email, html = html, request = request, send_immediately = True): self.sent_dates.append(utcnow())
def remove_contained_cards_relations(event): """ If a collection is removed, cleanup all relevant relations to/from cards that will be removed. """ resource = event.context wall = find_interface(resource, IWall) for rid in event.contained_rids: for relation_id in wall.relations_map.find_relations(rid): del wall.relations_map[relation_id]
def user_tag_i_support(brain, request, va, **kw): """ Special view action for user tag 'support'. It requires catalog metadata + expects a brain as context, rather than a full object. """ api = kw['api'] obj = find_resource(api.root, brain['path']) # Only available on proposals if not obj.content_type == 'Proposal': return "" # only show form if users has the vote role show_form = False meeting = find_interface(obj, IMeeting) if ROLE_VOTER in meeting.get_groups(api.userid): show_form = True user_tags = request.registry.getAdapter(obj, IUserTags) userids = user_tags.userids_for_tag('support') #Note: It's not possible to have nested translation strings. So we do the translation here in advance. display_name = api.translate(_(u"Support")) expl_display_name = _(u"Support this") brain_url = "%s%s" % (request.application_url, brain['path']) response = dict( context_id=brain['uid'], toggle_url="%s/_support" % brain_url, tag='support', display_name=display_name, get_userinfo_url=api.get_userinfo_url, expl_display_name=expl_display_name, ) if api.userid and api.userid in userids: #Current user likes the current context response['button_label'] = _(u"Remove ${display_name}", mapping={'display_name': display_name}) response['selected'] = True response['do'] = "0" userids = list(userids) userids.remove(api.userid) else: #Current user hasn't selected the current context response['button_label'] = display_name response['selected'] = False response['do'] = "1" response['userids'] = userids response['has_entries'] = bool(response['selected'] or userids) response[ 'tagging_users_url'] = " %s/_tagging_users?tag=%s&display_name=%s&expl_display_name=%s" % ( brain_url, 'support', display_name, expl_display_name) response['show_form'] = show_form return render('voteit.core.views:templates/snippets/user_tag.pt', response, request=request)
def get_proposal_objects(self): agenda_item = find_interface(self, IAgendaItem) if agenda_item is None: raise ValueError("Can't find any agenda item in the polls lineage") proposals = set() for item in agenda_item.values(): if item.uid in self.proposal_uids: proposals.add(item) return proposals
def __acl__(self): #If ai is private, use private ai = find_interface(self, IAgendaItem) ai_state = ai.get_workflow_state() if ai_state == 'private': return ACL['private'] state = self.get_workflow_state() #As default - don't traverse to parent return ACL.get(state, ACL['closed'])
def index_tag(resource, default) -> [str]: """Return value for the tag index.""" item = find_interface(resource, IItem) if item is None: # ease testing return registry = get_current_registry(resource) tags_sheet = registry.content.get_sheet(item, ITags) tagnames = [f for f, v in tags_sheet.get().items() if v is resource] return tagnames if tagnames else default
def index_workflow_state_of_item(resource, default) -> [str]: """Find item and return it`s value for the workflow_state index.""" item = find_interface(resource, IItem) try: state = get_sheet_field(item, IWorkflowAssignment, 'workflow_state') except (RuntimeConfigurationError, AttributeError): return default else: return state
def get_context_vas(self, context, request): for va in self.values(): if va.interface and not va.interface.providedBy(context): continue if va.permission and not self.perm_checker(va.permission, context, request): continue if va.containment and not find_interface(context, va.containment): continue yield va
def block_starting_polls_with_multivotes_open(context, event): if event.new_state == "ongoing": meeting = find_interface(context, IMeeting) if MEETING_NAMESPACE in meeting: mv = meeting[MEETING_NAMESPACE] if mv.wf_state == "open": raise HTTPForbidden( _("You may not start polls unless you've locked the assignment of votes. See multivotes." ))
def create_proposal_id(obj, event): """ Call an IProposalIds adapter if it exists. See IProposalIds for implementation. """ reg = get_current_registry() meeting = find_interface(obj, IMeeting) proposal_ids = reg.queryAdapter(meeting, IProposalIds) if proposal_ids: proposal_ids.add(obj)