Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

How to determine fully shareable status of a ContentEntityObject?

I currently have an in-house Confluence EventListener add-on that sends content from Confluence ContentEvents to our DevOps Kafka bus.  However, we have found that content marked in the UI as Private (or otherwise "not shared") is happily sent to the Listener and we happily send the private content to the Kafka bus for everyone to see. :(

All the references I've seen seem to focus on "does a specific user have permission".  However, we need the filter to answer the question "is this shared with EVERYONE", and I have not found an ALL_USERS constant.

Currently, I'm experimenting down a trial-and-error path of something like:

boolean isShared(ContentEntityObject content){

    return ((content.sharedAccessAllowed((String)null)) &&
            (content.sharedAccessAllowed((User)null))  &&
            (!content.hasContentPermissions()));
}

But some documentation suggests restrictive permissions from the Ancestry of the content (parent Pages or Space) are not provided in the List of ContentPermissions provided for the specific instance of content?

Is there more information available for identifying only fully shared content that has no restrictions whatsoever?  Or, more precisely, that a specific piece of content (Page, Blog, Comment) has no restriction on it--including inherited restrictions/permission?

1 answer

1 accepted

This is what seems to have worked for me.  The following restrictions are filtered and NOT sent to Kafka (or any external destination):

  • User UNSELECTS Notify Watchers
  • Confluence otherwise sets Suppress Notifications
  • Page/Blog is not yet "Published"
  • Page/Blog has ANY View Restrictions
  • Page/Blog Ancestry has ANY View Restrictions
  • Space itself has View Restrictions
  • Comments on ANY View restricted Page/Blog are also restricted

This method is called by recursePermissions to determine if the Space itself is Shared or not.  Experimentaiont with Space Tools uncovered an issue which is corrected in 'sharedSpacePermissions' below:

 private boolean sharedSpacePermission(Space space){
final String ALL_USERS = "confluence-users";
if(space.getPermissions() != null){
for(SpacePermission permission:space.getPermissions()){
// if VIEW permission is for Group 'confluence-users' it is a Shareable Space
if((SpacePermission.VIEWSPACE_PERMISSION.equalsIgnoreCase(permission.getType())) &&
(ALL_USERS.equals(permission.getGroup())))
return true; }
log.debug("*** Space has no 'confluence-users' VIEW permission so it should not be shared! ");
}else{
log.warn("??? Unexpected case of Space not defining ANY permissions. It is not shared. ???");
}
return false;
}

 And recursePermissions handles the recursive ancestry check for permissions:

 private boolean recursePermissions(ContentEntityObject content){
final boolean shared = true;
String type = content.getClass().getSimpleName();

if(content.hasPermissions(ContentPermission.VIEW_PERMISSION)){
log.debug("*** The "+ type +" contains a VIEW restriction and should not be shared! ");
return !shared;
}
// a Restricted page might have no ContentPermissions--but its Parent Containers WILL!
if(content instanceof Comment){
if(((Comment)content).getContainer() != null){
if(!recursePermissions(((Comment)content).getContainer())) return !shared;
}else{
log.warn("??? Unexpected case of a Comment outside of a Container ???");
}
}else if(content instanceof Page){
if(((Page)content).getParent() != null){
if(!recursePermissions(((Page)content).getParent())) return !shared;
}else if(((Page)content).getSpace() != null){
if(!sharedSpacePermission(((Page)content).getSpace())) return !shared;
}else{
log.warn("??? Unexpected case of a Page having no parent Page or Space ???");
}
}else if(content instanceof BlogPost){
if(((BlogPost)content).getSpace() != null){
if(!sharedSpacePermission(((BlogPost)content).getSpace())) return !shared;
}else{
log.warn("??? Unexpected case of a BlogPost having no parent Space ???");
}
}else{
log.warn("\n\n\n??? Unexpected "+ type +" not being processed for permissions ???\n\n\n");
}
log.debug("*** The "+ type +" did not contain any VIEW restrictions...");
return shared;
}

And to kick it all off, we first check for suppressed notifications and the like.  This is the entry point for the overall "is it shareable" check:

 private boolean isShared(ContentEvent event){ 
final boolean shared = true;
ContentEntityObject content = event.getContent();
if(content.isUnpublished()){
log.debug("*** The content has not yet been published!");
return !shared;
}
if(event.isSuppressNotifications()){
log.debug("*** The event SUPPRESSED notifications!");
return !shared;
}
if(!content.sharedAccessAllowed((User)null)){
log.debug("*** The content.sharedAccessAllowed((User)null) is NOT shareable! ");
return !shared;
}
return recursePermissions(content);
}

     

Suggest an answer

Log in or Sign up to answer
TAGS
Community showcase
Published in Confluence

Confluence Mythbusters: Does Atlassian even use Confluence?

Hi, Confluence collaborators! As part of #Confluence-Collaboratory month, we’ve created a very special Mythsbusters segment, where we're dive into an interesting myth and uncover the truth behind i...

1,384 views 7 29
Read article

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you