def isReport(self, name): """ See IMailinDispatcher. """ root = find_root(self.context) if name in root.list_aliases: return True pd = find_peopledirectory(self.context) tokens = name.split('+') try: find_model(pd, tokens) except KeyError: return False return True
def user_tagged_content(event): if ITagAddedEvent.providedBy(event): request = get_current_request() context = getattr(request, 'context', None) if context is None: return events = find_events(context) if not events: return site = find_site(context) catalog = find_catalog(context) path = catalog.document_map.address_for_docid(event.item) tagged = find_model(site, path) if tagged is None: return profile_id = event.user if profile_id in (None, 'None'): return profile = site['profiles'][profile_id] info = _getInfo(profile, tagged) if info is None: return if info['content_type'] == 'Community': info['flavor'] = 'tagged_community' elif info['content_type'] == 'Profile': info['flavor'] = 'tagged_profile' else: info['flavor'] = 'tagged_other' info['operation'] = 'tagged' info['tagname'] = event.name events.push(**info)
def createContent(self, name, content_type, obj_location, REQUEST, **kwargs): """ """ if isinstance(content_type, basestring): klass = self.get_model(content_type) else: klass = content_type if type(obj_location) == str: obj_location = find_model(self, obj_location) newobj = klass(name=name) newobj.put() # Hook content up to traveral machinery locations etc.. before # applying all the data if IContentish.providedBy(newobj): if obj_location: obj_location.addContent(newobj, name, REQUEST) zope.event.notify(zope.lifecycleevent.ObjectCreatedEvent(self)) self.setcached(str(obj_location.getPath()), None) elif isinstance(newobj, NonContentishMixin): newobj.__parent__ = obj_location newobj.applyChanges(kwargs) newobj.put() return newobj
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'
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)
def __call__(self, v): if not v: return site = find_site(self.context) try: target = find_model(site, v) except KeyError, e: raise Invalid("Path not found: %s" % v)
def move_content_view(context, request): """ Move content from one community to another. Only blog entries supported for now. May or may not eventually expand to other content types. """ api = AdminTemplateAPI(context, request, 'Admin UI: Move Content') filtered_content = [] if 'filter_content' in request.params: # We're limiting ourselves to content that always lives in the same # place in each community, ie /blog, /calendar, /wiki, etc, so that # we can be pretty sure we can figure out where inside the destination # community we should move it to. filtered_content = _get_filtered_content( context, request, [IBlogEntry, IWikiPage, ICalendarEvent]) if not filtered_content: api.error_message = 'No content matches your query.' if 'move_content' in request.params: to_community = request.params.get('to_community', '') if not to_community: api.error_message = 'Please specify destination community.' else: try: paths = request.params.getall('selected_content') dst_community = find_model(context, to_community) for path in paths: obj = find_model(context, path) dst_container = _find_dst_container(obj, dst_community) name = make_unique_name(dst_container, obj.__name__) del obj.__parent__[obj.__name__] dst_container[name] = obj if len(paths) == 1: status_message = 'Moved one content item.' else: status_message = 'Moved %d content items.' % len(paths) redirect_to = model_url( context, request, request.view_name, query=dict(status_message=status_message) ) return HTTPFound(location=redirect_to) except _DstNotFound, error: api.error_message = str(error)
def resolver(docid): path = address(docid) if path is None: return None try: return find_model(self.context, path) except KeyError: logger and logger.warn('Model missing: %s' % path) return None
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)
def __call__(self, docid): site = self.context.site catalog = find_catalog(site) if catalog is None: raise ValueError('No catalog') path = catalog.document_map.address_for_docid(docid) if path is None: raise KeyError(docid) doc = find_model(site, path) community = find_community(doc) return community and community.__name__ or None
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)
def _get_portlet_html(context, request, portlet_ids): missing = '<div class="sections"><p>Missing portlet at %s</p></div>' html = '' for portlet_id in portlet_ids: try: model = find_model(context, portlet_id) except KeyError: html += missing % portlet_id continue portlet_info = getMultiAdapter((model, request), IIntranetPortlet) html += portlet_info.asHTML return html
def _get_calendar_layers(context): layers = [ x for x in context.values() if ICalendarLayer.providedBy(x) ] for layer in layers: layer._v_categories = [] for path in layer.paths: category = {} try: calendar = find_model(context, path) title = _calendar_category_title(calendar) category['title'] = title layer._v_categories.append(category) except KeyError: continue return layers
def prune_catalog(root, out=None): """ Under some circumstances (an error of some sort) we can wind up with documents in the catalog that no longer exist in real life. This prunes the catalog of dead records. """ catalog = find_catalog(root) for path, docid in list(catalog.document_map.address_to_docid.items()): try: model = find_model(root, path) except KeyError: if out is not None: print >>out, "Removing dead catalog record: %s" % path catalog.unindex_doc(docid) catalog.document_map.remove_docid(docid)
def evolve(site): """ Add the new containment index to the catalog. """ catalog = find_catalog(site) if 'containment' in catalog: print 'Nothing to do.' return index = CatalogKeywordIndex(get_containment) catalog['containment'] = index for docid, address in catalog.document_map.docid_to_address.items(): print 'Indexing containment: %s' % address model = find_model(site, address) index.index_doc(docid, model) model._p_deactivate()
def validate_python(self, value, state): super(HomePath, self).validate_python(value, state) context = getattr(state, "context", None) if value and context: site = find_site(context) try: target = find_model(site, value) except KeyError, e: raise Invalid( "Path not found: %s" % value, value, state) else: if target is site: raise Invalid( "Home path must not point to the site root", value, state)
def _get_portlet_html(context, request, portlet_ids): missing = '<div class="generic-portlet"><p>Missing portlet at %s</p></div>' notaportlet = '<div class="sections"><p>%s is not a portlet</p></div>' html = "" for portlet_id in portlet_ids: try: model = find_model(context, portlet_id) except KeyError: html += missing % portlet_id continue try: portlet_info = getMultiAdapter((model, request), IIntranetPortlet) except ComponentLookupError: html += notaportlet % portlet_id continue html += portlet_info.asHTML return html
def evolve(root): """ We've added a modified_by index to the catalog to support renaming of users and reassignment of content from one user to another. Without the index we'd have to walk the entire content tree in order to update modified_by attributes on documents. """ print "Adding the 'modified_by' index to the catalog." root.update_indexes() catalog = find_catalog(root) index = catalog["modified_by"] entries = list(catalog.document_map.docid_to_address.items()) n_docs = len(entries) for n, (docid, addr) in enumerate(entries): if n % 500 == 0: print "Indexed %d/%d documents" % (n, n_docs) doc = find_model(root, addr) index.index_doc(docid, doc) doc._p_deactivate()
def evolve(context): catalog = find_catalog(context) index = catalog['texts'] for docid in index.index._docweight.keys(): try: path = catalog.document_map.address_for_docid(docid) context = find_model(context, path) if (ICalendarLayer.providedBy(context) or ICalendarCategory.providedBy(context) or not IContent.providedBy(context)): index.unindex_doc(docid) if hasattr(context, '_p_deactivate'): context._p_deactivate() except KeyError: # Work around some bad data in the db--some calendar categories # got added with '/' characters in their ids. Skip them for now # until we can figure out what to do with them. print "Bad path in catalog: ", path
def community_tag_users_view(context, request): page_title = 'Tag Users' api = request.api api.page_title = page_title tag = request.params.get('tag', None) docid = request.params.get('docid', None) # Test for some cases if tag is None: return HTTPBadRequest('Missing parameter for tag') if docid is None: return HTTPBadRequest('Missing parameter for docid') docid = int(docid) tags = find_tags(context) profiles = find_profiles(context) catalog = find_catalog(context) address = catalog.document_map.address_for_docid(docid) target = find_model(context, address) if tags is not None and profiles is not None: users = [] for userid in tags.getUsers(tags=[tag], items=[docid], community=context.__name__): profile = profiles[userid] fullname = profile.firstname + ' ' + profile.lastname also = [x for x in tags.getTags(items=[docid], users=[userid], community=context.__name__) if x != tag] users.append({'login': userid, 'fullname': fullname, 'also': also, }) else: users = () return dict( api=api, tag=tag, url=model_url(target, request), title=target.title, users=users, )
def delete_content_view(context, request): api = AdminTemplateAPI(context, request, 'Admin UI: Delete Content') filtered_content = [] if 'filter_content' in request.params: filtered_content = _get_filtered_content(context, request) if not filtered_content: api.status_message = 'No content matches your query.' if 'delete_content' in request.params: paths = request.params.getall('selected_content') if paths: for path in paths: try: content = find_model(context, path) del content.__parent__[content.__name__] except KeyError: # Thrown by find_model if we've already deleted an # ancestor of this node. Can safely ignore becuase child # node has been deleted along with ancestor. pass if len(paths) == 1: status_message = 'Deleted one content item.' else: status_message = 'Deleted %d content items.' % len(paths) redirect_to = model_url( context, request, request.view_name, query=dict(status_message=status_message) ) return HTTPFound(location=redirect_to) parms = dict( api=api, menu=_menu_macro(), content_select_widget=_content_selection_widget(), content_select_grid=_content_selection_grid(), filtered_content=filtered_content, ) parms.update(_populate_content_selection_widget(context, request)) return parms
def reindex_catalog(context, path_re=None, commit_interval=200, dry_run=False, output=None, transaction=transaction, indexes=None): def commit_or_abort(): if dry_run: output and output('*** aborting ***') transaction.abort() else: output and output('*** committing ***') transaction.commit() site = find_site(context) catalog = site.catalog output and output('updating indexes') site.update_indexes() commit_or_abort() if indexes is not None: output and output('reindexing only indexes %s' % str(indexes)) i = 1 for path, docid in catalog.document_map.address_to_docid.items(): if path_re is not None and path_re.match(path) is None: continue output and output('reindexing %s' % path) try: model = find_model(context, path) except KeyError: output and output('error: %s not found' % path) continue if indexes is None: catalog.reindex_doc(docid, model) else: for index in indexes: catalog[index].reindex_doc(docid, model) if i % commit_interval == 0: commit_or_abort() i+=1 commit_or_abort()
def delete_content_view(context, request): api = AdminTemplateAPI(context, request, 'Admin UI: Delete Content') filtered_content = [] if 'filter_content' in request.params: filtered_content = _get_filtered_content(context, request) if not filtered_content: api.status_message = 'No content matches your query.' if 'delete_content' in request.params: paths = request.params.getall('selected_content') if paths: for path in paths: content = find_model(context, path) del content.__parent__[content.__name__] if len(paths) == 1: status_message = 'Deleted one content item.' else: status_message = 'Deleted %d content items.' % len(paths) redirect_to = model_url( context, request, request.view_name, query=dict(status_message=status_message) ) return HTTPFound(location=redirect_to) parms = dict( api=api, menu=_menu_macro(), content_select_widget=_content_selection_widget(), content_select_grid=_content_selection_grid(), filtered_content=filtered_content, ) parms.update(_populate_content_selection_widget(context, request)) return render_template_to_response( 'templates/admin/delete_content.pt', **parms )
def main(): parser = OptionParser(description=__doc__, usage='usage: %prog [options] username password') parser.add_option('-C', '--config', dest='config', default=None, help="Specify a paster config file. Defaults to $CWD/etc/karl.ini") parser.add_option('--dry-run', '-n', dest='dry_run', action='store_true', default=False, help="Don't actually commit any transaction") path = '/' options, args = parser.parse_args() if args: path = args[0] config = options.config if config is None: config = get_default_config() root, closer = open_root(config) model = find_model(root, path) def out(msg): sys.stderr.write(msg) sys.stderr.write('\n') sys.stderr.flush() try: reset_security_workflow(model, output=out) except: transaction.abort() raise else: if options.dry_run: print 'no transaction committed due to --dry-run' else: transaction.commit()
def list_indexes(context): from opencore.tagging.index import TagIndex from repoze.catalog.indexes.text import CatalogTextIndex from repoze.bfg.traversal import find_model catalog = find_catalog(context) for name, index in catalog.items(): try: if isinstance(index, TagIndex): tags = find_site(context).tags taglist = list(tags._tagid_to_obj.items()) print name, (len(taglist), taglist) elif isinstance(index, CatalogTextIndex): docids = index.index._docwords objs = [] for docid in docids: path = catalog.document_map.address_for_docid(docid) context = find_model(context, path) objs.append(context) print name, (len(objs), objs) else: print name, list_index(index) except Exception, e: print e
def context(self): if not self._context: self._context = find_model(find_site(self.content), self.eventinfo['context_url']) return self._context
def _exists(context, path): try: find_model(context, path) return True except KeyError: return False
def traverse(self, path): return find_model(self, unquote(path))
def __call__(self, context, utility_name): if utility_name not in self._utilities: raise KeyError('`%s` is not a registered utility' % utility_name) return find_model(find_root(context), self._utilities[utility_name])
def showtag_view(context, request, community=None, user=None, crumb_title=None): """Show a page for a particular tag, optionally refined by context.""" page_title = 'Show Tag' api = request.api api.page_title = page_title # The tag screens (cloud, listing, and this view) each have a # "jump box" that allows you to quickly jump to another tag. All # three will point here at /showtag?tag=tag1. We detect this mode # and do a redirect. jump_tag = request.params.get('jumptag', False) if jump_tag: location = model_url(context, request, request.view_name, jump_tag) return HTTPFound(location=location) # Our strategy is to support tag URLs that are like this: # /showtag/tag1 # ...instead of: # /tagpage.html?tag=tag1 # However, our tag data isn't traversable (it is site.tags and not # site['tags']. So we have a view at /showtag that picks apart # the next hop in the URL. tag = request.subpath if not tag: # The user didn't provide anything beyond /showtag in the URL tag = None entries = related = [] else: # Ahh, the good part. Let's find some tag results and unpack # data into what the ZPT needs. tag = tag[0] page_title = 'Show Tag ' + tag catalog = find_catalog(context) dm = catalog.document_map tags = find_tags(context) related = tags.getRelatedTags(tag, user=user, community=community) entries = [] if user: users = (user,) else: users = None for docid in tags.getItems(tags=(tag,), users=users, community=community, ): # XXX Need to wire in batching address = dm.address_for_docid(int(docid)) if address is None: raise KeyError(docid) resource = find_model(context, address) # Skip documents which aren't viewable by authenticated user #if not has_permission('view', resource, request): # continue # Do a secondary query for each result to find the # per-user info users = tags.getUsers(tags=(tag,), items=(docid,), community=community) if len(users) == 1: tuh = '1 person' else: tuh = '%s people' % len(users) tuhref = model_url(context, request, 'tagusers.html', query={'tag': tag, 'docid': docid}) entry = { 'title': resource.title, 'description': getattr(resource, 'description', ''), 'href': model_url(resource, request), 'type': get_content_type_name(resource), 'tagusers_href': tuhref, 'tagusers_count': tuh, } entries.append(entry) args = dict( api=api, tag=tag, entries=entries, related=related, ) if crumb_title: # XXX Would context.title be a bit nicer for displaying to user? system_name = get_setting(context, 'system_name', 'KARL') args['crumbs'] = '%s / %s / %s' % ( system_name, crumb_title, context.__name__) return dict(**args)
def evolve(context): root = find_root(context) searcher = ICatalogSearch(root) categories_and_layers_query = dict( interfaces={'query':[ICalendarCategory, ICalendarLayer], 'operator':'or'}, ) total, docids, resolver = searcher(**categories_and_layers_query) changed_categories = {} for docid in docids: ob = resolver(docid) if ob is None: # slash in path, likely path = root.catalog.document_map.docid_to_address.get(docid) if path is not None: container_path, ob_name = path.rsplit('/', 1) container = find_model(root, container_path) name = urllib.unquote(ob_name) ob = container.get(name) if ob is not None: ob_name = ob.__name__ if not (ob_name.startswith('_default_') or is_opaque_id(ob_name)): old_path = model_path(ob) container = ob.__parent__ new_name = generate_name(container) del container[ob_name] ob.__name__ = new_name # XXX required? container.add(new_name, ob, send_events=False) new_path = model_path(ob) index_content(ob, None) print 'path fixed: %s -> %s' % (old_path, new_path) if ICalendarCategory.providedBy(ob): changed_categories[old_path] = new_path if changed_categories: # fix layer.paths layers_query = dict(interfaces=[ICalendarLayer]) total, docids, resolver = searcher(**layers_query) for docid in docids: layer = resolver(docid) if layer is not None: new_paths = [] changed = [] for path in layer.paths: if path in changed_categories: new_paths.append(changed_categories[path]) changed.append((path, changed_categories[path])) else: new_paths.append(path) if changed: layer.paths = new_paths reindex_content(layer, None) print 'layer fixed: %s, %s' % ( model_path(layer), [ '%s -> %s' % x for x in changed ]) # fix the category of events events_query = dict( interfaces=[ICalendarEvent], ) total, docids, resolver = searcher(**events_query) for docid in docids: event = resolver(docid) if event is not None: category = event.calendar_category if category in changed_categories: old_category = event.calendar_category new_category = changed_categories[category] event.calendar_category = new_category reindex_content(event, None) print 'event fixed: %s, %s -> %s' % ( model_path(event), old_category, new_category)
def move_content(root, src, dst, wf_state): try: context = find_model(root, src) except KeyError: print >>sys.stderr, "Source content not found: %s" % src sys.exit(-1) try: dest_folder = find_model(root, dst) except KeyError: print >>sys.stderr, "Destination folder not found: %s" % dst sys.exit(-1) src_community = find_community(context) catalog = find_catalog(root) assert catalog is not None users = find_users(root) assert users is not None if src_community is not None: move_header = ('<p><em>This was originally authored ' 'in the "%s" community.</em></p>' % src_community.title) else: move_header = '' src_folder = context.__parent__ name = context.__name__ log.info("Moving %s", model_path(context)) for obj in postorder(context): if hasattr(obj, 'docid'): docid = obj.docid catalog.document_map.remove_docid(docid) catalog.unindex_doc(docid) del src_folder[name] if (context.creator != 'admin' and users.get_by_id(context.creator) is None): # give the entry to the system admin log.warning( "User %s not found; reassigning to admin", context.creator) context.creator = 'admin' if name in dest_folder: name = make_unique_name(dest_folder, context.title) dest_folder[name] = context for obj in postorder(context): if hasattr(obj, 'docid'): docid = obj.docid catalog.document_map.add(model_path(obj), docid) catalog.index_doc(docid, obj) if wf_state is not None: wf = get_workflow(get_content_type(context), 'security', context) wf.transition_to_state(context, None, wf_state) if hasattr(context, 'text'): context.text = "%s\n%s" % (move_header, context.text)