When adding a custom model to the Asset Framework, a String array of tag names is passed in via the updateEntry method of AssetEntryLocalServiceBaseImpl.
This method calls the method checkTags in AssetTagLocalServiceImpl to see if the passed-in tags are new and need to be added or if they already exist (and thus should be used instead of adding new ones).
The problem here is that when tags are added to the database, the names are first sanitized:
But the same is not done in checkTags. So if updateEntry was previously called with, say, the tag names "TAG1" and "TAG2", they will be stored in the database with names set to "tag1" and "tag2," respectively.
If updateEntry is called for a new asset with the same tag names "TAG1" and "TAG2," you would expect that no new tags would be attempted to be made but this is not the case. In checkTags, the fetchTag method is called using the unsanitized "TAG1" and "TAG2" string. Since they are not found in the database (the existing ones are "tag1" and "tag2"), the logic calls addTag. The method will then sanitize the names appropriately and attempt to add them. Since they already exist in the database, this throws a DuplicateTagException.
Steps to reproduce:
- Create a custom asset using the updateEntry method, passing in a String array containing the Strings "TAG1" and "TAG2"
- Create a second custom asset using the updateEntry method, using the same tag name array
The second asset is created using the existing tags in the database.
The second asset creation fails with a DuplicateTagException.
This can also be replicated with out-of-the-box asset-enabled entities through the UI:
- Create a new Basic Web Content, enter the string "TAG1" in the tag field and click Add. Publish the web content.
- Create a second Basic Web Content, enter the string "TAG1" in the tag field and click Add (do not use Select). Publish the web content.
The second web content is created successfully with the same tag.
The portal reports that an error occurred and does not add the web content.