User macro question
Asked by Rumceisz:

Hi,

I have to refine the code because I see the problem:

I would like to get macro for each space which lists all the groups in the space which has VIEWSPACE right but doesn't have ADMIN right (we use 2 types of groups: one has view only rights the other has admin rights). Members of the groups also listed.

This macro could then embedded by all space admins to their own pages.

First define the space we examine:

\<p\>The following users and groups have permission to administer the \<strong\>$space.getName()\</strong\> Space.\</p\>

then I'd like to get all the groups that has the space (at least VIESPACE permission):

#foreach ($groups in $space.getGroups()) - this is not velocity but I don't have a clue!

and then collect all the groups whivh has only VIESPACE right in this space:

if PERMISSION of the group == VIEWSPACE and PERMISSION of the group NOT EQUAL SETSPACEPERMISSIONS)

....

Can you please help?

Thanks in advance!

Rumi


Answers:
author: Andrew Frayling
body: DISCLAIMER: This works, but is hideous, if anyone has a better way of doing this please post it.

Finally got something that works and de-duplicates.

```
## Macro title: Group Permissions## Macro has a body: Y or N (N)## Body processing: Selected body processing option## Output: Selected output option#### Developed by: Andrew Frayling## Date created: 21/05/2012## Installed by: &lt;your name&gt;## Macro loops through every group and every space listings permissions on that space grouped by group## @noparams## get all the spaces#set ( $allSpaces = $spaceManager.getAllSpaces() )## create an array to hold unique groups#set ( $uniqueGroups = [] )## create an array to hold unique users#set ( $uniqueUsers = [] )  &lt;h1&gt;$space.getName()&lt;/h1&gt;  &lt;h2&gt;Groups&lt;/h2&gt;  &lt;h3&gt;Administrators&lt;/h3&gt;  &lt;ul&gt;  #foreach ($permission in $space.getPermissions())    ## check for groups that are admins    #if($permission.isGroupPermission() &amp;&amp; $permission.getType() == "SETSPACEPERMISSIONS")      ## add the group to the uniqueGroups array      ## $added is an ugly hack to stop Velocity outputting boolean value      #set ( $added = $uniqueGroups.add($permission.getGroup()) )      &lt;li&gt;$permission.getGroup()&lt;/li&gt;    #end  #end  &lt;/ul&gt;    &lt;h3&gt;Developers&lt;/h3&gt;  &lt;ul&gt;  #foreach ($permission in $space.getPermissions())    ## check for groups that are developers    ## assumes all developer groups can comment    #if($permission.isGroupPermission() &amp;&amp; $permission.getType() == "COMMENT")      ## check if the group has already been counted as an admin      #set ( $exists = false )      #foreach($group in $uniqueGroups)        #if($group == $permission.getGroup())          #set ( $exists = true )          #break        #end      #end      ## if it hasn't been added as an admin, then add it      #if(!$exists)        #set ( $added = $uniqueGroups.add($permission.getGroup()) )        &lt;li&gt;$permission.getGroup()&lt;/li&gt;      #end    #end  #end  &lt;/ul&gt;    &lt;h3&gt;Viewers&lt;/h3&gt;  &lt;ul&gt;  #foreach ($permission in $space.getPermissions())    ## check for groups that can view only    ## assumes all developer groups can view    #if($permission.isGroupPermission() &amp;&amp; $permission.getType() == "VIEWSPACE")      ## check if the group has already been counted as an admin or a developer      #set ( $exists = false )      #foreach($group in $uniqueGroups)        #if($group == $permission.getGroup())          #set ( $exists = true )          #break        #end      #end      ## if it hasn't been added as an admin, then add it      #if(!$exists)        #set ( $added = $uniqueGroups.add($permission.getGroup()) )        &lt;li&gt;$permission.getGroup()&lt;/li&gt;      #end    #end  #end  &lt;/ul&gt;    ## now do it all again, but for users  &lt;h2&gt;Users&lt;/h2&gt;  &lt;h3&gt;Administrators&lt;/h3&gt;  &lt;ul&gt;  #foreach ($permission in $space.getPermissions())    ## check for users that are admins    #if($permission.isUserPermission() &amp;&amp; $permission.getType() == "SETSPACEPERMISSIONS")      ## add the user to the uniqueUsers array      ## $added is an ugly hack to stop Velocity outputting boolean value      #set ( $added = $uniqueUsers.add($permission.getUserName()) )      &lt;li&gt;#usernameLink($permission.getUserName())&lt;/li&gt;    #end  #end  &lt;/ul&gt;    &lt;h3&gt;Developers&lt;/h3&gt;  &lt;ul&gt;  #foreach ($permission in $space.getPermissions())    ## check for users that are developers    ## assumes all developer users can comment    #if($permission.isUserPermission() &amp;&amp; $permission.getType() == "COMMENT")      ## check if the user has already been counted as an admin      #set ( $exists = false )      #foreach($user in $uniqueUsers)        #if($user == $permission.getUserName())          #set ( $exists = true )          #break        #end      #end      ## if it hasn't been added as an admin, then add it      #if(!$exists)        #set ( $added = $uniqueUsers.add($permission.getUserName()) )        &lt;li&gt;#usernameLink($permission.getUserName())&lt;/li&gt;      #end    #end  #end  &lt;/ul&gt;    &lt;h3&gt;Viewers&lt;/h3&gt;  &lt;ul&gt;  #foreach ($permission in $space.getPermissions())    ## check for users that are developers    ## assumes all developer users can comment    #if($permission.isUserPermission() &amp;&amp; $permission.getType() == "VIEWSPACE")      ## check if the user has already been counted as an admin      #set ( $exists = false )      #foreach($user in $uniqueUsers)        #if($user == $permission.getUserName())          #set ( $exists = true )          #break        #end      #end      ## if it hasn't been added as an admin or a developer, then add it      #if(!$exists)        #set ( $added = $uniqueUsers.add($permission.getUserName()) )        &lt;li&gt;#usernameLink($permission.getUserName())&lt;/li&gt;      #end    #end  #end  &lt;/ul&gt;
```

