← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 9830: Limit access to certain programs by userrole.

 

------------------------------------------------------------
revno: 9830
committer: Tran Chau <tran.hispvietnam@xxxxxxxxx>
branch nick: dhis2
timestamp: Tue 2013-02-19 13:54:22 +0700
message:
  Limit access to certain programs by userrole.
added:
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/DefineProgramUserroleAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/ShowProgramUserroleFormAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/images/userrole.png
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/programUserrole.vm
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/Program.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramService.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramStore.java
  dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/DefaultProgramService.java
  dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/hibernate/HibernateProgramStore.java
  dhis-2/dhis-services/dhis-service-patient/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-services/dhis-service-patient/src/main/resources/org/hisp/dhis/program/hibernate/Program.hbm.xml
  dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/DataRecordingSelectAction.java
  dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/GetProgramsByOrgunitAction.java
  dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/GetSingleEventProgramListAction.java
  dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/LoadAnonymousProgramsAction.java
  dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/MultiDataEntrySelectAction.java
  dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/ProgramEnrollmentSelectAction.java
  dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/SelectAction.java
  dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/report/ReportSelectAction.java
  dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/report/TabularInitializeAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/org/hisp/dhis/patient/i18n_module.properties
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/struts.xml
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/programList.vm


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/Program.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/Program.java	2013-02-14 09:02:07 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/Program.java	2013-02-19 06:54:22 +0000
@@ -42,8 +42,11 @@
 import org.hisp.dhis.patient.Patient;
 import org.hisp.dhis.patient.PatientAttribute;
 import org.hisp.dhis.patient.PatientIdentifierType;
+import org.hisp.dhis.user.UserAuthorityGroup;
+import org.hisp.dhis.user.comparator.UserRoleComparator;
 import org.hisp.dhis.validation.ValidationCriteria;
 
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -106,6 +109,8 @@
 
     private Boolean blockEntryForm = false;
 
+    private Set<UserAuthorityGroup> userRoles = new HashSet<UserAuthorityGroup>();
+
     // -------------------------------------------------------------------------
     // Constructors
     // -------------------------------------------------------------------------
@@ -446,4 +451,15 @@
     {
         return type != null && (SINGLE_EVENT_WITH_REGISTRATION == type || MULTIPLE_EVENTS_WITH_REGISTRATION == type);
     }
+
+    public Set<UserAuthorityGroup> getUserRoles()
+    {
+        return userRoles;
+    }
+
+    public void setUserRoles( Set<UserAuthorityGroup> userRoles )
+    {
+        this.userRoles = userRoles;
+    }
+
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramService.java	2012-05-23 15:02:50 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramService.java	2013-02-19 06:54:22 +0000
@@ -53,6 +53,8 @@
     Collection<Program> getAllPrograms();
 
     Collection<Program> getPrograms( OrganisationUnit organisationUnit );
+    
+    Collection<Program> getProgramsByCurrentUser();
 
     Collection<Program> getPrograms( ValidationCriteria validationCriteria );
 

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramStore.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramStore.java	2013-01-07 05:07:05 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramStore.java	2013-02-19 06:54:22 +0000
@@ -45,4 +45,6 @@
     Collection<Program> getByType( int type );
     
     Collection<Program> get( int type, OrganisationUnit orgunit );
+    
+    Collection<Program> getByCurrentUser();
 }

=== modified file 'dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/DefaultProgramService.java'
--- dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/DefaultProgramService.java	2013-01-28 05:28:45 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/DefaultProgramService.java	2013-02-19 06:54:22 +0000
@@ -138,4 +138,9 @@
         return i18n( i18nService, programStore.get( type, orgunit ) );
     }
 
+    public Collection<Program> getProgramsByCurrentUser()
+    {
+        return i18n( i18nService, programStore.getByCurrentUser() );
+    }
+    
 }

=== modified file 'dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/hibernate/HibernateProgramStore.java'
--- dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/hibernate/HibernateProgramStore.java	2013-01-07 05:07:05 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/hibernate/HibernateProgramStore.java	2013-02-19 06:54:22 +0000
@@ -28,12 +28,18 @@
 package org.hisp.dhis.program.hibernate;
 
 import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
 
 import org.hibernate.criterion.Restrictions;
 import org.hisp.dhis.common.hibernate.HibernateIdentifiableObjectStore;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.program.Program;
 import org.hisp.dhis.program.ProgramStore;
