def error(self, error, last_known_obj): """Render and log an error.""" # This is the patch ... in the original IBrowserView is IBrowserPage if IBrowserView.providedBy(last_known_obj): #of the last obj is a view, use it's context (which should be # an IAcquirer) last_known_obj = last_known_obj.context if not IAcquirer.providedBy(last_known_obj): last_known_site = getSite() if last_known_site is not None: last_known_obj = last_known_site context = DefaultError(error) if IAcquirer.providedBy(last_known_obj): context = context.__of__(last_known_obj) error_page = queryMultiAdapter( (context, self.request), name='error.html') if error_page is not None: try: error_result = error_page() if error_result is not None: self.response.setBody(error_result) except Exception as error: log_last_error( self.request, self.response, obj=last_known_obj, extra="Error while rendering error message") self.response.setStatus(500) self.response.setBody(ERROR_WHILE_RENDERING_ERROR_TEMPLATE) else: logger.error('No action defined for last exception') self.response.setStatus(500) self.response.setBody(DEFAULT_ERROR_TEMPLATE)
def getFields(self): if IAcquirer.providedBy(self.context): base = aq_base(self.context) else: base = self.context cls = type(base) applicable = self.types.get(cls) if applicable is None: # Check that we can get a settings object for this # context. applicable = IFeedSettings(self.context, None) is not None if applicable: # If there's an overlap on field names, we do not extend # the content schema. Note that Archetypes allows # overriding a field which is why we need to perform this # check ourselves. names = set(field.__name__ for field in self.fields) existing = self.context.schema.keys() overlap = names & set(existing) applicable = self.types[cls] = not bool(overlap) if not applicable: logging.getLogger('collective.chimpfeed').warn( "Unable to extend schema for: %s." % cls.__name__ ) if not applicable: return () return self.fields
def create(self, data): fti = getUtility(IDexterityFTI, name=self.portal_type) container = aq_inner(self.context) content = createObject(fti.factory) # Note: The factory may have done this already, but we want to be sure # that the created type has the right portal type. It is possible # to re-define a type through the web that uses the factory from an # existing type, but wants a unique portal_type! if hasattr(content, '_setPortalTypeName'): content._setPortalTypeName(fti.getId()) # Acquisition wrap temporarily to satisfy things like vocabularies # depending on tools if IAcquirer.providedBy(content): content = content.__of__(container) form.applyChanges(self, content, data) for group in self.groups: form.applyChanges(group, content, data) return aq_base(content)
def traverseName(self, ob, name): if name and name[:1] in '@+': # Process URI segment parameters. ns, nm = nsParse(name) if ns: try: ob2 = namespaceLookup(ns, nm, ob, self) except LocationError: raise ztkNotFound(ob, name) if IAcquirer.providedBy(ob2): ob2 = ob2.__of__(ob) return ob2 if name == '.': return ob if IPublishTraverse.providedBy(ob): ob2 = ob.publishTraverse(self, name) else: adapter = queryMultiAdapter((ob, self), IPublishTraverse) if adapter is None: ## Zope2 doesn't set up its own adapters in a lot of cases ## so we will just use a default adapter. adapter = DefaultPublishTraverse(ob, self) ob2 = adapter.publishTraverse(self, name) return ob2
def createAndAdd(self, data): # Filter away data values that does not come from the 'core' schema. # Additional values can come from AutoExtensibleForm/FormExtender # schemas,and the portlet Assignment creation will fail if the # portlet AddForm create() method is using "Assignment(**data)" # instead of explicit parameters. # Extender values are set by form.applyChanges below, via the usual # z3cform adapter lookups. schema_keys = field.Fields(self.schema).keys() unextended_data = {key: data[key] for key in schema_keys if data.has_key(key)} obj = self.create(unextended_data) # Acquisition wrap temporarily to satisfy things like vocabularies # depending on tools container = aq_inner(self.context) if IAcquirer.providedBy(obj): obj = obj.__of__(container) form.applyChanges(self, obj, data) obj = aq_base(obj) zope.event.notify(zope.lifecycleevent.ObjectCreatedEvent(obj)) self.add(obj) return obj
def publishTraverse(self, request, name): context = aq_inner(self.context) # If we are trying to traverse to the folder "body" pseudo-object # returned by listDAVObjects(), return that immediately if getattr(request, 'maybe_webdav_client', False) \ and name == DAV_FOLDER_DATA_ID: return FolderDataResource( DAV_FOLDER_DATA_ID, context ).__of__(context) defaultTraversal = super( DexterityPublishTraverse, self).publishTraverse(request, name) # If this is a WebDAV PUT/PROPFIND/PROPPATCH request, don't acquire # things. If we did, we couldn't create a new object with PUT, for # example, because the acquired object would shadow the NullResource if getattr(request, 'maybe_webdav_client', False) \ and request.get('REQUEST_METHOD', 'GET') not in ('GET', 'POST',) \ and IAcquirer.providedBy(defaultTraversal): parent = aq_parent(aq_inner(defaultTraversal)) if parent is not None and parent is not context: return NullResource( self.context, name, request).__of__(self.context) return defaultTraversal
def filter(self, viewlets): """Filter the viewlets. ``viewlets`` is a list of tuples of the form (name, viewlet). This filters the viewlets just like Five, but also filters out viewlets by name from the local utility which implements the IViewletSettingsStorage interface. """ results = [] storage = queryUtility(IViewletSettingsStorage) if storage is None: return results skinname = self.context.getCurrentSkinName() hidden = frozenset(storage.getHidden(self.__name__, skinname)) # Only return visible viewlets accessible to the principal # We need to wrap each viewlet in its context to make sure that # the object has a real context from which to determine owner # security. # Copied from Five for name, viewlet in viewlets: if IAcquirer.providedBy(viewlet): viewlet = viewlet.__of__(viewlet.context) if name not in hidden and guarded_hasattr(viewlet, 'render'): results.append((name, viewlet)) return results
def inherited_portlets(self): """Return the list of portlets inherited by the current context. Invisible (hidden) portlets are excluded. """ context = aq_inner(self.context) data = [] while not IPloneSiteRoot.providedBy(context): if IAcquirer.providedBy(context): context = aq_parent(aq_inner(context)) else: context = context.__parent__ # we get the contextual portlets view to access its utility methods view = queryMultiAdapter((context, self.request), name=self.__parent__.__name__) if view is not None: assignments = view.getAssignmentsForManager(self.manager) is_visible = lambda a: IPortletAssignmentSettings(a).get('visible', True) assignments_to_show = [a for a in assignments if is_visible(a)] base_url = view.getAssignmentMappingUrl(self.manager) data.extend(self.portlets_for_assignments(assignments_to_show, self.manager, base_url)) assignable = queryMultiAdapter((context, self.manager), ILocalPortletAssignmentManager) if assignable is not None and assignable.getBlacklistStatus(CONTEXT_CATEGORY): # Current context has blocked inherited portlets, stop. break return data
def create(self, data): LOG.info('create: '+str(self.portal_type)) fti = getUtility(IDexterityFTI, name=self.portal_type) container = aq_inner(self.context) options = {} options['portal_type'] = self.portal_type options['sql_id'] = data.get('ISQLContent.sql_id') content = createObject(fti.factory, **options) # Note: The factory may have done this already, but we want to be sure # that the created type has the right portal type. It is possible # to re-define a type through the web that uses the factory from an # existing type, but wants a unique portal_type! if hasattr(content, '_setPortalTypeName'): content._setPortalTypeName(fti.getId()) # Acquisition wrap temporarily to satisfy things like vocabularies # depending on tools if IAcquirer.providedBy(content): content = content.__of__(container) # Don't set empty data in SQL DB: for k,v in data.items(): if not v: del data[k] form.applyChanges(self, content, data) for group in self.groups: form.applyChanges(group, content, data) return aq_base(content)
def create(context, type_): """ Create element, set attributes and add it to container. """ fti = getUtility(IDexterityFTI, name=type_) container = aq_inner(context) obj = createObject(fti.factory) # Note: The factory may have done this already, but we want to be sure # that the created type has the right portal type. It is possible # to re-define a type through the web that uses the factory from an # existing type, but wants a unique portal_type! if hasattr(obj, '_setPortalTypeName'): obj._setPortalTypeName(fti.getId()) # Acquisition wrap temporarily to satisfy things like vocabularies # depending on tools if IAcquirer.providedBy(obj): obj = obj.__of__(container) obj = aq_base(obj) if obj: notify(ObjectCreatedEvent(obj)) return obj
def create(self, data={}): # import pdb; pdb.set_trace() # return super(AddForm, self).create(data) fti = getUtility(IDexterityFTI, name=self.portal_type) container = aq_inner(self.context) content = createObject(fti.factory) if hasattr(content, '_setPortalTypeName'): content._setPortalTypeName(fti.getId()) # Acquisition wrap temporarily to satisfy things like vocabularies # depending on tools if IAcquirer.providedBy(content): content = content.__of__(container) id = str(int(time())) content.title = id content.id = id content.text = self.request.form.get('form.widgets.text', '') reason = self.request.form.get('form.widgets.closing_reason') content.closing_reason = reason[0] adapted = IAllowDiscussion(content) adapted.allow_discussion = True # Edit highlighs highlights = self.request.form.get('form.widgets.highlight') container.highlights = highlights # Update Observation state api.content.transition( obj=self.context, transition='phase1-draft-conclusions' ) return aq_base(content)
def populateContextFromDraft(self): """Will populate the temporary content object from values contained within the draft """ data, errors = self.extractData() if errors: return None fti = zope.component.getUtility(IDexterityFTI, name=self.portal_type) container = aq_inner(self.context) content = zope.component.createObject(fti.factory) if hasattr(content, '_setPortalTypeName'): content._setPortalTypeName(fti.getId()) # Acquisition wrap temporarily to satisfy things like vocabularies # depending on tools if IAcquirer.providedBy(content): content = content.__of__(container) applyChanges(self, content, data) for group in self.groups: applyChanges(group, content, data) return aq_base(content)
def render_error(self, error, last_known_obj): """Render and log an error. """ if IBrowserPage.providedBy(last_known_obj): #of the last obj is a view, use it's context (which should be # an IAcquirer) last_known_obj = last_known_obj.context if not IAcquirer.providedBy(last_known_obj): last_known_site = getSite() if last_known_site is not None: last_known_obj = last_known_site context = DefaultError(error) if IAcquirer.providedBy(last_known_obj): context = context.__of__(last_known_obj) error_view = queryMultiAdapter( (context, self.request), name='error.html') if IBrowserPublisher.providedBy(error_view): error_view, error_path = error_view.browserDefault(self.request) if error_path: raise NotImplementedError( u'Error browserDefault retuned an path. ' u'This is not implemented.') if error_view is not None: notify(interfaces.PublicationBeforeError( self.request, last_known_obj)) try: error_result = error_view() if error_result is not None: self.response.setBody(error_result) notify(interfaces.PublicationAfterRender( self.request, error_view)) except Exception: log_last_error( self.request, self.response, obj=last_known_obj, extra=u"Error while rendering error message") self.response.setStatus(500) self.response.setBody(ERROR_WHILE_RENDERING_ERROR_TEMPLATE) else: logger.error('No action defined for last exception') self.response.setStatus(500) self.response.setBody(DEFAULT_ERROR_TEMPLATE)
def _find_page_context(self, given_context=None): """Try to find a usable context, with increasing agression""" # Normally, we should be given a useful context (e.g the page) c = given_context if IAcquirer.providedBy(c): return c # Subforms (e.g. DataGridField) may not have a context set, find out # what page is being published c = getattr(getRequest(), 'PUBLISHED', None) if IAcquirer.providedBy(c): return c # During widget traversal nothing is being published yet, use getSite() c = getSite() if IAcquirer.providedBy(c): return c # During kss_z3cform_inline_validation, PUBLISHED and getSite() return # a Z3CFormValidation object. What we want is it's context. c = getattr(getattr(getRequest(), 'PUBLISHED', None), 'context', None) if IAcquirer.providedBy(c): return c raise ValueError('Cannot find suitable context to bind to source')
def _wrap(comp, registry): """Return an aq wrapped component with the site as the parent but only if the comp has an aq wrapper to begin with. """ # BBB: The primary reason for doing this sort of wrapping of # returned utilities is to support CMF tool-like functionality where # a tool expects its aq_parent to be the portal object. New code # (ie new utilities) should not rely on this predictability to # get the portal object and should search out an alternate means # (possibly retrieve the ISiteRoot utility). Although in most # cases getting at the portal object shouldn't be the required pattern # but instead looking up required functionality via other (possibly # local) components. if registry.__bases__ and IAcquirer.providedBy(comp): current_site = getSite() registry_site = Acquisition.aq_base(registry.__parent__) if not ISite.providedBy(registry_site): registry_site = registry_site.__parent__ if current_site is None: # If no current site can be found, return utilities wrapped in # the site they where registered in. We loose the whole aq chain # here though current_site = Acquisition.aq_base(registry_site) parent = None if current_site == registry_site: parent = current_site else: parent = _recurse_to_site(current_site, registry_site) if parent is None: raise ValueError('Not enough context to acquire parent') base = Acquisition.aq_base(comp) # clean up aq_chain, removing REQUEST objects parent = _rewrap(parent) if base is not Acquisition.aq_base(parent): # If the component is not the component registry container, # wrap it in the parent comp = base.__of__(parent) else: # If the component happens to be the component registry # container we are looking up a ISiteRoot. # We are not wrapping it in itself but in its own parent comp = base.__of__(Acquisition.aq_parent(parent)) return comp
def publishTraverse(self, request, name): if name == 'managers': return Managers('managers', request, self.context)\ .__of__(self.context) elif name == 'sectors': return Sectors('sectors', request, self.context)\ .__of__(self.context) view = queryMultiAdapter((self.context, request), Interface, name) if view is not None: if IAcquirer.providedBy(view): view = view.__of__(self.context) return view raise KeyError(name)
def get(template, view=None, cls=None): layer = utility.getLayer() key = layer, template inst = registry.get(key) if inst is None: cls = type(template) inst = registry[key] = cls.__new__(cls) inst.__dict__ = template.__dict__.copy() for manager in utility.getManagers(layer): # register template; this call returns ``True`` if the # template was invalidated (changed filename) if manager.registerTemplate(inst, template): inst._v_last_read = False inst.__dict__.pop('_v_template', None) break if view is not None and IAcquirer is not None: if IAcquirer.providedBy(inst) and IAcquirer.providedBy(view): return inst.__of__(view) return inst
def render_tree(self): content = self.context if not IAcquirer.providedBy(content): content = getSite() source = self.bound_source strategy = getMultiAdapter((content, self), INavtreeStrategy) data = buildFolderTree(content, obj=content, query=source.navigation_tree_query, strategy=strategy) return self.recurse_template(children=data.get('children', []), level=1)
def createAndAdd(self, data): obj = self.create(data) # Acquisition wrap temporarily to satisfy things like vocabularies # depending on tools container = aq_inner(self.context) if IAcquirer.providedBy(obj): obj = obj.__of__(container) form.applyChanges(self, obj, data) obj = aq_base(obj) zope.event.notify(zope.lifecycleevent.ObjectCreatedEvent(obj)) self.add(obj) return obj
def getToolByName(obj, name, default=_marker): """ Get the tool, 'toolname', by acquiring it. o Application code should use this method, rather than simply acquiring the tool by name, to ease forward migration (e.g., to Zope3). """ tool_interface = _tool_interface_registry.get(name) if tool_interface is not None: try: utility = getUtility(tool_interface) # Site managers, except for five.localsitemanager, return unwrapped # utilities. If the result is something which is acquisition-unaware # but unwrapped we wrap it on the context. if IAcquirer.providedBy(obj) and \ aq_parent(utility) is None and \ IAcquirer.providedBy(utility): utilty = utility.__of__(obj) return utility except ComponentLookupError: # behave in backwards-compatible way # fall through to old implementation pass try: tool = aq_get(obj, name, default, 1) except AttributeError: if default is _marker: raise return default else: if tool is _marker: raise AttributeError, name return tool
def create(self, data): data['timezone'] = default_timezone() self.prepare_coordinates(data) self.prepare_submission(data) content = createContent('seantis.dir.events.item', **data) if IAcquirer.providedBy(content): content = content.__of__(aq_inner(self.context)) # must be done before adding to the container self.apply_submission(content) return aq_base(content)
def create(self, data): # This is mostly a direct copy of # :py:meth:`plone.dexterity.browser.add.DefaultAddForm.create`, # extended to apply the right interface. fti = getUtility(IDexterityFTI, name=self.portal_type) container = aq_inner(self.context) content = createObject(fti.factory) alsoProvides(content, self.schema) if hasattr(content, '_setPortalTypeName'): content._setPortalTypeName(fti.getId()) if IAcquirer.providedBy(content): content = content.__of__(container) applyChanges(self, content, data) for group in self.groups: applyChanges(group, content, data) return aq_base(content)
def __call__(self): # We want to check that the user was indeed allowed to access the # form for this widget. We can only this now, since security isn't # applied yet during traversal. self.validate_access() widget = self.context context = widget.context # Update the widget before accessing the source. # The source was only bound without security applied # during traversal before. widget.update() source = widget.bound_source # Convert token from request to the path to the object token = self.request.form.get('href', None) directory = self.context.bound_source.tokenToPath(token) level = self.request.form.get('rel', 0) navtree_query = source.navigation_tree_query.copy() navtree_query['path'] = {'depth': 1, 'query': directory} if 'is_default_page' not in navtree_query: navtree_query['is_default_page'] = False content = context if not IAcquirer.providedBy(content): content = getSite() strategy = getMultiAdapter((content, widget), INavtreeStrategy) catalog = getToolByName(content, 'portal_catalog') children = [] for brain in catalog(navtree_query): newNode = {'item' : brain, 'depth' : -1, # not needed here 'currentItem' : False, 'currentParent' : False, 'children' : []} if strategy.nodeFilter(newNode): newNode = strategy.decoratorFactory(newNode) children.append(newNode) return self.fragment_template(children=children, level=int(level))
def create(self, data={}): fti = getUtility(IDexterityFTI, name=self.portal_type) container = aq_inner(self.context) content = createObject(fti.factory) if hasattr(content, '_setPortalTypeName'): content._setPortalTypeName(fti.getId()) # Acquisition wrap temporarily to satisfy things like vocabularies # depending on tools if IAcquirer.providedBy(content): content = content.__of__(container) context = self.context ids = [id for id in context.keys() if id.startswith('question-')] id = len(ids) + 1 content.title = 'Question %d' % id return aq_base(content)
def __call__(self): # We want to check that the user was indeed allowed to access the # form for this widget. We can only this now, since security isn't # applied yet during traversal. self.validate_access() widget = self.context context = widget.context # Update the widget before accessing the source. # The source was only bound without security applied # during traversal before. widget.update() source = widget.bound_source # Convert token from request to the path to the object token = self.request.form.get('href', None) directory = self.context.bound_source.tokenToPath(token) navtree_query = source.navigation_tree_query.copy() navtree_query['path'] = {'query': directory} if 'is_default_page' not in navtree_query: navtree_query['is_default_page'] = False if navtree_query['is_default_page'] in [(True,False), (False, True)]: del navtree_query['is_default_page'] content = context if not IAcquirer.providedBy(content): content = closest_content(context) catalog = getToolByName(content, 'portal_catalog') results = catalog(navtree_query) if len(results) > 0: obj = results[0].getObject() preview = queryMultiAdapter( (obj, self.context), IContentTreeWidgetPreview) if preview is None: return _(u"No preview available.") return preview()
def create(self, data={}): # import pdb; pdb.set_trace() # return super(AddForm, self).create(data) fti = getUtility(IDexterityFTI, name=self.portal_type) container = aq_inner(self.context) content = createObject(fti.factory) if hasattr(content, '_setPortalTypeName'): content._setPortalTypeName(fti.getId()) # Acquisition wrap temporarily to satisfy things like vocabularies # depending on tools if IAcquirer.providedBy(content): content = content.__of__(container) id = str(int(time())) content.title = id content.id = id content.text = self.request.form.get('form.widgets.text', '') return aq_base(content)
def get_value(self, id, **kw): """Get value for id. Optionally pass keyword arguments that get passed to TALES expression. """ tales_expr = self.tales.get(id, "") if tales_expr: # kw are the expression namespace. Fill in it correctly. field = aq_inner(self) context = aq_parent(self) if 'here' not in kw: kw['here'] = field if 'request' not in kw and hasattr(self, 'REQUEST'): kw['request'] = self.REQUEST kw['modules'] = SecureModuleImporter value = tales_expr.__of__(self)( field=field, form=aq_parent(field), context=context, **kw) else: override = self.overrides.get(id, "") if override: # call wrapped method to get answer value = override.__of__(self)() else: # get normal value value = self.get_orig_value(id) # if normal value can be wrapped in Acquisition, do it if IAcquirer.providedBy(value): return value.__of__(self) # create message id for title and description in right domain if id in ['title', 'description']: i18n_domain = self.get_i18n_domain() if i18n_domain: return MessageFactory(i18n_domain)(value) return value
def publishTraverse(self, request, name): stack = request['TraversalRequestNameStack'] stack.append(name) node_id = find_sql_context(self.context.id, stack) if node_id is not None: self.request.survey_session = self.context if stack and stack[-1] != 'actionplans' and\ not stack[-1].startswith('@@'): stack.append('@@%s' % stack.pop()) return build_tree_aq_chain(self.context, node_id) stack.pop() view = queryMultiAdapter((self.context, request), Interface, name) if view is not None: if IAcquirer.providedBy(view): view = view.__of__(self.context) return view else: raise KeyError(name)
def get_viewlet(self, manager_name, viewlet_name): # check visibility storage = queryUtility(IViewletSettingsStorage) if storage is None: return None skinname = self.context.getCurrentSkinName() hidden = frozenset(storage.getHidden(manager_name, skinname)) if viewlet_name in hidden: return None # get viewlet instance manager = queryMultiAdapter( (self.context, self.request, self), IViewletManager, name=manager_name ) viewlet = queryMultiAdapter( (self.context, self.request, self, manager), IViewlet, name=viewlet_name ) if viewlet is None: logger.debug( 'Viewlet tile {0} in manager {1}. ' 'Was not found.'.format(viewlet_name, manager_name) ) return None # check permissions - same as in plone.app.viewletmanager if IAcquirer.providedBy(viewlet): viewlet = viewlet.__of__(viewlet.context) if not guarded_hasattr(viewlet, 'render'): logger.warn( 'Blocked attempt to render tile {0} in manager {1}. ' 'Permission denied.'.format(viewlet_name, manager_name) ) return None return viewlet
def create(self, data): fti = getUtility(IDexterityFTI, name=self.portal_type) container = aq_inner(self.context) content = createObject(fti.factory) # Note: The factory may have done this already, but we want to be # sure that the created type has the right portal type. It is # possible to re-define a type through the web that uses the # factory from an existing type, but wants a unique portal_type! if hasattr(content, '_setPortalTypeName'): content._setPortalTypeName(fti.getId()) # Acquisition wrap temporarily to satisfy things like # vocabularies depending on tools if IAcquirer.providedBy(content): content = content.__of__(container) for (key, value) in data.items(): setattr(content, key, value) return aq_base(content)
def reply(self): data = json_body(self.request) type_ = data.get("@type", None) id_ = data.get("id", None) title = data.get("title", None) translation_of = data.get("translation_of", None) language = data.get("language", None) uid = data.get("UID", None) if not type_: raise BadRequest("Property '@type' is required") # Disable CSRF protection if "IDisableCSRFProtection" in dir(plone.protect.interfaces): alsoProvides(self.request, plone.protect.interfaces.IDisableCSRFProtection) sm = getSecurityManager() # ManagePortal is required to set the uid of an object during creation if uid and not sm.checkPermission(ManagePortal, self.context): self.request.response.setStatus(403) msg = "Setting UID of an object requires Manage Portal permission" return dict(error=dict(type="Forbidden", message=msg)) try: obj = create(self.context, type_, id_=id_, title=title) except Unauthorized as exc: self.request.response.setStatus(403) return dict(error=dict(type="Forbidden", message=str(exc))) except BadRequest as exc: self.request.response.setStatus(400) return dict(error=dict(type="Bad Request", message=str(exc))) # Acquisition wrap temporarily to satisfy things like vocabularies # depending on tools temporarily_wrapped = False if IAcquirer.providedBy(obj) and not safe_hasattr(obj, "aq_base"): obj = obj.__of__(self.context) temporarily_wrapped = True # Update fields deserializer = queryMultiAdapter((obj, self.request), IDeserializeFromJson) if deserializer is None: self.request.response.setStatus(501) return dict(error=dict( message=f"Cannot deserialize type {obj.portal_type}")) try: deserializer(validate_all=True, create=True) except DeserializationError as e: self.request.response.setStatus(400) return dict( error=dict(type="DeserializationError", message=str(e))) if temporarily_wrapped: obj = aq_base(obj) if uid: setattr(obj, "_plone.uuid", uid) if not getattr(deserializer, "notifies_create", False): notify(ObjectCreatedEvent(obj)) obj = add(self.context, obj, rename=not bool(id_)) # Link translation given the translation_of property if (IPloneAppMultilingualInstalled.providedBy(self.request) and translation_of and language): source = self.get_object(translation_of) if source: manager = ITranslationManager(source) manager.register_translation(language, obj) self.request.response.setStatus(201) self.request.response.setHeader("Location", obj.absolute_url()) serializer = queryMultiAdapter((obj, self.request), ISerializeToJson) serialized_obj = serializer() # HypermediaBatch can't determine the correct canonical URL for # objects that have just been created via POST - so we make sure # to set it here serialized_obj["@id"] = obj.absolute_url() return serialized_obj
def _create_object(self, fhir): """ """ form_data = { "@type": fhir["resourceType"], "id": fhir["id"], "title": "{0}-{1}".format(self.resource_type, fhir["id"]), } fhir_field_name = "{0}_resource".format(fhir["resourceType"].lower()) form_data[fhir_field_name] = fhir self.request["BODY"] = json.dumps(form_data) context = self.context obj = create_obj(context, form_data["@type"], id_=form_data["id"], title=form_data["title"]) if isinstance(obj, dict) and "error" in obj: self.request.response.setStatus(400) return obj # Acquisition wrap temporarily to satisfy things like vocabularies # depending on tools temporarily_wrapped = False if IAcquirer.providedBy(obj) and not safe_hasattr(obj, "aq_base"): obj = obj.__of__(context) temporarily_wrapped = True # Update fields deserializer = queryMultiAdapter((obj, self.request), IDeserializeFromJson) if deserializer is None: self.request.response.setStatus(501) return dict(error=dict( message="Cannot deserialize type {0}".format(obj.portal_type))) try: deserializer(validate_all=True, create=True) except DeserializationError as e: self.request.response.setStatus(400) return dict( error=dict(type="DeserializationError", message=str(e))) if temporarily_wrapped: obj = aq_base(obj) # Notify Dexterity Created if not getattr(deserializer, "notifies_create", False): notify(ObjectCreatedEvent(obj)) # Adding to Container add_obj(context, obj, rename=False) self.request.response.setStatus(201) response = getattr(obj, fhir_field_name) self.request.response.setHeader( "Location", "/".join([ self.context.portal_url(), "@fhir", response.resource_type, response.id, ]), ) return response
def publishTraverse(self, request, name): object = self.context URL = request['URL'] if name[:1] == '_': raise Forbidden("Object name begins with an underscore at: %s" % URL) if hasattr(object, '__bobo_traverse__'): # We can use the normal logic return super(PortalRootPublishTraverse, self).publishTraverse(request, name) else: subobject = None # No __bobo_traverse__ # Try with an unacquired attribute: try: subobject = object.__getattribute__(name) except AttributeError: # this is not a direct object pass else: if IAcquirer.providedBy(subobject): subobject = aq_base(subobject).__of__(object) if subobject is None: # We try to fall back to a view: subobject = queryMultiAdapter((object, request), Interface, name) if subobject is not None: if IAcquirer.providedBy(subobject): subobject = subobject.__of__(object) return subobject # And lastly, of there is no view, try acquired attributes, but # only if there is no __bobo_traverse__: try: subobject = getattr(object, name) # Again, clear any error status created by __bobo_traverse__ # because we actually found something: request.response.setStatus(200) return subobject except AttributeError: pass # Lastly we try with key access: try: subobject = object[name] except TypeError: # unsubscriptable raise KeyError(name) # Ensure that the object has a docstring, or that the parent # object has a pseudo-docstring for the object. Objects that # have an empty or missing docstring are not published. doc = getattr(subobject, '__doc__', None) if doc is None: doc = getattr(object, '%s__doc__' % name, None) if not doc: raise Forbidden( "The object at %s has an empty or missing " \ "docstring. Objects must have a docstring to be " \ "published." % URL ) # Hack for security: in Python 2.2.2, most built-in types # gained docstrings that they didn't have before. That caused # certain mutable types (dicts, lists) to become publishable # when they shouldn't be. The following check makes sure that # the right thing happens in both 2.2.2+ and earlier versions. if not typeCheck(subobject): raise Forbidden("The object at %s is not publishable." % URL) return subobject
def __call__(self, published, REQUEST, t, v, traceback): try: if t is SystemExit or issubclass(t, Redirect): raise t, v, traceback if issubclass(t, ConflictError): self.logConflicts(v, REQUEST) raise ZPublisher.Retry(t, v, traceback) if t is ZPublisher.Retry: try: v.reraise() except: # we catch the re-raised exception so that it gets # stored in the error log and gets rendered with # standard_error_message t, v, traceback = sys.exc_info() if issubclass(t, ConflictError): # ouch, a user saw this conflict error :-( self.unresolved_conflict_errors += 1 try: log = aq_acquire(published, '__error_log__', containment=1) except AttributeError: error_log_url = '' else: error_log_url = log.raising((t, v, traceback)) if (REQUEST is None or (getattr(REQUEST.get( 'RESPONSE', None), '_error_format', '') != 'text/html')): raise t, v, traceback # Lookup a view for the exception and render it, then # raise the rendered value as the exception value # (basically the same that 'raise_standardErrorMessage' # does. The view is named 'index.html' because that's what # zope.publisher uses as well. view = queryMultiAdapter((v, REQUEST), name=u'index.html') if view is not None: if IAcquirer.providedBy(view) and IAcquirer.providedBy( published): view = view.__of__(published) else: view.__parent__ = published v = view() if issubclass(t, Unauthorized): # Re-raise Unauthorized to make sure it is handled # correctly. We can't do that with all exceptions # because some don't work with the rendered v as # argument. raise t, v, traceback response = REQUEST.RESPONSE response.setStatus(t) response.setBody(v) return response if (published is None or published is app or isinstance(published, list)): # At least get the top-level object published = app.__bobo_traverse__(REQUEST).__of__( RequestContainer(REQUEST)) published = getattr(published, 'im_self', published) while 1: f = getattr(published, self.raise_error_message, None) if f is None: published = aq_parent(published) if published is None: raise t, v, traceback else: break client = published while 1: if getattr(client, self.error_message, None) is not None: break client = aq_parent(client) # If we are going in circles without getting the error_message # just raise if client is None or aq_base(client) is aq_base(published): raise t, v, traceback if REQUEST.get('AUTHENTICATED_USER', None) is None: REQUEST['AUTHENTICATED_USER'] = AccessControl.User.nobody result = f(client, REQUEST, t, v, traceback, error_log_url=error_log_url) if result is not None: t, v, traceback = result if issubclass(t, Unauthorized): # Re-raise Unauthorized to make sure it is handled # correctly. We can't do that with all exceptions # because some don't work with the rendered v as # argument. raise t, v, traceback response = REQUEST.RESPONSE response.setStatus(t) response.setBody(v) return response finally: traceback = None
def _wrap(comp, registry): """Return an aq wrapped component with the site as the parent but only if the comp has an aq wrapper to begin with. """ # If component is stored as a ComponentPathWrapper, we traverse to # the component using the stored path: if isinstance(comp, ComponentPathWrapper): comp = getSite().unrestrictedTraverse(comp.path) if IAcquirer.providedBy(comp): return _rewrap(comp) else: return comp # BBB: The primary reason for doing this sort of wrapping of # returned utilities is to support CMF tool-like functionality where # a tool expects its aq_parent to be the portal object. New code # (ie new utilities) should not rely on this predictability to # get the portal object and should search out an alternate means # (possibly retrieve the ISiteRoot utility). Although in most # cases getting at the portal object shouldn't be the required pattern # but instead looking up required functionality via other (possibly # local) components. if registry.__bases__ and IAcquirer.providedBy(comp): current_site = getSite() registry_site = Acquisition.aq_base(registry.__parent__) if not ISite.providedBy(registry_site): registry_site = registry_site.__parent__ if current_site is None: # If no current site can be found, return utilities wrapped in # the site they where registered in. We loose the whole aq chain # here though current_site = Acquisition.aq_base(registry_site) parent = None if current_site == registry_site: parent = current_site else: parent = _recurse_to_site(current_site, registry_site) if parent is None: raise ValueError('Not enough context to acquire parent') base = Acquisition.aq_base(comp) # clean up aq_chain, removing REQUEST objects parent = _rewrap(parent) if base is not Acquisition.aq_base(parent): # If the component is not the component registry container, # wrap it in the parent comp = base.__of__(parent) else: # If the component happens to be the component registry # container we are looking up a ISiteRoot. # We are not wrapping it in itself but in its own parent site_parent = Acquisition.aq_parent(parent) if site_parent is not None: comp = base.__of__(site_parent) else: comp = base return comp
def reply(self): data = json_body(self.request) type_ = data.get('@type', None) id_ = data.get('id', None) title = data.get('title', None) if not type_: raise BadRequest("Property '@type' is required") # Disable CSRF protection if 'IDisableCSRFProtection' in dir(plone.protect.interfaces): alsoProvides(self.request, plone.protect.interfaces.IDisableCSRFProtection) try: obj = create(self.context, type_, id_=id_, title=title) except Unauthorized as exc: self.request.response.setStatus(403) return dict(error=dict( type='Forbidden', message=str(exc))) except BadRequest as exc: self.request.response.setStatus(400) return dict(error=dict( type='Bad Request', message=str(exc))) # Acquisition wrap temporarily to satisfy things like vocabularies # depending on tools temporarily_wrapped = False if IAcquirer.providedBy(obj) and not safe_hasattr(obj, 'aq_base'): obj = obj.__of__(self.context) temporarily_wrapped = True # Update fields deserializer = queryMultiAdapter((obj, self.request), IDeserializeFromJson) if deserializer is None: self.request.response.setStatus(501) return dict(error=dict( message='Cannot deserialize type {}'.format(obj.portal_type))) try: deserializer(validate_all=True, create=True) except DeserializationError as e: self.request.response.setStatus(400) return dict(error=dict( type='DeserializationError', message=str(e))) if temporarily_wrapped: obj = aq_base(obj) if not getattr(deserializer, 'notifies_create', False): notify(ObjectCreatedEvent(obj)) obj = add(self.context, obj, rename=not bool(id_)) self.request.response.setStatus(201) self.request.response.setHeader('Location', obj.absolute_url()) serializer = queryMultiAdapter( (obj, self.request), ISerializeToJson ) serialized_obj = serializer() # HypermediaBatch can't determine the correct canonical URL for # objects that have just been created via POST - so we make sure # to set it here serialized_obj['@id'] = obj.absolute_url() return serialized_obj
def unrestrictedTraverse(self, path, default=_marker, restricted=False): """Lookup an object by path. path -- The path to the object. May be a sequence of strings or a slash separated string. If the path begins with an empty path element (i.e., an empty string or a slash) then the lookup is performed from the application root. Otherwise, the lookup is relative to self. Two dots (..) as a path element indicates an upward traversal to the acquisition parent. default -- If provided, this is the value returned if the path cannot be traversed for any reason (i.e., no object exists at that path or the object is inaccessible). restricted -- If false (default) then no security checking is performed. If true, then all of the objects along the path are validated with the security machinery. Usually invoked using restrictedTraverse(). """ if not path: return self if isinstance(path, str): # Only native strings are allowed path = path.split('/') else: path = list(path) REQUEST = {'TraversalRequestNameStack': path} path.reverse() path_pop = path.pop if len(path) > 1 and not path[0]: # Remove trailing slash path_pop(0) if restricted: validate = getSecurityManager().validate if not path[-1]: # If the path starts with an empty string, go to the root first. path_pop() obj = self.getPhysicalRoot() if restricted: validate(None, None, None, obj) # may raise Unauthorized else: obj = self # import time ordering problem if bbb.HAS_ZSERVER: from webdav.NullResource import NullResource else: NullResource = bbb.NullResource resource = _marker try: while path: name = path_pop() __traceback_info__ = path, name if name[0] == '_': # Never allowed in a URL. raise NotFound(name) if name == '..': next = aq_parent(obj) if next is not None: if restricted and not validate(obj, obj, name, next): raise Unauthorized(name) obj = next continue bobo_traverse = getattr(obj, '__bobo_traverse__', None) try: if (name and name[:1] in '@+' and name != '+' and nsParse(name)[1]): # Process URI segment parameters. ns, nm = nsParse(name) try: next = namespaceLookup(ns, nm, obj, aq_acquire(self, 'REQUEST')) if IAcquirer.providedBy(next): next = next.__of__(obj) if restricted and not validate( obj, obj, name, next): raise Unauthorized(name) except LocationError: raise AttributeError(name) else: next = UseTraversalDefault # indicator try: if bobo_traverse is not None: next = bobo_traverse(REQUEST, name) if restricted: if aq_base(next) is not next: # The object is wrapped, so the # acquisition context is the container. container = aq_parent(aq_inner(next)) elif getattr(next, '__self__', None) is not None: # Bound method, the bound instance # is the container container = next.__self__ elif getattr(aq_base(obj), name, _marker) is next: # Unwrapped direct attribute of the # object so object is the container container = obj else: # Can't determine container container = None # If next is a simple unwrapped property, # its parentage is indeterminate, but it # may have been acquired safely. In this # case validate will raise an error, and # we can explicitly check that our value # was acquired safely. try: ok = validate(obj, container, name, next) except Unauthorized: ok = False if not ok: if (container is not None or guarded_getattr( obj, name, _marker) is not next # NOQA: E501 ): raise Unauthorized(name) except UseTraversalDefault: # behave as if there had been no # '__bobo_traverse__' bobo_traverse = None if next is UseTraversalDefault: if getattr(aq_base(obj), name, _marker) is not _marker: if restricted: next = guarded_getattr(obj, name) else: next = getattr(obj, name) else: try: next = obj[name] # The item lookup may return a # NullResource, if this is the case we # save it and return it if all other # lookups fail. if (NullResource is not None and isinstance(next, NullResource)): resource = next raise KeyError(name) except (AttributeError, TypeError): # Raise NotFound for easier debugging # instead of AttributeError: __getitem__ # or TypeError: not subscriptable raise NotFound(name) if restricted and not validate( obj, obj, None, next): raise Unauthorized(name) except (AttributeError, NotFound, KeyError) as e: # Try to look for a view next = queryMultiAdapter( (obj, aq_acquire(self, 'REQUEST')), Interface, name) if next is not None: if IAcquirer.providedBy(next): next = next.__of__(obj) if restricted and not validate(obj, obj, name, next): raise Unauthorized(name) elif bobo_traverse is not None: # Attribute lookup should not be done after # __bobo_traverse__: raise e else: # No view, try acquired attributes try: if restricted: next = guarded_getattr(obj, name, _marker) else: next = getattr(obj, name, _marker) except AttributeError: raise e if next is _marker: # If we have a NullResource from earlier use it. next = resource if next is _marker: # Nothing found re-raise error raise e obj = next return obj except ConflictError: raise except Exception: if default is not _marker: return default else: raise
def publishTraverse(self, request, name): object = self.context URL = request['URL'] if name[:1] == '_': raise Forbidden("Object name begins with an underscore at: %s" % URL) subobject = UseTraversalDefault # indicator try: if hasattr(object, '__bobo_traverse__'): try: subobject = object.__bobo_traverse__(request, name) if isinstance(subobject, tuple) and len(subobject) > 1: # Add additional parents into the path # XXX There are no tests for this: request['PARENTS'][-1:] = list(subobject[:-1]) object, subobject = subobject[-2:] except (AttributeError, KeyError, NotFound) as e: # Try to find a view subobject = queryMultiAdapter((object, request), Interface, name) if subobject is not None: # OFS.Application.__bobo_traverse__ calls # REQUEST.RESPONSE.notFoundError which sets the HTTP # status code to 404 request.response.setStatus(200) # We don't need to do the docstring security check # for views, so lets skip it and # return the object here. if IAcquirer.providedBy(subobject): subobject = subobject.__of__(object) return subobject # No view found. Reraise the error # raised by __bobo_traverse__ raise e except UseTraversalDefault: pass if subobject is UseTraversalDefault: # No __bobo_traverse__ or default traversal requested # Try with an unacquired attribute: if hasattr(aq_base(object), name): subobject = getattr(object, name) else: # We try to fall back to a view: subobject = queryMultiAdapter((object, request), Interface, name) if subobject is not None: if IAcquirer.providedBy(subobject): subobject = subobject.__of__(object) return subobject # And lastly, of there is no view, try acquired attributes, but # only if there is no __bobo_traverse__: try: subobject = getattr(object, name) # Again, clear any error status created by # __bobo_traverse__ because we actually found something: request.response.setStatus(200) except AttributeError: pass # Lastly we try with key access: if subobject is None: try: subobject = object[name] except TypeError: # unsubscriptable raise KeyError(name) # Ensure that the object has a docstring, or that the parent # object has a pseudo-docstring for the object. Objects that # have an empty or missing docstring are not published. doc = getattr(subobject, '__doc__', None) if not doc: raise Forbidden("The object at %s has an empty or missing " "docstring. Objects must have a docstring to be " "published." % URL) # Check that built-in types aren't publishable. if not typeCheck(subobject): raise Forbidden("The object at %s is not publishable." % URL) return subobject