Ticket #14266 (new Bug)

Opened 21 months ago

Last modified 21 months ago

Traversal failure in folderish content on name collision with a field

Reported by: seanupton Owned by: davisagli
Priority: minor Milestone: 4.x
Component: Dexterity Version: 4.3
Keywords: Cc:

Description (last modified by seanupton) (diff)

OFS.Traversable.unrestrictedTraverse() and ZPublisher.BaseRequest.DefaultPublishTraverse.publishTraverse() both favor getattr(obj, name) before trying obj.__getitem__(name).

This can have a side-effect I consider a user-facing defect in (at least) Dexterity-based folderish types: users are unable to traverse to newly added content when the id of the item they added collides with a field name on the folderish object. The item will appear in navigation and folder contents, but be inaccessible to work with, rename, or delete.

Steps to duplicate

(1) Create a folderish Dexterity type based on plone.dexterity.content.Container (in add-on or TTW). (2) Add a field called "contacts". (3) Add a content item of this type. (4) In that content item, add any content item with the title of "Contacts" -- the auto-generated shortname of "contacts" should have a collision with the field, but you would not know until... (5) Try to click into that content item from the navigation.

Workarounds

Write a custom traversal adapter ( example) or __bobo_traverse__ method.

Is this really a bug?

IMHO, yes, if a user can add content that they cannot then access. Either deny the user that ability to add that name, auto-choose a name that does not collide, or fix traversal to favor __getitem__ first. Moreover, you cannot rename or delete the item.

Scope

  • This may be more of an issue with Dexterity content than in Archetypes content, depending upon how fields are named. I suspect this is most likely to affect add-on authors, but may also affect plone.app.contenttypes for Plone 5.

Proposed solution(s)

I am unsure of the suitability of this, but have a hunch it will work; please comment if you have thoughts on it:

  • Modify plone.dexterity.browser.traversal.DexterityPublishTraverse.publishTraverse() to avoid deferring to DefaultPublishTraverse when the context provides IDexterityContainer and the name requested is in self.context.objectIds().
    • Instead obtain the object via self.context.get(name) and return it.

Change History

comment:1 Changed 21 months ago by seanupton

  • Keywords dexterity removed
  • Owner set to davisagli
  • Component changed from Unknown to Dexterity

comment:2 Changed 21 months ago by seanupton

  • Description modified (diff)

comment:3 Changed 21 months ago by seanupton

  • Description modified (diff)
Note: See TracTickets for help on using tickets.