+import org.hisp.dhis.system.util.CollectionUtils;
+import org.hisp.dhis.user.CurrentUserService;
+import org.hisp.dhis.user.UserAuthorityGroup;
+import org.hisp.dhis.user.UserService;
 
 /**
  * @author Chau Thu Tran
@@ -44,6 +50,28 @@
     extends HibernateIdentifiableObjectStore<Program>
     implements ProgramStore
 {
+    // -------------------------------------------------------------------------
+    // Dependency
+    // -------------------------------------------------------------------------
+
+    private CurrentUserService currentUserService;
+
+    public void setCurrentUserService( CurrentUserService currentUserService )
+    {
+        this.currentUserService = currentUserService;
+    }
+
+    private UserService userService;
+
+    public void setUserService( UserService userService )
+    {
+        this.userService = userService;
+    }
+
+    // -------------------------------------------------------------------------
+    // Implemented methods
+    // -------------------------------------------------------------------------
+
     @SuppressWarnings( "unchecked" )
     @Override
     public Collection<Program> getByType( int type )
@@ -56,7 +84,32 @@
     public Collection<Program> get( int type, OrganisationUnit organisationUnit )
     {
         final String hql = "from Program p where p.type = :type and :organisationUnit in elements(p.organisationUnits)";
-        
+
         return getQuery( hql ).setInteger( "type", type ).setEntity( "organisationUnit", organisationUnit ).list();
     }
+
+    @Override
+    public Collection<Program> getByCurrentUser()
+    {
+        Collection<Program> programs = new HashSet<Program>();
+
+        if ( !currentUserService.currentUserIsSuper() )
+        {
+            Set<UserAuthorityGroup> userRoles = userService.getUserCredentials( currentUserService.getCurrentUser() )
+                .getUserAuthorityGroups();
+            
+            for ( Program program : getAll() )
+            {
+                if ( CollectionUtils.intersection( program.getUserRoles(), userRoles ).size() > 0 )
+                {
+                    programs.add( program );
+                }
+            }
+        }
+        else
+        {
+            programs = getAll();
+        }
+        return programs;
+    }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-patient/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-services/dhis-service-patient/src/main/resources/META-INF/dhis/beans.xml	2013-02-18 03:04:47 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/resources/META-INF/dhis/beans.xml	2013-02-19 06:54:22 +0000
@@ -57,6 +57,8 @@
 	<bean id="org.hisp.dhis.program.ProgramStore" class="org.hisp.dhis.program.hibernate.HibernateProgramStore">
 		<property name="clazz" value="org.hisp.dhis.program.Program" />
 		<property name="sessionFactory" ref="sessionFactory" />
+		<property name="userService" ref="org.hisp.dhis.user.UserService" />
+		<property name="currentUserService" ref="org.hisp.dhis.user.CurrentUserService" />
 	</bean>
 
 	<bean id="org.hisp.dhis.program.ProgramValidationStore"

=== modified file 'dhis-2/dhis-services/dhis-service-patient/src/main/resources/org/hisp/dhis/program/hibernate/Program.hbm.xml'
--- dhis-2/dhis-services/dhis-service-patient/src/main/resources/org/hisp/dhis/program/hibernate/Program.hbm.xml	2013-02-07 10:25:34 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/resources/org/hisp/dhis/program/hibernate/Program.hbm.xml	2013-02-19 06:54:22 +0000
@@ -66,5 +66,11 @@
 
     <property name="blockEntryForm" />
 
+	<set name="userRoles" table="program_userroles">
+		<key column="programid" />
+		<many-to-many class="org.hisp.dhis.user.UserAuthorityGroup"
+			column="userroleid" foreign-key="fk_program_userroles"/>
+	</set>
+		
   </class>
 </hibernate-mapping>

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/DataRecordingSelectAction.java'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/DataRecordingSelectAction.java	2012-09-03 19:53:34 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/DataRecordingSelectAction.java	2013-02-19 06:54:22 +0000
@@ -111,11 +111,9 @@
         // ---------------------------------------------------------------------
 
         programs = programService.getPrograms( orgunit );
-
         programs.retainAll( patient.getPrograms() );
-
-        programs.addAll( programService.getPrograms( Program.SINGLE_EVENT_WITH_REGISTRATION, orgunit ) );
-
+        programs.retainAll( programService.getProgramsByCurrentUser());
+        
         selectedStateManager.setSelectedPatient( patient );
 
         return SUCCESS;

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/GetProgramsByOrgunitAction.java'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/GetProgramsByOrgunitAction.java	2012-09-03 19:53:34 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/GetProgramsByOrgunitAction.java	2013-02-19 06:54:22 +0000
@@ -93,8 +93,8 @@
         if ( organisationUnit != null )
         {
             programs = programService.getPrograms( organisationUnit );
-            Collection<Program> anonymousPrograms = programService.getPrograms( Program.SINGLE_EVENT_WITHOUT_REGISTRATION, organisationUnit );
-            programs.removeAll( anonymousPrograms );
+            programs.retainAll( programService.getProgramsByCurrentUser());
+            programs.removeAll( programService.getPrograms( Program.SINGLE_EVENT_WITHOUT_REGISTRATION, organisationUnit ) );
         }
         
         selectedStateManager.clearSelectedPatient();

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/GetSingleEventProgramListAction.java'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/GetSingleEventProgramListAction.java	2012-09-03 19:53:34 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/GetSingleEventProgramListAction.java	2013-02-19 06:54:22 +0000
@@ -85,6 +85,7 @@
         if ( orgunit != null )
         {
             programs = programService.getPrograms( Program.SINGLE_EVENT_WITH_REGISTRATION, orgunit );
+            programs.retainAll( programService.getProgramsByCurrentUser());
         }
         
         return SUCCESS;

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/LoadAnonymousProgramsAction.java'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/LoadAnonymousProgramsAction.java	2013-01-30 02:38:51 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/LoadAnonymousProgramsAction.java	2013-02-19 06:54:22 +0000
@@ -112,6 +112,8 @@
         {
             programs = new ArrayList<Program>( programService.getPrograms( Program.SINGLE_EVENT_WITHOUT_REGISTRATION,
                 orgunit ) );
+            programs.retainAll( programService.getProgramsByCurrentUser());
+            
             Collections.sort( programs, new ProgramDisplayNameComparator() );
         }
 

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/MultiDataEntrySelectAction.java'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/MultiDataEntrySelectAction.java	2012-09-03 19:53:34 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/MultiDataEntrySelectAction.java	2013-02-19 06:54:22 +0000
@@ -118,8 +118,8 @@
         if ( organisationUnit != null )
         {
             programs = programService.getPrograms( organisationUnit );
-            Collection<Program> anonymousPrograms = programService.getPrograms( Program.SINGLE_EVENT_WITHOUT_REGISTRATION, organisationUnit );
-            programs.removeAll( anonymousPrograms );
+            programs.retainAll( programService.getProgramsByCurrentUser());
+            programs.removeAll( programService.getPrograms( Program.SINGLE_EVENT_WITHOUT_REGISTRATION, organisationUnit ) );
         }
         
         return SUCCESS;

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/ProgramEnrollmentSelectAction.java'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/ProgramEnrollmentSelectAction.java	2012-11-23 03:02:35 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/ProgramEnrollmentSelectAction.java	2013-02-19 06:54:22 +0000
@@ -111,16 +111,15 @@
     public String execute()
         throws Exception
     {
+        OrganisationUnit orgunit = selectedStateManager.getSelectedOrganisationUnit();
         patient = patientService.getPatient( id );
 
         // Get all programs
         programs = programService.getPrograms( Program.MULTIPLE_EVENTS_WITH_REGISTRATION );
-
-        // Check single-event with registration
-        OrganisationUnit orgunit = selectedStateManager.getSelectedOrganisationUnit();
-
         programs.addAll( programService.getPrograms( Program.SINGLE_EVENT_WITH_REGISTRATION, orgunit ) );
+        programs.retainAll( programService.getProgramsByCurrentUser());
         programs.removeAll( patient.getPrograms() );
+        
         Collection<ProgramInstance> programInstances = programInstanceService.getProgramInstances( patient, false );
 
         for ( ProgramInstance programInstance : programInstances )

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/SelectAction.java'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/SelectAction.java	2013-01-30 02:38:51 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/SelectAction.java	2013-02-19 06:54:22 +0000
@@ -115,8 +115,8 @@
     {
         patientAttributes = patientAttributeService.getAllPatientAttributes();
 
-        programs = new ArrayList<Program>( programService.getPrograms( Program.MULTIPLE_EVENTS_WITH_REGISTRATION ) );
-        programs.addAll( programService.getPrograms( Program.SINGLE_EVENT_WITH_REGISTRATION ) );
+        programs = new ArrayList<Program>(programService.getProgramsByCurrentUser());
+        programs.removeAll( programService.getPrograms( Program.SINGLE_EVENT_WITHOUT_REGISTRATION ) );
         
         Collections.sort( programs, new ProgramDisplayNameComparator() );
 

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/report/ReportSelectAction.java'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/report/ReportSelectAction.java	2012-10-06 15:55:56 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/report/ReportSelectAction.java	2013-02-19 06:54:22 +0000
@@ -87,10 +87,8 @@
     {
         orgunit = selectionManager.getSelectedOrganisationUnit();
         
-        programs = programService.getAllPrograms();
-        
-        programs.removeAll( programService.getPrograms( Program.SINGLE_EVENT_WITH_REGISTRATION ) );
-        programs.removeAll( programService.getPrograms( Program.SINGLE_EVENT_WITHOUT_REGISTRATION ) );
+        programs = programService.getPrograms( Program.MULTIPLE_EVENTS_WITH_REGISTRATION );
+        programs.retainAll( programService.getProgramsByCurrentUser());
 
         return SUCCESS;
     }

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/report/TabularInitializeAction.java'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/report/TabularInitializeAction.java	2012-11-07 14:52:49 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/report/TabularInitializeAction.java	2013-02-19 06:54:22 +0000
@@ -112,7 +112,8 @@
         Collections.sort( orgunitGroups, IdentifiableObjectNameComparator.INSTANCE );
         
         programs = programService.getAllPrograms();
-
+        programs.retainAll( programService.getProgramsByCurrentUser());
+        
         levels = organisationUnitService.getOrganisationUnitLevels();
 
         return SUCCESS;

=== added file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/DefineProgramUserroleAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/DefineProgramUserroleAction.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/DefineProgramUserroleAction.java	2013-02-19 06:54:22 +0000
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2004-2009, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the HISP project nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.hisp.dhis.patient.action.program;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.hisp.dhis.program.Program;
+import org.hisp.dhis.program.ProgramService;
+import org.hisp.dhis.user.UserAuthorityGroup;
+import org.hisp.dhis.user.UserService;
+
+import com.opensymphony.xwork2.Action;
+
+/**
+ * @author Chau Thu Tran
+ * 
+ * @version DefineProgramUserroleAction.java 12:43:40 PM Feb 19, 2013 $
+ */
+public class DefineProgramUserroleAction
+    implements Action
+{// -------------------------------------------------------------------------
+ // Dependency
+ // -------------------------------------------------------------------------
+
+    private ProgramService programService;
+
+    public void setProgramService( ProgramService programService )
+    {
+        this.programService = programService;
+    }
+
+    private UserService userService;
+
+    public void setUserService( UserService userService )
+    {
+        this.userService = userService;
+    }
+
+    // -------------------------------------------------------------------------
+    // Input
+    // -------------------------------------------------------------------------
+
+    private Integer id;
+
+    public void setId( Integer id )
+    {
+        this.id = id;
+    }
+
+    private Collection<Integer> userRoleIds = new HashSet<Integer>();
+
+    public void setUserRoleIds( Collection<Integer> userRoleIds )
+    {
+        this.userRoleIds = userRoleIds;
+    }
+
+    // -------------------------------------------------------------------------
+    // Action implementation
+    // -------------------------------------------------------------------------
+
+    @Override
+    public String execute()
+        throws Exception
+    {
+        Program program = programService.getProgram( id );
+
+        Set<UserAuthorityGroup> userAutorities = new HashSet<UserAuthorityGroup>();
+
+        for ( Integer userRoleId : this.userRoleIds )
+        {
+            userAutorities.add( userService.getUserAuthorityGroup( userRoleId ) );
+        }
+
+        program.setUserRoles( userAutorities );
+
+        programService.updateProgram( program );
+
+        return SUCCESS;
+    }
+
+}