It works for the current space rather than looping through all the spaces and creates arrays to hold groups and users that it has already evaluated as being admins, developers, etc. so it doesn't repeat them for subsequent checks. The ordering of the loops is important as it works on decreasing permissions and assumes that someone with a higher permission also has a lower permission. E.g. I assume admin is the highest permission so test for that first, if a group or a user has the admin permission it is assumed that they also have the comment permission so they get discounted when it tests for comments so they are not duplicated. Anyone found having the comment permission is assumed to also have the view permission, so they are discounted when testing for the view permission. If you need to tweak it to test for other permissions you need to use the same inherited permissions assumptions, e.g. if you want to test for who can add pages you need to decide if it is safe to assume that everyone can add could also comment, therefore you test for add first and discount before you check for the comment permission.

As mentioned it's a hideous way of doing it and if someone knows a better way of doing it you should do it that way instead.

Andrew.

comments: author: Rumceisz
body: Hi Andrew,

it is perfect!!!!

Thank you very much!

Can I simply insert the member of group line?

```
#set ( $memberList = $userAccessor.getMemberNamesAsList($groupObject) )
```

Thanks again!

Rumi


author: Rumceisz
body: Hi Andrew,

I defined the group members and I get the list of the members of the group. But I'd like to get it in a more esthatic table like yours. I only get in a row (see attached pic).![](../../upfiles/group_members.jpg)


author: Andrew Frayling
body: Hi Rumi,

Once you've got your memberlist you need to loop through them with something like:

```
&lt;table class="confluenceTable"&gt;      &lt;tr&gt;        &lt;th class="confluenceTh"&gt;Members&lt;/th&gt;      &lt;/tr&gt;      #foreach ($member in $memberList)        &lt;tr&gt;          &lt;td class="confluenceTd"&gt;#usernameLink($member)&lt;/td&gt;        &lt;/tr&gt;      #end&lt;/table&gt;
```

