It's all about the answers!

Ask a question

precondition: restrict assigning roles for team members


Martin Wassermann (13863444) | asked Jun 24 '14, 9:58 a.m.
 Hello 

I want to write a precondition that restrict assigning of some roles to specific roles. We want that e.g. only a team member with the role "Administrator" can assign the role "Administrator" to other team members. All other roles should not be restricted.

But how can I identify which change was done when the precondition for "SaveTeamArea" is run? If I use getActions() on the AdvisableOperation argument I got only the String "modify/members". And getOperationData returns "null".

Is there a way e.g. with the history to identify which roles has be added or removed?

Thanks and regards
Martin

Comments
1
sam detweiler commented Jun 24 '14, 10:32 a.m.

I don't believe there is history for team area changes.

I'm not aware of any before/after capabilty on anything other than workitems
altho the getprocessarea/getsecondaryprocessarea might be how to get it.

what does operation.getSecondaryActions(operation.getProcessArea()) return.



Martin Wassermann commented Jun 30 '14, 2:58 a.m. | edited Jun 30 '14, 2:59 a.m.

 Unfortunately "operation.getSecondaryActions(operation.getProcessArea())" returns an empty String array. 


Do you see any other option to identify which changes was done for the "save team area" operation?


sam detweiler commented Jun 30 '14, 8:45 a.m.

I do not know any more about this. I have never seen any history or change info team areas or project areas other than the process config source.

Accepted answer


permanent link
sam detweiler (12.4k6172200) | answered Jul 28 '14, 5:59 p.m.
this code works, shows the proposed new roles for members. I haven't figured out how to load the existing PA data.