=== added file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/ShowProgramUserroleFormAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/ShowProgramUserroleFormAction.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/ShowProgramUserroleFormAction.java	2013-02-19 06:54:22 +0000
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2004-2009, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the HISP project nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.hisp.dhis.patient.action.program;
+
+import java.util.Collection;
+
+import org.hisp.dhis.program.Program;
+import org.hisp.dhis.program.ProgramService;
+import org.hisp.dhis.user.UserAuthorityGroup;
+import org.hisp.dhis.user.UserService;
+
+import com.opensymphony.xwork2.Action;
+
+/**
+ * @author Chau Thu Tran
+ * 
+ * @version ShowProgramUserroleFormAction.java 12:44:19 PM Feb 19, 2013 $
+ */
+public class ShowProgramUserroleFormAction
+    implements Action
+{
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+    
+    private UserService userService;
+
+    public void setUserService( UserService userService )
+    {
+        this.userService = userService;
+    }
+
+    private ProgramService programService;
+
+    public void setProgramService( ProgramService programService )
+    {
+        this.programService = programService;
+    }
+
+    // -------------------------------------------------------------------------
+    // Input/output
+    // -------------------------------------------------------------------------
+
+    private Integer id;
+
+    public void setId( Integer id )
+    {
+        this.id = id;
+    }
+
+    private Collection<UserAuthorityGroup> userRoles;
+
+    public Collection<UserAuthorityGroup> getUserRoles()
+    {
+        return userRoles;
+    }
+
+    private Program program;
+
+    public Program getProgram()
+    {
+        return program;
+    }
+
+    // -------------------------------------------------------------------------
+    // Action implementation
+    // -------------------------------------------------------------------------
+
+    @Override
+    public String execute()
+    {
+        program = programService.getProgram( id );
+
+        userRoles = userService.getAllUserAuthorityGroups();
+        userRoles.removeAll( program.getUserRoles() );
+
+        return SUCCESS;
+    }
+
+}

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/META-INF/dhis/beans.xml	2013-02-07 13:44:38 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/META-INF/dhis/beans.xml	2013-02-19 06:54:22 +0000
@@ -238,6 +238,20 @@
 		scope="prototype">
 		<property name="programService" ref="org.hisp.dhis.program.ProgramService" />
 	</bean>