Andrew.


author: Nic Brough -Adaptavist-
body: You're right on the != being "not equals", and your logic looks fine to me.

But I don't think $permission.getType() returns a string, I think it returns an object, which you need to transform into a string. Even then, Velocity treats the objects it gets from the application as objects, and in Java, you can't actually say "if StringX == StringY", you have to say "if StringX.equals(StringY)".

I'd try this instead, but bear in mind that I don't know that the toString is right, you may want .getName or something like that:

$permission.getType().toString().equals("VIEWSPACE")

comments: author: Rumceisz
body: Hi Nic,

the script I posted above works fine. It was written by Andrew Ferling earlier. My only request is to make 2 sections: viewonly groups with members and admin groups with members.


author: Andrew Frayling
body: Hi Rumi,

I am still looking at this just not got there yet :-)

The abstract logic you're applying to remove duplicates is fine, but I don't think the implementation path you're using is going to work as when you're looping through permissions you're dealing with something that looks like:

```
[VIEWSPACE,65537,confluence-administrators,null][VIEWSPACE,65537,confluence-users,null][VIEWSPACE,65537,null,null][COMMENT,65537,confluence-administrators,null][COMMENT,65537,confluence-users,null][COMMENT,65537,null,null][EDITSPACE,65537,confluence-administrators,null][EDITSPACE,65537,confluence-users,null][EDITSPACE,65537,null,null]
```

so the groups are duplicated for each permission and, for example, "confluence-administrators" will be listed for both SETSPACEPERMISSIONS and (VIEWSPACE not SETSPACEPERMISSIONS) because there would be 2 permissions that would both evaluate to true.

Off the top of my head it needs additional logic to flag that a group has already been accounted for in a previous permission set.

Andrew.


author: Rumceisz
body: Hi Andrew,

in the meantime I realized that I can't implement the NOT EQUAL statement in your code because your code cycle examines all the permissions one by one.

What is the code you implemented above?

Regards,

Rumi


author: Andrew Frayling
body: Hi Rumi,

To generate the above I just used:

```
## get all the spaces#set ( $allSpaces = $spaceManager.getAllSpaces() )&lt;h1&gt;Spaces&lt;/h1&gt;#foreach ($space in $allSpaces)  &lt;h2&gt;$space.getName()&lt;/h2&gt;  #foreach ($permission in $space.getPermissions())    $permission&lt;br /&gt;  #end#end
```

Looping through the permissions is a pain, but I haven't found any other way of doing it. There's a $permissionHelper which lets you do things like $permissionHelper.canView() , $permissionHelper.canComment(), etc. which would make things easier, but it's only available for users, not groups.

I could still be missing something in the API, but as far as I can tell to do what you want you have to find all the spaces, then find all the permissions on the space, then find which of those are group permissions and which groups those permissions belong to, then de-duplicate and then list the groups. I haven't found anything that lets you take a group object and a space object and do a direct evaluation of the permissions it has.

Andrew.


author: Rumceisz
body: Hi Andrew,

I guess you misread my question: the macro I' d like to implement is much more simplier: the space is given, hence this user macro would be inserted by the space admins.

So the space is given and I would collect all the groups related to this particular space. And then I would make 2 sections:

1. Groups and group members that have only view permission

2. Groups and group members that have admin permission.

This is very-very close to your origonal code above, and you suggested to simply double the code above for the 2 permission types. But only one problem left you mentioned already: the VIEWSPACE section also has the admin groups too.

So that's all.

The start-up was this code: <http://blog.networkedcollaboration.com/2012/04/28/>

Rumi


author: Andrew Frayling
body: Ah, ok. To be honest the spaces aren't the complexity, the de-duplicating is.