in a participant (too far after the fact).. the getSaveditems()[0] has the new data. while getItems()[0] has the old data

        Object objData = operation;
        if (operation instanceof ProjectAreaSaveOperation)
        {   
            ProjectAreaSaveOperation data = (ProjectAreaSaveOperation) objData;          
            List<String> actions = Arrays.asList(data.getActions());
            if (actions.contains(ProjectAreaSaveOperation.ACTION_MODIFY_MEMBERS))
            {
                if(fcontributorService==null)
                {
                    IContributorService fcontributorService= getService(IContributorService.class);
                    fItemService = getService(IRepositoryItemService.class);
                }
                System.out.println("in modify members");
                IProjectArea pa = (IProjectArea) data.getItems()[0];
                IContributorHandle members[] = pa.getMembers();
                for(IContributorHandle member: members)
                {
                    IContributor user = (IContributor) fItemService.fetchItem(member, (new String[]{IContributor.NAME_PROPERTY,IContributor.DETAILS_PROPERTY}));
                    System.out.println("user name="+user.getName());
                    String[] roles = RolePersistence.getRoleIds(RolePersistence.getPersistentRoleData(pa.getTeamData(), user));
                    for(String role:roles)
                    {
                        System.out.println("\t role="+role);
                    }
                }
Martin Wassermann selected this answer as the correct answer

Comments
Martin Wassermann commented Jul 29 '14, 7:38 a.m.
in a participant (too far after the fact).. the getSaveditems()[0] has the new data. while getItems()[0] has the old data 

but data.getSavedItems()[0]; returns a 

java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 0
So there with this solution there is the same problem as in my solution. I didn't get the new data. Or did it work for you with data.getSavedItems()[0]?


1
sam detweiler commented Jul 29 '14, 7:46 a.m.

there are two different solutions..

in an Advisor, you get the NEW data, and have to LOAD the old data for the project area to compare against

in a Participant, you get BOTH the old and the new, least I do.


Martin Wassermann commented Jul 29 '14, 8:18 a.m.

Many thanks Sam for your support. Now it work's. 


Getting the old data can simply be done with 
IProcessArea oldProcess = (IProcessArea) repositoryService.fetchItem( newProcess.getItemHandle(), null);


sam detweiler commented Jul 29 '14, 8:32 a.m.

had to post another 'answer' to hold the full sample. see my comment there about using the itemhandle

2 other answers



permanent link
Martin Wassermann (13863444) | answered Jul 21 '14, 9:35 a.m.
edited Jul 21 '14, 9:37 a.m.
I have found a solution for the saveTeamArea operation. With
IProcessArea newProcess = operation.getProcessArea();
I can get the working copy of the user, and compare it the the actual process
IProcessArea oldProcess = (IProcessArea) repositoryService.fetchItem( newProcess.getItemHandle(), null);
After that I can compare the members of the oldProcess and the newProcess.

But If I try the same with the saveProjectArea operation I have a problem, because 
operation.getProcessArea();
returns not the working copy in the saveProjectArea operation but the original. Therefore I did not see the changes the user has made. 

Is there a way to get the working copy of the user that save the project area?

Comments
sam detweiler commented Jul 21 '14, 10:52 a.m.

get the contributor service ( add it as a pre-req to the plugin.xml)

    private static IContributorService fcontributorService = null;
            fcontributorService = getService(IContributorService.class);

then the extension is running in the context of the user making the change
            on the AbstractService class the  extension is part of

            getAuthenticatedContributor()

will get u the users handle, then use the service..


Ralph Schoon commented Jul 21 '14, 11:03 a.m.
FORUM ADMINISTRATOR / FORUM MODERATOR / JAZZ DEVELOPER

Some examples of the roles API also on my blog. E.g. https://rsjazz.wordpress.com/2013/06/26/attribute-customization-java-based-value-providers-conditions-and-validators/

Once you have the above, you could go deeper into the roles.


Martin Wassermann commented Jul 22 '14, 1:38 a.m.

Sorry, I write my question unclear. I did not need the working copy of the user - I need the working copy of the project area that the authenticated user has changed. (and exactly the working copy that contains the changes of the authenticated user)


The operation getProcesssArea in the precondition did not return the working copy that the authenticated user has changed when he press save. Therefore I don'T know how I should get the changed the user has made to the project area. 

Did you know I can get this information?


sam detweiler commented Jul 22 '14, 8:26 a.m.

ah.. because you are in a pre-condition no changes have been made yet.

but you should be able ot get the list of users in the teamarea/project area,
and get their role data

RolePersistence.getPersistentRoleData(teamarea_area.getTeamData(), user_handle);

my guess is that the old/new process data will point to different data.
I haven't done this is a plugin.
but you will have to loop thru each user, get their role data on both old/new process areas and compare lists.


Martin Wassermann commented Jul 22 '14, 9:49 a.m. | edited Jul 22 '14, 9:55 a.m.

Right, and this works perfect for the operation saveTeamArea


But if I want to use the same for saveProjectArea, oldProcess and newProcess points to the same data. So I can't get the "changed version" to compare with the original one.

So for the operation saveTeamArea my precondition works fine. But not for saveProjectArea because I can't fetch the changed version (the working copy)


sam detweiler commented Jul 22 '14, 10:21 a.m.

don't you get a teamarea save for the project area, when you don't change the process config?

I don't see the save project area extension point in the default list.


Martin Wassermann commented Jul 23 '14, 7:19 a.m.

Unfortunately it is a saveProjectArea operation if you change the members of the project area.

In Web the editor you dont see this operation for precondition but there is an operation for it (see https://jazz.net/wiki/bin/view/Main/CustomPreconditionsLandingSite)


sam detweiler commented Jul 23 '14, 8:08 a.m.

I don't see that operation listed except in the 'data passed'  table.
"The following table gives the data types of the operation data"

you should not get the processarea (working copy), as you should HAVE the process area already.
and as u are not changing it (pre-conditions don't change), the other apis against it would work ok.


Martin Wassermann commented Jul 23 '14, 9:11 a.m.

And that's the problem. I don't have the the process area that contains the changes. For  the operation saveTeamArea I get the process area that CONTAINS the changed by calling
    operation.getProcessArea();
But if I try the same with the operation saveProjectArea I receive the process area WITHOUT the changes. Therefore I can't check if the changes are correct.


sam detweiler commented Jul 23 '14, 9:30 a.m.

ok, sorry, without debugging this myself, I don't have any other answer..


sam detweiler commented Jul 23 '14, 10:36 a.m.

can u show me how you configured you advisor?  
(cut/paste the xml from eclipse project source view)
as I don't see it.


Martin Wassermann commented Jul 28 '14, 3:23 a.m.
 The configuration is very similar to saveTeamArea, but inside the behavior of the project.configuration.

<project-configuration>
  .........
  <behavior>
    <role id="default">
    ...... 
      <project-operation id="com.ibm.team.process.server.saveProjectArea">
      <preconditions>
        <precondition
          id="com.company.jazz.extension.service.restrictassignofroles" 
          name="Restrict Assign of Roles"/>
        </preconditions>
      </project-operation>
   </role>
  </behavior>
</project-configuration>

sam detweiler commented Jul 28 '14, 8:32 a.m. | edited Jul 28 '14, 9:24 a.m.

thanks.. one more thing.. I am getting ''Save Project Area' failed. Preconditions have not been met: The advisor com.sd.tools.SaveProjectArea.advisor is not valid for the operation com.ibm.team.process.server.saveProjectArea.'

and my class def is
public class ProjectAreaSaveAdvisor extends AbstractService implements IOperationAdvisor

running on a 4.0.3 server. compiled against the 4.0.3 sdk.

showing 5 of 13 show 8 more comments

permanent link
sam detweiler (12.4k6172200) | answered Jul 29 '14, 8:31 a.m.
cool.. and sadly, in the SaveProjectArea operation data there is a field fPreviousItems
which holds the data you seek, but there is no method to get it.

I was concerned with using the projectArea handle provided in the advisor to load the pre-change data, as it was provided by the advisor..

so I did this

                URI srcuri = URI.create(pa.getName().replaceAll(" ", "%20"));
                IProcessArea projectArea = fProcessServerService.findProcessArea(srcuri.toString(), null);


full sample

package com.sd.tools;

import java.net.URI;
import java.util.Arrays;
import java.util.List;

import org.eclipse.core.runtime.IProgressMonitor;

import com.ibm.team.process.common.IDevelopmentLine;
import com.ibm.team.process.common.IProcessArea;
import com.ibm.team.process.common.IProcessConfigurationElement;
import com.ibm.team.process.common.IProjectArea;
import com.ibm.team.process.common.advice.AdvisableOperation;
import com.ibm.team.process.common.advice.IAdvisorInfo;
import com.ibm.team.process.common.advice.IAdvisorInfoCollector;
import com.ibm.team.process.common.advice.runtime.IOperationAdvisor;
import com.ibm.team.process.common.advice.runtime.IOperationParticipant;
import com.ibm.team.process.common.advice.runtime.IParticipantInfoCollector;
import com.ibm.team.process.internal.common.RolePersistence;
import com.ibm.team.process.internal.service.ProjectAreaSaveOperation;
import com.ibm.team.process.service.IProcessServerService;
import com.ibm.team.repository.common.IContributor;
import com.ibm.team.repository.common.IContributorHandle;
import com.ibm.team.repository.common.TeamRepositoryException;
import com.ibm.team.repository.common.service.IContributorService;
import com.ibm.team.repository.service.AbstractService;
import com.ibm.team.repository.service.IRepositoryItemService;

public class ProjectAreaSaveAdvisor extends AbstractService implements IOperationAdvisor
{
    IContributorService fcontributorService = null;
    IRepositoryItemService fItemService = null;
    IProcessServerService fProcessServerService = null;
    public ProjectAreaSaveAdvisor()   
    {
        System.out.println("in project save constructor");
    }

    @SuppressWarnings("restriction")
    public void run(AdvisableOperation operation,
            IProcessConfigurationElement participantConfig,
            IAdvisorInfoCollector collector, IProgressMonitor monitor)
            throws TeamRepositoryException   
    {
        Object objData = operation;
        if (operation instanceof ProjectAreaSaveOperation)
        {   
            ProjectAreaSaveOperation data = (ProjectAreaSaveOperation) objData;          
            List<String> actions = Arrays.asList(data.getActions());
            if (actions.contains(ProjectAreaSaveOperation.ACTION_MODIFY_MEMBERS))
            {
                if(fcontributorService==null)
                {
                    IContributorService fcontributorService= getService(IContributorService.class);
                    fItemService = getService(IRepositoryItemService.class);
                    fProcessServerService = getService(IProcessServerService.class);                   
                }
                System.out.println("in modify members");
                //
                IProjectArea pa = (IProjectArea) data.getItems()[0];
                IContributorHandle members[] = pa.getMembers();
                for(IContributorHandle member: members)
                {
                    IContributor user = (IContributor) fItemService.fetchItem(member, (new String[]{IContributor.NAME_PROPERTY,IContributor.DETAILS_PROPERTY}));
                    System.out.println("user name="+user.getName());
                    String[] roles = RolePersistence.getRoleIds(RolePersistence.getPersistentRoleData(pa.getTeamData(), user));
                    for(String role:roles)
                    {
                        System.out.println("\t role="+role);
                    }
                }
               
                // use this if in an Advisor                
                // get the old data           
                URI srcuri = URI.create(pa.getName().replaceAll(" ", "%20"));
                IProcessArea projectArea = fProcessServerService.findProcessArea(srcuri.toString(), null);
               
                // use this if in a participant               
                // gets the new data (post save)
                // projectArea = (IProjectArea) data.getSavedItems()[0];
               
                // get the list of members
                members = projectArea.getMembers();
                System.out.println(" old info");
                for(IContributorHandle member: members)
                {
                    IContributor user = (IContributor) fItemService.fetchItem(member, (new String[]{IContributor.NAME_PROPERTY,IContributor.DETAILS_PROPERTY}));
                    System.out.println("user name="+user.getName());
                    String[] roles = RolePersistence.getRoleIds(RolePersistence.getPersistentRoleData(projectArea.getTeamData(), user));
                    for(String role:roles)
                    {
                        System.out.println("\t role="+role);
                    }
                }                               
            }
        }           
    }
}


Your answer


Register or to post your answer.