+	
+	<bean id="org.hisp.dhis.patient.action.program.ShowProgramUserroleFormAction"
+		class="org.hisp.dhis.patient.action.program.ShowProgramUserroleFormAction"
+		scope="prototype">
+		<property name="userService" ref="org.hisp.dhis.user.UserService" />
+		<property name="programService" ref="org.hisp.dhis.program.ProgramService" />
+	</bean>
+	
+	<bean id="org.hisp.dhis.patient.action.program.DefineProgramUserroleAction"
+		class="org.hisp.dhis.patient.action.program.DefineProgramUserroleAction"
+		scope="prototype">
+		<property name="userService" ref="org.hisp.dhis.user.UserService" />
+		<property name="programService" ref="org.hisp.dhis.program.ProgramService" />
+	</bean>
 
 	<!-- Program_OrganisationUnit Association -->
 

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/org/hisp/dhis/patient/i18n_module.properties'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/org/hisp/dhis/patient/i18n_module.properties	2013-02-07 13:44:38 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/org/hisp/dhis/patient/i18n_module.properties	2013-02-19 06:54:22 +0000
@@ -350,4 +350,5 @@
 data_element_for_sum_avg = Data element for sum/average 
 avg_dataelement_value = Average of data element values
 min_dataelement_value = Mininum of data element values