Probably a silly question, but if the space is a given why can't the space admins just visit http://\<CONFLUENCE_URL\>/spaces/spacepermissions.action?key=\<SPACE_KEY\> as that would show them all the groups and the permissions they have on the space?

Is it because you want non-admins to be able to see the permissions?

Andrew.


author: Rumceisz
body: Hi Andrew,

you're right: it was requested by different team members (not only space admins) that they would like to see all the groups accessed to the space and first of all the members of the groups!

Do you think this re-duplicating is very difficult?

Actually we use 3 types of groups (according to our grouping stenders): admins with all permissions, developers with comment, blog, attachment and restrictions permissions and view-only group.

So there is no need - I guess - to difficult de-duplicating feature: only extend the if statement: "if group permission = VIEWSPACE and group permission \<\> COMMENT"

Sorry, I only can develop visual basic, I don't know the Velocity syntax.

Rumi


author: Andrew Frayling
body: The de-duplicating shouldn't be hard, but my brain is obviously not working properly at the moment :-)

I'm fairly certain that the approach of "if permission = VIEW and permission \<\> COMMENT" is not going to work because it will still match admins and developers multiple times. It would need to mark all the admin groups that it's already flagged as admins so it didn't list them again when it wanted the list of developers or viewers.

When I initially said to just duplicate the permission check I'll admit I just glanced at it and didn't think it through, but I'm now seeng it's more involved than I thought.

I still think it's do-able, just not in the way I'd first thought.

Andrew.


author: Rumceisz
body: Hi,

I have to refine the code because I see the problem:

I would like to get macro for each space which lists all the groups in the space which has VIEWSPACE right but doesn't have ADMIN right (we use 2 types of groups: one has view only rights the other has admin rights). Members of the groups also listed.

This macro could then embedded by all space admins to their own pages.

First define the space we examine:

\<p\>The following users and groups have permission to administer the \<strong\>$space.getName()\</strong\> Space.\</p\>

then I'd like to get all the groups that has the space (at least VIESPACE permission):

#foreach ($groups in $space.getGroups()) - this is not velocity but I don't have a clue!

and then collect all the groups whivh has only VIESPACE right in this space:

if PERMISSION of the group == VIEWSPACE and PERMISSION of the group NOT EQUAL SETSPACEPERMISSIONS)

....

Can you please help?

Thanks in advance!

Rumi


author: Sandro Herrmann [Communardo]
body: have you tried

```
!$permission.getType().equals("SETSPACEPERMISSIONS")
```

comments: author: Rumceisz
body: Hi Sandro,

I tried but it doesn't work: it lists the admin groups henceforward.

Maybe the beginning of the script is wrong: I guess it doesn't examine the groups but the permissions one by one:

```
&lt;h1&gt;Space readers&lt;/h1&gt;&lt;p&gt;The following groups has only permission to view the &lt;strong&gt;$space.getName()&lt;/strong&gt; Space.&lt;/p&gt;&lt;h2&gt;Groups&lt;/h2&gt;#foreach ($permission in $space.getPermissions())   ? here we should have: groups in space(?)  #if ($permission.isGroupPermission() &amp;&amp; $permission.getType() == "VIEWSPACE" &amp;&amp; !$permission.getType().equals("SETSPACEPERMISSIONS"))    #set ( $groupString = $permission.getGroup() )    #set ( $groupObject = $userAccessor.getGroup($groupString) )    #set ( $memberList = $userAccessor.getMemberNamesAsList($groupObject) )    &lt;h3&gt;$groupString&lt;/h3&gt;    &lt;table class="confluenceTable"&gt;      &lt;tr&gt;        &lt;th class="confluenceTh"&gt;Space Administrators&lt;/th&gt;      &lt;/tr&gt;      #foreach ($member in $memberList)        &lt;tr&gt;          &lt;td class="confluenceTd"&gt;#usernameLink($member)&lt;/td&gt;        &lt;/tr&gt;      #end    &lt;/table&gt;  #end#end
```


Tags: macro

velocity