This is the second post in the series around very fine grained access control permissions for work items and RTC SCM versionables. It explains how to set the access control permissions for work items.
See the problem description in the first post of the series
Related posts
The posts in this series are:
- Manage Access Control Permissions for Work Items and Versionables
- Setting Access Control Permissions for Work Items – this post
- Setting Access Control Permissions for SCM Versionables
- Setting Attributes for SCM Versionables
License
The post contains published code, so our lawyers reminded me to state that the code in this post is derived from examples from Jazz.net as well as the RTC SDK. The usage of code from that example source code is governed by this license. Therefore this code is governed by this license. I found a section relevant to source code at the and of the license. Please also remember, as stated in the disclaimer, that this code comes with the usual lack of promise or guarantee. Enjoy!
Just Starting With Extending RTC?
If you just get started with extending Rational Team Concert, or create API based automation, start with the post Learning To Fly: Getting Started with the RTC Java API’s and follow the linked resources.
You should be able to use the following code in this environment and get your own automation or extension working.
Compatibility
This code has been used with RTC 5.0.2 and is prepared to be used with RTC 6.0.x with no changes and it is pretty safe to assume, that the code will work with newer versions of RTC.
The code in this post uses common libraries/services that are available in the Plain Java Client, Eclipse client and Jazz Eclipse server API. If client or server API is used, this is stated.
Work Item Access Control Code
Now that we have all the rules and pieces together as explained in this post, lets have a look at the work item access control. Again, note, that work items can only have access groups and project areas set for access control in manual mode as shown in the image below.
To set the access context for work items, the interface IWorkItem provides the method
IWorkItem.setContextId(UUID contextId);
It should also be possible to set the internal attribute with the ID “contextId” also available as constant
IWorkItem.CONTEXT_ID_PROPERTY
in the IWorkItem interface.
Working With the UUID Representing the Access Context
How to find the objects we are interested in, is explained in this post.
To be able to set the access control context for work items, it is necessary to understand how to access the value that represents the access context of a process area (project or team area) or access group.
The common API provides this method to access the access context of an item:
com.ibm.team.repository.common.IAuditableHandle.getItemId()
This interface implements (through a number of intermediate interfaces) the interface IItemHandle, which defines the method getItemId() for all items. So strictly speaking the method is available as
com.ibm.team.repository.common.IItemHandle.getItemId()
This means, the access context can be accessed already from the item handle e.g. in case only a handle such as IProcessAreaHandle, IProjectAreaHandle, ITeamAreaHandle, IAccessGroupHandle or IContributorHanlde is available.
It is also available at all resolved IItems such as IProcessArea, IProjectArea, ITeamArea, IAccessGroup or IContributor as all these interfaces implement IItemHandle. In fact it is available on all IItems. Example code:
IProcessAreaHandle paHandle = ..... get the handle IProcessArea pa = ..... resolve the handle // These values are the same UUID paHandleContext1 = paHandle.getItemID(); UUID paHandleContext2 = pa.getItemID();
Note, that all items in RTC have an itemID like the one above and can be uniquely be identified by it. Other itemID’s are just not used as access context.
The return value is of the type
com.ibm.team.repository.common.UUID
The UUID is an object that uniquely identifies an item in the repository and can be used to recreate the item as well. The string representation shows up in several places, for example in OSLC links. To get the string representation use
com.ibm.team.repository.common.UUID.getUuidValue()
If it is necessary to recreate an UUID from the string representation as an example named contextIDString, use the method
UUID.valueOf(contextIDString)
This recreates the UUID of the object if the string is a valid string representation of a UUID.
This way, you have the choice to use the UUID or its string representation to set the access context of RTC work items.
Setting the WorkItem Access Context
Given the UUID provided by a project area or access group, it is possible to set the access context of a work item.
Although all the code to retrieve the access context is common code, the code to set the work items context differs on client and server.
In the Client API, use a WorkItemOperation like the code below.
/******************************************************************************* * Licensed Materials - Property of IBM * (c) Copyright IBM Corporation 2015. All Rights Reserved. * * Note to U.S. Government Users Restricted Rights: Use, duplication or * disclosure restricted by GSA ADP Schedule Contract with IBM Corp. *******************************************************************************/ package com.ibm.js.access.control.client; import org.eclipse.core.runtime.IProgressMonitor; import com.ibm.team.repository.common.TeamRepositoryException; import com.ibm.team.repository.common.UUID; import com.ibm.team.workitem.client.WorkItemOperation; import com.ibm.team.workitem.client.WorkItemWorkingCopy; import com.ibm.team.workitem.common.model.IWorkItem; import com.ibm.team.workitem.common.model.ItemProfile; /** * WorkItem Operation to set the access context for the work item. This is * client code only. * */ public class SetAccessControlOperation extends WorkItemOperation { private UUID fAccessContext; public SetAccessControlOperation(UUID accessContext, ItemProfile loadProfile) { super("Set Access Context", loadProfile); fAccessContext = accessContext; } @Override protected void execute(WorkItemWorkingCopy workingCopy, IProgressMonitor monitor) throws TeamRepositoryException { workingCopy.getWorkItem().setContextId(fAccessContext); } }
The operation can be called like this:
SetAccessControlOperation operation = new SetAccessControlOperation( UUID.valueOf(context), IWorkItem.FULL_PROFILE); operation.run(workItem, monitor);
Because the WorkItemOperation is not available in the server API, a save has to be performed manually like below.
// Set the work item visibility // Get the full state of the parent work item so we can edit it // and avoid stale data exceptions // Get the required service interfaces IWorkItemServer wiServer = getService(IWorkItemServer.class); IWorkItem fullItem = (IWorkItem) wiServer .getAuditableCommon() .resolveAuditable(workItem, IWorkItem.FULL_PROFILE, monitor) .getWorkingCopy(); // Set the context of the work item fullItem.setContextId(UUID.valueOf(context)); // Save the work item HashSet additionalParams = new HashSet(); additionalParams.add("WORK_ITEM_CONTEXT_CHANGE"); IStatus status = wiServer.saveWorkItem3(fullItem, null, null, additionalParams); if (!status.isOK()) { String parameter[] = new String[1]; parameter[0] = Integer.toString(fullItem.getId()); String description = NLS.bind( "Failed to save work item ''{0}''.", parameter); IReportInfo info = collector.createInfo( "WORK_ITEM_CONTEXT_CHANGE" + ": Error running the participant.", description); info.setSeverity(IProcessReport.ERROR); collector.addInfo(info); return; }
Please note, if this is performed in a participant/follow up action, it is important to send an additional save parameter like “WORK_ITEM_CONTEXT_CHANGE”. This protects the participants from causing a recursion ultimately crashing the server. The participant can protect itself to run again for the save it just performed by testing for the additional save parameter. If the parameter is detected, the participant knows it caused the save and should exit to prevent the recursion.
Please also note, that in some cases you might have a WorkItemWorkingCopy, instead of an IWorkItem. In these cases use a cast or the method getWorkItem() on the working copy to get the IWorkItem item to be able to set the context.
The examples above uses the string version of the UUID, however, it would have been possible to get the UUID directly from the IItem.
Getting the WorkItem Access Context
It is possible to get the access context of a work item, if the work item is accessible for read, by using IWorkItem.getContextId(). The resulting UUID can be used to get the related item.
Summary
This post explains how to set read access control for work items. The next post will explain the details around setting access control for SCM versionables.