-max_dataelement_value = Maximun of data element values
\ No newline at end of file
+max_dataelement_value = Maximun of data element values
+assign_program_to_userroles = Assign program to userroles
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/struts.xml'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/struts.xml	2013-02-04 03:09:04 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/struts.xml	2013-02-19 06:54:22 +0000
@@ -275,6 +275,20 @@
 			<param name="onExceptionReturn">plainTextError</param>
 		</action>
 
+		<action name="showProgramUserroleForm"
+			class="org.hisp.dhis.patient.action.program.ShowProgramUserroleFormAction">
+			<result name="success" type="velocity">/main.vm</result>
+			<param name="page">/dhis-web-maintenance-patient/programUserrole.vm</param>
+			<param name="javascripts">javascript/program.js</param>
+			<param name="stylesheets">style/basic.css</param>
+			<param name="requiredAuthorities">F_PROGRAM_ADD</param>
+		</action>
+
+		<action name="defineProgramUserrole"
+			class="org.hisp.dhis.patient.action.program.DefineProgramUserroleAction">
+			<result name="success" type="redirect">program.action</result>
+		</action>
+
 		<!-- Program_OrganisationUnit Association -->
 
 		<action name="defineProgramAssociationsForm"

=== added file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/images/userrole.png'
Binary files dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/images/userrole.png	1970-01-01 00:00:00 +0000 and dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/images/userrole.png	2013-02-19 06:54:22 +0000 differ
=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/programList.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/programList.vm	2013-01-23 10:27:28 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/programList.vm	2013-02-19 06:54:22 +0000
@@ -9,7 +9,7 @@
 		
 		<table class="listTable" id="listTable">
 			  <col>          
