This page last changed on Oct 29, 2006 by ivan@atlassian.com.

Cannot resolve external resource into attachment. How do I tell if a user has permission to...?

When you're writing a Confluence plugin, it's important to check that the user has permission to do the operations your plugin is performing. Confluence does not enforce security for you, it's up to your code to perform these checks.

There are two places you might want to check permissions:

In Java Code:

You will need:

  1. the User object of the user whose permissions you want to check (How do I find the logged in user?)
  2. the permissionManager component from Spring (How do I get a reference to a component?)

The PermissionManager has quite a few methods (Javadoc), but the most important are:

/**
     * Determine whether a user has a particular permission against a given target.
     *
     * @param user the user seeking permission, or null if the anonymous user is being checked against
     * @param permission the permission to check
     * @param target the object that the permission is being checked against. If this object is null, the method
     *        will return false
     * @return true if the user has this permission, false otherwise
     * @throws IllegalStateException if the permission being checked against does not apply to the target
     */
    boolean hasPermission(User user, Permission permission, Object target);

    /**
     * Determine whether a user has permission to create an entity of a particular type within a given container.
     *
     * <p>The container is the natural container of the object being created. For example, a comment is contained
     * in a page, which is contained within TARGET_APPLICATION.
     *
     * @param user the user seeking permission, or null if the anonymous user is being checked against
     * @param container the target that the object is being created within. If this object is null, the method
     *        will return false
     * @param typeToCreate the type of object being created (see above)
     * @return true if the user has permission, false otherwise
     * @see com.atlassian.confluence.core.ContentEntityObject#getType()
     * @throws IllegalStateException if the permission being checked against does not apply to the target
     */
    boolean hasCreatePermission(User user, Object container, Class typeToCreate);

Simple Permissions

Generally you're going to be asking the question: "Does some user have permission to do something to some target?" For example: "Does BOB have permission to VIEW this PAGE?", "Does JANE have permission to REMOVE this ATTACHMENT?" These questions map to the hasPermission() method above.

The various values of "something" are all constants of the Permission class listed in this Javadoc. At the time this document was written, the permission 'verbs' are:

Permission.VIEW
    Permission.EDIT
    Permission.EXPORT
    Permission.REMOVE
    Permission.SET_PERMISSIONS
    Permission.ADMINISTER

So to check if your user has permission to edit a particular page, the call is:

permissionManager.hasPermission(myUser, Permission.EDIT, thePage)

For global permissions, the 'target object' is considered to be the Confluence application itself. There is a special target, TARGET_APPLICATION that represents the application as a whole. So to check if someone is a global administrator, call:

permissionManager.hasPermission(myUser, Permission.ADMINISTER, PermissionManager.TARGET_APPLICATION

Create Permissions

Checking if someone has the ability to create an object (page, blogpost, space, etc) is a little more complicated. Every object is created inside some other object. Comments and Attachments are created inside Pages or BlogPosts. Pages are created inside Spaces. And Spaces are crated inside TARGET_APPLICATION.

So to check if someone can create something, the question is: "Does this user have permission to create this KIND OF OBJECT, in this CONTAINER?" In Java, kinds of objects are represented by their class, so to see if a user can create a comment inside a particular page, you'd call:

permissionManager.hasCreatePermission(myUser, containingPage, Comment.class)

And to check if the user has permission to create spaces globally:

permissionManager.asCreatePermission(myUser, PermissionManager.TARGET_APPLICATION, Space.class)

In Velocity Templates

While all of the above is very powerful, it's a bit complicated to deal with in a Velocity file. There is an object in the default velocity context called $permissionHelper which has a bunch of useful methods on it. All the methods do pretty much what you'd expect them to do, so I'll just link to the Javadoc:

http://www.atlassian.com/software/confluence/docs/api/latest/com/atlassian/confluence/security/PermissionHelper.html

And give a simple example:

#if ($permissionHelper.canEdit($remoteUser, $action.page))
       <b>You have Edit Permission for this Page</b>
   #end

Hi,

Is there a listing of the default velocity context objects somewhere?
Using a User Macro, I can use the $action object to call

$action.RemoteUser

But that gives me 3 values all at once - user, email, fullName.

The only call that I can find that would return a single value correctly is the call to get email:

$action.RemoteUser.Email

But how do I only get a user's username?

Ultimately, I'd like to check if a user is in a particular group.
What other convenient objects and methods would allow me to check that?

None of these work:
$action.RemoteUser.Username
$action.RemoteUser.UserName
$action.RemoteUser.Login
$action.RemoteUser.LoginName
$action.RemoteUser.User.UserName
$action.RemoteUser.User.Username
$action.RemoteUser.User.Login
$action.RemoteUser.User.LoginName
$action.RemoteUser.User.UserName
$action.Username
$action.UserName
$action.User.Username
$action.User.UserName
$action.User.Login
$action.Login
$user
$user.Username
$user.UserName
$user.Login
$remoteUser
$remoteUser.Username
$remoteUser.UserName
$remoteUser.Login

Thanks for your help.
/max

Posted by umich at Oct 28, 2006 11:32

To get a user's username, use $action.remoteUser.name.

To check whether a user is a member of a group, you need to use the UserAccessor:

$userAccessor.hasMembership("confluence-users", $action.remoteUser.name))

You could implement a simple version of Adaptavist's {show-to} macro as a user macro "show-to-group" with a body:

#if ($userAccessor.hasMembership($param0, $action.remoteUser.name))
    $body
#end

Then in your page, use it like this:

{show-to-group:confluence-administrators}
The secret password is 'ketchup'.
{show-to-group}

The entire suite of objects available from user macros is included in the User Macros documentation.

Posted by mryall at Oct 30, 2006 18:03

While we would love to take credit for them, the show-to macro is part of the Visibility Plugin created by David Peterson.

Posted by dhardiker@adaptavist.com at Oct 31, 2006 03:56

Thanks for adding the additional info for $userAccessor ... could not have guessed it myself.

Can I nest another user macro within this user macro?
For example:

{show-to-group:confluence-administrators}
The secret password is '{passphrase}'.
{show-to-group}

Ultimately, I'd like to modify the parameter values sent to an RSS Feed Macro.

{rss:url=http://my-rss-feed-site.com?members-only={nested-macro}}

Looks like I need to set a local variable in the page? Is that possible?

Posted by umich at Nov 01, 2006 21:47

Sure you can do that - but know that anyone can just put {passphrase} into a page / comment / even their profile and have the password shown to them.

Posted by dhardiker@adaptavist.com at Nov 02, 2006 03:46

Sorry, I was using the fictitious passphrase macro as just an example. The real scenario involves the RSS Feed Macro.  I cannot subtitute  the url value -- in whole or partially. Basically, I want to augment what is fed to Confluence depending on the end user group membership. So how do you do local vars in a page?

Posted by umich at Nov 02, 2006 10:32
Document generated by Confluence on Mar 22, 2007 21:00