-			  <col width="200">
+			  <col width="230">
 			<thead>			  
 			  <tr>            
 				<th>$i18n.getString( "name" )</th>
@@ -24,6 +24,7 @@
 					
 					<td style="text-align:center">
 					  <a href="defineProgramAssociationsForm.action?id=$program.id" title="$i18n.getString( 'assign_program_to_orgunits' )"><img src="../images/assign.png" alt="$i18n.getString( 'assign_program_to_orgunits' )"></a>					  
+					  <a href="showProgramUserroleForm.action?id=$program.id" title="$i18n.getString( 'assign_program_to_userroles' )"><img src="images/userrole.png" alt="$i18n.getString( 'assign_program_to_userroles' )"></a>					  
 					  <a href="programValidation.action?programId=$program.id" title="$i18n.getString( 'program_validation_rule_management' )"><img src="../images/assign_b.png" alt="$i18n.getString( 'program_validation_rule_management' )"></a>					  
 					  <a href="showUpdateProgramForm.action?id=$program.id" title="$i18n.getString( 'edit' )"><img src="../images/edit.png" alt="$i18n.getString( 'edit' )"></a>
 					  <a href="javascript:translate( 'Program', '$program.id' )" title="$i18n.getString( 'translation_translate' )"><img src="../images/i18n.png" alt="$i18n.getString( 'translation_translate' )"/></a>

=== added file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/programUserrole.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/programUserrole.vm	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/programUserrole.vm	2013-02-19 06:54:22 +0000
@@ -0,0 +1,44 @@
+<h3>$i18n.getString( "assign_program_to_userroles" )</h3>
+
+<h4>$program.displayName</h4>
+
+<form name="userRole" action="defineProgramUserrole.action" method="POST" onsubmit="selectAllById( 'selectedList' );">
+<input type="hidden" name="id" value="$program.id"/>
+<table>
+	<tr>
+		<th>$i18n.getString( "available" )</th>
+		<td></td>
+		<th>$i18n.getString( "selected" )</th>
+	</tr>
+	<tr>
+		<td>
+			 <select size="15" id="availableList" name="availableList" multiple="multiple" style="min-width:20em;height:20em" ondblclick="moveSelectedById( 'availableList', 'userRoleIds' )">
+            #foreach ( $userRole in $userRoles )
+              <option value="$userRole.id">$encoder.htmlEncode( $userRole.name )</option>
+            #end
+          </select>
+		</td>
+		<td>
+			<input type="button" value="&lt;" title="$i18n.getString('remove_selected')" onclick="moveSelectedById( 'userRoleIds', 'availableList' )" class="filterButton" /><br/>
+			<input type="button" value="&gt;" title="$i18n.getString('move_selected')" onclick="moveSelectedById( 'availableList', 'userRoleIds' )" class="filterButton" />
+		</td>
+		<td>
+			<select id="userRoleIds" name="userRoleIds" multiple="multiple" style="min-width:20em;height:20em" ondblclick="moveSelectedById( 'userRoleIds', 'availableList' )">
+			#foreach ( $userRole in $program.userRoles )
+              <option value="$userRole.id">$encoder.htmlEncode( $userRole.name )</option>
+            #end
+			</select>
+        </td>
+	</tr>
+</table>
+<br>
+<input type="submit" value="$i18n.getString( 'ok' )" style="width:100px"/>
+<input type="button" value="$i18n.getString( 'cancel' )"  style="width:100px" onclick="window.location = 'program.action'"/>
+</form>
+
+<script>
+	$(document).ready(function(){
+		sortList('availableList', 'ASC');
+		sortList('selectedList', 'ASC');
+	});
+</script>
\ No newline at end of file