diff --git a/src/python/dm/ds_web_service/api/experimentRestApi.py b/src/python/dm/ds_web_service/api/experimentRestApi.py
index e27fe46af138ed80cd6a1a439c5624dcbe2b9f71..78ff54e34fcf53fa5346da30fd958d1b73f76080 100755
--- a/src/python/dm/ds_web_service/api/experimentRestApi.py
+++ b/src/python/dm/ds_web_service/api/experimentRestApi.py
@@ -26,6 +26,14 @@ class ExperimentRestApi(DsRestApi):
         responseData = self.sendSessionRequest(url=url, method='GET')
         return self.toDmObjectList(responseData, Experiment)
 
+    @DsRestApi.execute
+    def getExperimentsByStation(self, stationName):
+        url = '%s/experimentsByStation/%s' % (self.getContextRoot(), stationName)
+        if not stationName:
+            raise InvalidRequest('Experiment station name must be provided.')
+        responseData = self.sendSessionRequest(url=url, method='GET')
+        return self.toDmObjectList(responseData, Experiment)
+
     @DsRestApi.execute
     def getExperimentByName(self, name):
         url = '%s/experimentsByName/%s' % (self.getContextRoot(), name)
@@ -36,7 +44,7 @@ class ExperimentRestApi(DsRestApi):
 
     @DsRestApi.execute
     def getExperimentById(self, id):
-        url = '%s/experiments/%s' % (self.getContextRoot(), id)
+        url = '%s/experimentsById/%s' % (self.getContextRoot(), id)
         if id is None:
             raise InvalidRequest('Experiment id must be provided.')
         responseDict = self.sendSessionRequest(url=url, method='GET')
@@ -70,14 +78,17 @@ class ExperimentRestApi(DsRestApi):
         return Experiment(responseDict)
 
     @DsRestApi.execute
-    def addExperiment(self, name, experimentTypeId, description, startDate, endDate):
+    def addExperiment(self, name, stationName, typeName, description, startDate, endDate):
         url = '%s/experiments' % (self.getContextRoot())
-        if name is None or not len(name):
+        if not name:
             raise InvalidRequest('Experiment name must be provided.')
         url += '?name=%s' % Encoder.encode(name)
-        if experimentTypeId is None:
-            raise InvalidRequest('Experiment type id must be provided.')
-        url += '&experimentTypeId=%s' % experimentTypeId
+        if not stationName:
+            raise InvalidRequest('Experiment station name must be provided.')
+        url += '&stationName=%s' % Encoder.encode(stationName)
+        if not typeName:
+            raise InvalidRequest('Experiment type must be provided.')
+        url += '&typeName=%s' % Encoder.encode(typeName)
         if description is not None:
             url += '&description=%s' % Encoder.encode(description)
         if startDate is not None:
diff --git a/src/python/dm/ds_web_service/api/userRestApi.py b/src/python/dm/ds_web_service/api/userRestApi.py
index 31f9bf52fcdb73b3fb6315aa4378722ccc871768..5834878f4dba5e3b6ee74a2c60e3e58502ec2de6 100755
--- a/src/python/dm/ds_web_service/api/userRestApi.py
+++ b/src/python/dm/ds_web_service/api/userRestApi.py
@@ -8,6 +8,7 @@ from dm.common.exceptions.dmException import DmException
 from dm.common.exceptions.invalidRequest import InvalidRequest
 from dm.common.objects.userInfo import UserInfo
 from dm.common.objects.userExperimentRole import UserExperimentRole
+from dm.common.objects.userSystemRole import UserSystemRole
 from dsRestApi import DsRestApi
 
 class UserRestApi(DsRestApi):
@@ -38,91 +39,50 @@ class UserRestApi(DsRestApi):
         return UserInfo(responseData)
 
     @DsRestApi.execute
-    def addUser(self, username, firstName, lastName, middleName, email, badge, globusUsername, description, password, isLocalUser, lastUpdate):
-        if username is None:
+    def addUserSystemRole(self, username, roleName, experimentStationName=None):
+        if not username:
             raise InvalidRequest('Username must be provided.')
-        if firstName is None:
-            raise InvalidRequest('firstName must be provided.')
-        if lastName is None:
-            raise InvalidRequest('lastName must be provided.')
-        url = '%s/users' % (self.getContextRoot())
-        url += '?username=%s' % username
-        url += '&firstName=%s' % Encoder.encode(firstName)
-        url += '&lastName=%s' % Encoder.encode(lastName)
-        if middleName:
-            url += '&middleName=%s' % Encoder.encode(middleName)
-        if email:
-            url += '&email=%s' % Encoder.encode(email)
-        if badge:
-            url += '&badge=%s' % Encoder.encode(badge)
-        if globusUsername:
-            url += '&globusUsername=%s' % Encoder.encode(globusUsername)
-        if description:
-            url += '&description=%s' % Encoder.encode(description)
-        if password:
-            url += '&password=%s' % Encoder.encode(password)
-        if isLocalUser:
-            url += '&isLocaUser=%s' % isLocalUser
-        if lastUpdate:
-            url += '&lastUpdate=%s' % Encoder.encode(str(lastUpdate))
+        if not roleName:
+            raise InvalidRequest('Role name must be provided.')
+        url = '%s/userSystemRoles/%s/%s' % (self.getContextRoot(), username, roleName)
+        if experimentStationName:
+            url += '?experimentStationName=%s' % (experimentStationName)
         responseData = self.sendSessionRequest(url=url, method='POST')
-        return UserInfo(responseData)
+        return UserSystemRole(responseData)
 
     @DsRestApi.execute
-    def updateUser(self, id, username, firstName, lastName, middleName, email, badge, globusUsername, description, password, isLocalUser, lastUpdate):
-        if id is None:
-            raise InvalidRequest('User id must be provided.')
-        url = ''
-        if username:
-            url += '&username=%s' % username
-        if firstName:
-            url += '&firstName=%s' % Encoder.encode(firstName)
-        if lastName:
-            url += '&lastName=%s' % Encoder.encode(lastName)
-        if middleName:
-            url += '&middleName=%s' % Encoder.encode(middleName)
-        if email:
-            url += '&email=%s' % Encoder.encode(email)
-        if badge:
-            url += '&badge=%s' % Encoder.encode(badge)
-        if globusUsername:
-            url += '&globusUsername=%s' % Encoder.encode(globusUsername)
-        if description:
-            url += '&description=%s' % Encoder.encode(description)
-        if password:
-            url += '&password=%s' % Encoder.encode(password)
-        if isLocalUser:
-            url += '&isLocaUser=%s' % isLocalUser
-        if lastUpdate:
-            url += '&lastUpdate=%s' % Encoder.encode(str(lastUpdate))
-        if not url:
-            raise InvalidRequest('No user attributes have been modified.')
-        # Remove first '&' character
-        url = '%s/users/%s?%s' % (self.getContextRoot(), id, url[1:])
-        responseData = self.sendSessionRequest(url=url, method='PUT')
-        return UserInfo(responseData)
+    def deleteUserSystemRole(self, username, roleName, experimentStationName=None):
+        if not username:
+            raise InvalidRequest('Username must be provided.')
+        if not roleName:
+            raise InvalidRequest('Role name must be provided.')
+        url = '%s/userSystemRoles/%s/%s' % (self.getContextRoot(), username, roleName)
+        if experimentStationName:
+            url += '?experimentStationName=%s' % (experimentStationName)
+        responseData = self.sendSessionRequest(url=url, method='DELETE')
+        return UserSystemRole(responseData)
 
     @DsRestApi.execute
-    def addUserExperimentRole(self, username, experimentName, roleName):
+    def addUserExperimentRole(self, username, roleName, experimentName):
         if not username:
             raise InvalidRequest('Username must be provided.')
         if not experimentName:
             raise InvalidRequest('Experiment name must be provided.')
         if not roleName:
             raise InvalidRequest('Role name must be provided.')
-        url = '%s/usersByExperiment/%s/%s/%s' % (self.getContextRoot(), username, experimentName, roleName)
+        url = '%s/userExperimentRoles/%s/%s/%s' % (self.getContextRoot(), username, roleName, experimentName)
         responseData = self.sendSessionRequest(url=url, method='POST')
         return UserExperimentRole(responseData)
 
     @DsRestApi.execute
-    def deleteUserExperimentRole(self, username, experimentName, roleName):
+    def deleteUserExperimentRole(self, username, roleName, experimentName):
         if not username:
             raise InvalidRequest('Username must be provided.')
         if not experimentName:
             raise InvalidRequest('Experiment name must be provided.')
         if not roleName:
             raise InvalidRequest('Role name must be provided.')
-        url = '%s/usersByExperiment/%s/%s/%s' % (self.getContextRoot(), username, experimentName, roleName)
+        url = '%s/userExperimentRoles/%s/%s/%s' % (self.getContextRoot(), username, roleName, experimentName)
         responseData = self.sendSessionRequest(url=url, method='DELETE')
         return UserExperimentRole(responseData)
 
diff --git a/src/python/dm/ds_web_service/cli/addExperimentCli.py b/src/python/dm/ds_web_service/cli/addExperimentCli.py
index 91a0dab5a9cd27d51ee224aad9c4392bf9e9e061..f509231d7b17a48b23177050927d6ebbad6627be 100755
--- a/src/python/dm/ds_web_service/cli/addExperimentCli.py
+++ b/src/python/dm/ds_web_service/cli/addExperimentCli.py
@@ -2,13 +2,23 @@
 
 from dm.ds_web_service.api.experimentRestApi import ExperimentRestApi
 from dm.common.exceptions.invalidRequest import InvalidRequest
+from dm.common.utility.configurationManager import ConfigurationManager
 from dsWebServiceSessionCli import DsWebServiceSessionCli
 
 class AddExperimentCli(DsWebServiceSessionCli):
     def __init__(self):
         DsWebServiceSessionCli.__init__(self)
+        configManager = ConfigurationManager.getInstance()
+        self.allowedExperimentTypes = configManager.getAllowedExperimentTypes()
+        allowedExperimentTypesHelp = ''
+        if self.allowedExperimentTypes:
+            allowedExperimentTypesHelp = ' Allowed types: %s' % self.allowedExperimentTypes
+            
+
         self.addOption('', '--experiment', dest='experimentName', help='Experiment name.')
-        self.addOption('', '--type-id', dest='typeId', help='Experiment type id.')
+        self.addOption('', '--station', dest='stationName', help='Experiment station name, can also be set via DM_STATION_NAME environment variable.')
+        self.addOption('', '--type', dest='typeName', help='Experiment type name.%s' % allowedExperimentTypesHelp)
+        self.addOption('', '--type-id', dest='typeId', help='Experiment type id (may be given instead of type name; type id is ignored if both type name and id are provided).')
         self.addOption('', '--description', dest='description', help='Experiment description.')
         self.addOption('', '--start-date', dest='startDate', help='Experiment start date in format DD-MMM-YY.')
         self.addOption('', '--end-date', dest='endDate', help='Experiment end date in format DD-MMM-YY.')
@@ -16,14 +26,34 @@ class AddExperimentCli(DsWebServiceSessionCli):
     def checkArgs(self):
         if self.options.experimentName is None:
             raise InvalidRequest('Experiment name must be provided.')
-        if self.options.typeId is None:
-            raise InvalidRequest('Experiment type id must be provided.')
+        if self.getTypeName() is None:
+            raise InvalidRequest('Experiment type name must be provided.')
+        if self.getStationName() is None:
+            raise InvalidRequest('Experiment station name must be provided.')
+        # If allowed experiment types is not set, there are no restrictions
+        if self.allowedExperimentTypes:
+            if self.getTypeName() not in self.allowedExperimentTypes.split(','):
+                raise InvalidRequest('Experiment type %s is not allowed on this station. Allowed types are: %s.' % (self.getTypeName(), self.allowedExperimentTypes))
 
     def getExperimentName(self):
         return self.options.experimentName
 
-    def getTypeId(self):
-        return self.options.typeId
+    def getStationName(self):
+        stationName = self.options.stationName
+        if not stationName:
+            configManager = ConfigurationManager.getInstance()
+            stationName = configManager.getStationName()
+        return stationName
+
+    def getTypeName(self):
+        typeName = self.options.typeName
+        if not typeName:
+            if self.options.typeId:
+                api = ExperimentRestApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol())
+                experimentType = api.getExperimentTypeById(typeId)
+                typeName = experimentType.get('name')
+                self.options.typeName = typeName
+        return typeName
 
     def getDescription(self):
         return self.options.description
@@ -36,7 +66,8 @@ class AddExperimentCli(DsWebServiceSessionCli):
 
     def runCommand(self):
         self.parseArgs(usage="""
-    dm-add-experiment --experiment=EXPERIMENTNAME --type-id=TYPEID
+    dm-add-experiment 
+        --experiment=EXPERIMENTNAME --station=STATIONNAME --type=TYPENAME|--type-id=TYPEID
         [--description=DESCRIPTION] 
         [--start-date=STARTDATE] 
         [--end-date=ENDDATE]
@@ -46,7 +77,7 @@ Description:
         """)
         self.checkArgs()
         api = ExperimentRestApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol())
-        experiment = api.addExperiment(self.getExperimentName(), self.getTypeId(), self.getDescription(), self.getStartDate(), self.getEndDate())
+        experiment = api.addExperiment(self.getExperimentName(), self.getStationName(), self.getTypeName(), self.getDescription(), self.getStartDate(), self.getEndDate())
         print experiment.getDisplayString(self.getDisplayKeys(), self.getDisplayFormat())
 
 #######################################################################
diff --git a/src/python/dm/ds_web_service/cli/addUserExperimentRoleCli.py b/src/python/dm/ds_web_service/cli/addUserExperimentRoleCli.py
index ff044163712828ffa602fd217e4164a6cdd39d37..be374b8cd11ff1d0f12a051f86032efea296a7cb 100755
--- a/src/python/dm/ds_web_service/cli/addUserExperimentRoleCli.py
+++ b/src/python/dm/ds_web_service/cli/addUserExperimentRoleCli.py
@@ -8,8 +8,8 @@ class AddUserExperimentRoleCli(DsWebServiceSessionCli):
     def __init__(self):
         DsWebServiceSessionCli.__init__(self)
         self.addOption('', '--username', dest='username', help='User username.')
+        self.addOption('', '--role', dest='roleName', help='Role name can be either \'PI\' or \'User\'.')
         self.addOption('', '--experiment', dest='experimentName', help='Experiment name.')
-        self.addOption('', '--role', dest='roleName', help='Role name.')
 
     def checkArgs(self):
         if not self.options.username:
@@ -30,15 +30,16 @@ class AddUserExperimentRoleCli(DsWebServiceSessionCli):
 
     def runCommand(self):
         self.parseArgs(usage="""
-    dm-add-user-experiment-role --username=USERNAME --experiment=EXPERIMENTNAME
+    dm-add-user-experiment-role --username=USERNAME 
         --role=ROLENAME
+        --experiment=EXPERIMENTNAME
 
 Description:
     Assigns experiment role to the given user.
         """)
         self.checkArgs()
         api = UserRestApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol())
-        userExperimentRole = api.addUserExperimentRole(self.getUsername(), self.getExperimentName(), self.getRoleName())
+        userExperimentRole = api.addUserExperimentRole(self.getUsername(), self.getRoleName(), self.getExperimentName())
         print userExperimentRole.getDisplayString(self.getDisplayKeys(), self.getDisplayFormat())
 
 #######################################################################
diff --git a/src/python/dm/ds_web_service/cli/addUserSystemRoleCli.py b/src/python/dm/ds_web_service/cli/addUserSystemRoleCli.py
new file mode 100755
index 0000000000000000000000000000000000000000..c42e62796d5079607cfa16673819e55d2522ec39
--- /dev/null
+++ b/src/python/dm/ds_web_service/cli/addUserSystemRoleCli.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+
+from dm.common.exceptions.invalidRequest import InvalidRequest
+from dm.ds_web_service.api.userRestApi import UserRestApi
+from dsWebServiceSessionCli import DsWebServiceSessionCli
+
+class AddUserSystemRoleCli(DsWebServiceSessionCli):
+    def __init__(self):
+        DsWebServiceSessionCli.__init__(self)
+        self.addOption('', '--username', dest='username', help='User username.')
+        self.addOption('', '--role', dest='roleName', help='Role name can be either \'Administrator\' or \'Manager\'.')
+        self.addOption('', '--station', dest='experimentStationName', help='Experiment station name (should not be provided for administrator system role).')
+
+    def checkArgs(self):
+        if not self.options.username:
+            raise InvalidRequest('Username must be provided.')
+        if not self.options.roleName:
+            raise InvalidRequest('Role name must be provided.')
+
+    def getUsername(self):
+        return self.options.username
+
+    def getExperimentStationName(self):
+        return self.options.experimentStationName
+
+    def getRoleName(self):
+        return self.options.roleName
+
+    def runCommand(self):
+        self.parseArgs(usage="""
+    dm-add-user-experiment-role --username=USERNAME 
+        --role=ROLENAME
+        [--station=EXPERIMENTSTATIONNAME]
+
+Description:
+    Assigns system role to the given user. The 'Administrator' role cannot be accompanied with experiment station, while the 'Manager' role requires it.
+        """)
+        self.checkArgs()
+        api = UserRestApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol())
+        userSystemRole = api.addUserSystemRole(self.getUsername(), self.getRoleName(), self.getExperimentStationName())
+        print userSystemRole.getDisplayString(self.getDisplayKeys(), self.getDisplayFormat())
+
+#######################################################################
+# Run command.
+if __name__ == '__main__':
+    cli = AddUserSystemRoleCli()
+    cli.run()
+
diff --git a/src/python/dm/ds_web_service/cli/deleteUserExperimentRoleCli.py b/src/python/dm/ds_web_service/cli/deleteUserExperimentRoleCli.py
index 520984522a87f7372117975b9b20d088e0435957..15dae638de56c71f62e2a6f9ed5dbaf5bf06744d 100755
--- a/src/python/dm/ds_web_service/cli/deleteUserExperimentRoleCli.py
+++ b/src/python/dm/ds_web_service/cli/deleteUserExperimentRoleCli.py
@@ -8,8 +8,8 @@ class DeleteUserExperimentRoleCli(DsWebServiceSessionCli):
     def __init__(self):
         DsWebServiceSessionCli.__init__(self)
         self.addOption('', '--username', dest='username', help='User username.')
+        self.addOption('', '--role', dest='roleName', help='Role name can be either \'PI\' or \'User\'.')
         self.addOption('', '--experiment', dest='experimentName', help='Experiment name.')
-        self.addOption('', '--role', dest='roleName', help='Role name.')
 
     def checkArgs(self):
         if not self.options.username:
@@ -31,14 +31,15 @@ class DeleteUserExperimentRoleCli(DsWebServiceSessionCli):
     def runCommand(self):
         self.parseArgs(usage="""
     dm-delete-user-experiment-role --username=USERNAME 
-        --experiment=EXPERIMENTNAME --role=ROLENAME
+        --role=ROLENAME
+        --experiment=EXPERIMENTNAME
 
 Description:
     Deletes experiment role from the given user.
         """)
         self.checkArgs()
         api = UserRestApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol())
-        userExperimentRole = api.deleteUserExperimentRole(self.getUsername(), self.getExperimentName(), self.getRoleName())
+        userExperimentRole = api.deleteUserExperimentRole(self.getUsername(), self.getRoleName(), self.getExperimentName())
         #print 'Deleted User Experiment Role:\n\t%s' % userExperimentRole.getDisplayString(self.getDisplayKeys(), self.getDisplayFormat())
 
 #######################################################################
diff --git a/src/python/dm/ds_web_service/cli/deleteUserSystemRoleCli.py b/src/python/dm/ds_web_service/cli/deleteUserSystemRoleCli.py
new file mode 100755
index 0000000000000000000000000000000000000000..85a3f32f783c1555ef9a76629c27aaa36dc6b15e
--- /dev/null
+++ b/src/python/dm/ds_web_service/cli/deleteUserSystemRoleCli.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+
+from dm.common.exceptions.invalidRequest import InvalidRequest
+from dm.ds_web_service.api.userRestApi import UserRestApi
+from dsWebServiceSessionCli import DsWebServiceSessionCli
+
+class DeleteUserSystemRoleCli(DsWebServiceSessionCli):
+    def __init__(self):
+        DsWebServiceSessionCli.__init__(self)
+        self.addOption('', '--username', dest='username', help='User username.')
+        self.addOption('', '--role', dest='roleName', help='Role name can be either \'Administrator\' or \'Manager\'.')
+        self.addOption('', '--station', dest='experimentStationName', help='Experiment station name (should not be provided for administrator system role).')
+
+    def checkArgs(self):
+        if not self.options.username:
+            raise InvalidRequest('Username must be provided.')
+        if not self.options.roleName:
+            raise InvalidRequest('Role name must be provided.')
+
+    def getUsername(self):
+        return self.options.username
+
+    def getExperimentStationName(self):
+        return self.options.experimentStationName
+
+    def getRoleName(self):
+        return self.options.roleName
+
+    def runCommand(self):
+        self.parseArgs(usage="""
+    dm-delete-user-experiment-role --username=USERNAME 
+        --role=ROLENAME
+        [--station=EXPERIMENTSTATIONNAME]
+
+Description:
+    Removes system role from the given user. The 'Administrator' role cannot be accompanied with experiment station, while the 'Manager' role requires it.
+        """)
+        self.checkArgs()
+        api = UserRestApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol())
+        userSystemRole = api.deleteUserSystemRole(self.getUsername(), self.getRoleName(), self.getExperimentStationName())
+        #print userSystemRole.getDisplayString(self.getDisplayKeys(), self.getDisplayFormat())
+
+#######################################################################
+# Run command.
+if __name__ == '__main__':
+    cli = DeleteUserSystemRoleCli()
+    cli.run()
+
diff --git a/src/python/dm/ds_web_service/cli/getExperimentsCli.py b/src/python/dm/ds_web_service/cli/getExperimentsCli.py
index d46f5b738caff1fe200a40002c05610e0b4265ce..42afb78a1ac8ff4f0187c03784c50e982ba15aae 100755
--- a/src/python/dm/ds_web_service/cli/getExperimentsCli.py
+++ b/src/python/dm/ds_web_service/cli/getExperimentsCli.py
@@ -1,21 +1,34 @@
 #!/usr/bin/env python
 
 from dm.ds_web_service.api.experimentRestApi import ExperimentRestApi
+from dm.common.utility.configurationManager import ConfigurationManager
 from dsWebServiceSessionCli import DsWebServiceSessionCli
 
 class GetExperimentsCli(DsWebServiceSessionCli):
     def __init__(self):
         DsWebServiceSessionCli.__init__(self)
+        self.addOption('', '--station', dest='stationName', help='Experiment station name, can also be set via DM_STATION_NAME environment variable.')
+
+    def getStationName(self):
+        stationName = self.options.stationName
+        if not stationName:
+            configManager = ConfigurationManager.getInstance()
+            stationName = configManager.getStationName()
+        return stationName
 
     def runCommand(self):
         self.parseArgs(usage="""
-    dm-get-experiments 
+    dm-get-experiments [--station=STATIONNAME]
 
 Description:
-    Retrieves list of known experiments.
+    Retrieves list of experiments for a given station. If station name is not provided, this command will return list of experiments for all stations (requires administrator privileges).
         """)
         api = ExperimentRestApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol())
-        experiments = api.getExperiments()
+        stationName = self.getStationName()
+        if not stationName:
+            experiments = api.getExperiments()
+        else:
+            experiments = api.getExperimentsByStation(stationName)
         for experiment in experiments:
             print experiment.getDisplayString(self.getDisplayKeys(), self.getDisplayFormat())
 
diff --git a/src/python/dm/ds_web_service/service/experimentRouteDescriptor.py b/src/python/dm/ds_web_service/service/experimentRouteDescriptor.py
index f68d0f595118591e651808de392fc0a91f83f434..2ef94141c788f6c10a714f78e1fd11b6bddca471 100755
--- a/src/python/dm/ds_web_service/service/experimentRouteDescriptor.py
+++ b/src/python/dm/ds_web_service/service/experimentRouteDescriptor.py
@@ -28,6 +28,15 @@ class ExperimentRouteDescriptor:
                 'method' : ['GET']
             },
 
+            # Get experiment type by id
+            {
+                'name' : 'getExperimentTypeById',
+                'path' : '%s/experimentTypesById/:(id)' % contextRoot,
+                'controller' : experimentSessionController,
+                'action' : 'getExperimentTypeById',
+                'method' : ['GET']
+            },
+
             # Get experiments
             {
                 'name' : 'getExperiments',
@@ -37,10 +46,19 @@ class ExperimentRouteDescriptor:
                 'method' : ['GET']
             },
 
+            # Get experiments by station
+            {
+                'name' : 'getExperimentsByStation',
+                'path' : '%s/experimentsByStation/:(stationName)' % contextRoot,
+                'controller' : experimentSessionController,
+                'action' : 'getExperimentsByStation',
+                'method' : ['GET']
+            },
+
             # Get experiment
             {
                 'name' : 'getExperimentById',
-                'path' : '%s/experiments/:(id)' % contextRoot,
+                'path' : '%s/experimentsById/:(id)' % contextRoot,
                 'controller' : experimentSessionController,
                 'action' : 'getExperimentById',
                 'method' : ['GET']
diff --git a/src/python/dm/ds_web_service/service/experimentSessionController.py b/src/python/dm/ds_web_service/service/experimentSessionController.py
index b47a7bd5357fcf877efa50e57636f2db1133454c..2ef4c34fda68dc162af22cd9eb86d2d1fa91a162 100755
--- a/src/python/dm/ds_web_service/service/experimentSessionController.py
+++ b/src/python/dm/ds_web_service/service/experimentSessionController.py
@@ -4,6 +4,7 @@ import cherrypy
 
 from dm.common.service.dmSessionController import DmSessionController
 from dm.common.exceptions.invalidRequest import InvalidRequest
+from dm.common.exceptions.authorizationError import AuthorizationError
 from dm.common.utility.encoder import Encoder
 
 from dm.ds_web_service.service.impl.experimentSessionControllerImpl import ExperimentSessionControllerImpl
@@ -21,6 +22,13 @@ class ExperimentSessionController(DmSessionController):
     def getExperimentTypes(self, **kwargs):
         return self.listToJson(self.experimentSessionControllerImpl.getExperimentTypes())
 
+    @cherrypy.expose
+    @DmSessionController.require(DmSessionController.isLoggedIn())
+    @DmSessionController.execute
+    def getExperimentTypeById(self, id, **kwargs):
+        experimentType = self.experimentSessionControllerImpl.getExperimentTypeById(id)
+        return experimentType.getFullJsonRep()
+
     @cherrypy.expose
     @DmSessionController.require(DmSessionController.isAdministrator())
     @DmSessionController.execute
@@ -28,32 +36,47 @@ class ExperimentSessionController(DmSessionController):
         return self.listToJson(self.experimentSessionControllerImpl.getExperiments())
 
     @cherrypy.expose
-    @DmSessionController.require(DmSessionController.isAdministrator())
+    @DmSessionController.require(DmSessionController.isLoggedIn())
+    @DmSessionController.execute
+    def getExperimentsByStation(self, stationName, **kwargs):
+        if not self.hasAdministratorRole() and not self.hasManagerRole(stationName):
+            raise AuthorizationError('User %s cannot retrieve experiments for station %s.' % (self.getSessionUsername(), stationName))
+        return self.listToJson(self.experimentSessionControllerImpl.getExperimentsByStation(stationName))
+
+    @cherrypy.expose
+    @DmSessionController.require(DmSessionController.isLoggedIn())
     @DmSessionController.execute
     def getExperimentByName(self, name, **kwargs):
-        response = self.experimentSessionControllerImpl.getExperimentByName(name).getFullJsonRep()
-        self.logger.debug('Returning: %s' % response)
-        return response
+        experiment = self.experimentSessionControllerImpl.getExperimentByName(name)
+        if not self.hasAdministratorRole() and not self.hasManagerRole(experiment['experimentStationId']):
+            raise AuthorizationError('User %s cannot retrieve experiment %s.' % (self.getSessionUsername(), name))
+        return experiment.getFullJsonRep()
 
     @cherrypy.expose
-    @DmSessionController.require(DmSessionController.isAdministrator())
+    @DmSessionController.require(DmSessionController.isLoggedIn())
     @DmSessionController.execute
     def getExperimentById(self, id, **kwargs):
-        response = self.experimentSessionControllerImpl.getExperimentById(id).getFullJsonRep()
-        self.logger.debug('Returning: %s' % response)
-        return response
+        experiment = self.experimentSessionControllerImpl.getExperimentById(id)
+        if not self.hasAdministratorRole() and not self.hasManagerRole(experiment['experimentStationId']):
+            raise AuthorizationError('User %s cannot retrieve experiment %s.' % (self.getSessionUsername(), id))
+        return experiment.getFullJsonRep()
 
     @cherrypy.expose
-    @DmSessionController.require(DmSessionController.isAdministrator())
+    @DmSessionController.require(DmSessionController.isLoggedIn())
     @DmSessionController.execute
     def addExperiment(self, **kwargs):
         name = kwargs.get('name')
-        if name is None or not len(name):
+        if not name:
             raise InvalidRequest('Missing experiment name.')
         name = Encoder.decode(name)
-        experimentTypeId = kwargs.get('experimentTypeId')
-        if experimentTypeId is None:
-            raise InvalidRequest('Missing experiment type id.')
+        stationName = kwargs.get('stationName')
+        if not stationName:
+            raise InvalidRequest('Missing experiment station name.')
+        stationName = Encoder.decode(stationName)
+        typeName = kwargs.get('typeName')
+        if not typeName:
+            raise InvalidRequest('Missing experiment type.')
+        typeName = Encoder.decode(typeName)
         description = kwargs.get('description')
         if description is not None:
             description = Encoder.decode(description)
@@ -63,65 +86,83 @@ class ExperimentSessionController(DmSessionController):
         endDate = kwargs.get('endDate')
         if endDate is not None:
             endDate = Encoder.decode(endDate)
-        response = self.experimentSessionControllerImpl.addExperiment(name, experimentTypeId, description, startDate, endDate).getFullJsonRep()
-        self.logger.debug('Returning: %s' % response)
+        if not self.hasAdministratorRole() and not self.hasManagerRole(stationName):
+            raise AuthorizationError('User %s is not allowed to add experiment on station %s.' % (self.getSessionUsername(), stationName))
+        response = self.experimentSessionControllerImpl.addExperiment(name, stationName, typeName, description, startDate, endDate).getFullJsonRep()
+        
+        self.logger.debug('Added experiment: %s' % response)
         return response
 
     @cherrypy.expose
-    @DmSessionController.require(DmSessionController.isAdministrator())
+    @DmSessionController.require(DmSessionController.isLoggedIn())
     @DmSessionController.execute
     def startExperiment(self, **kwargs):
         name = kwargs.get('name')
-        if name is None or not len(name):
+        if not name:
             raise InvalidRequest('Missing experiment name.')
         name = Encoder.decode(name)
-        response = self.experimentSessionControllerImpl.startExperiment(name).getFullJsonRep()
-        self.logger.debug('Returning: %s' % response)
+        experiment = self.experimentSessionControllerImpl.getExperimentByName(name)
+        if not self.hasAdministratorRole() and not self.hasManagerRole(experiment['experimentStationId']):
+            raise AuthorizationError('User %s cannot start experiment %s.' % (self.getSessionUsername(), name))
+        response = self.experimentSessionControllerImpl.startExperiment(experiment).getFullJsonRep()
+        self.logger.debug('Started experiment: %s' % response)
         return response
 
     @cherrypy.expose
-    @DmSessionController.require(DmSessionController.isAdministrator())
+    @DmSessionController.require(DmSessionController.isLoggedIn())
     @DmSessionController.execute
     def updateExperiment(self, **kwargs):
         name = kwargs.get('name')
         if name is None or not len(name):
             raise InvalidRequest('Missing experiment name.')
         name = Encoder.decode(name)
-        response = self.experimentSessionControllerImpl.updateExperiment(name).getFullJsonRep()
-        self.logger.debug('Returning: %s' % response)
+        experiment = self.experimentSessionControllerImpl.getExperimentByName(name)
+        if not self.hasAdministratorRole() and not self.hasManagerRole(experiment['experimentStationId']):
+            raise AuthorizationError('User %s cannot update experiment %s.' % (self.getSessionUsername(), name))
+        response = self.experimentSessionControllerImpl.updateExperiment(experiment).getFullJsonRep()
+        self.logger.debug('Updated experiment: %s' % response)
         return response
 
     @cherrypy.expose
-    @DmSessionController.require(DmSessionController.isAdministrator())
+    @DmSessionController.require(DmSessionController.isLoggedIn())
     @DmSessionController.execute
     def stopExperiment(self, **kwargs):
         name = kwargs.get('name')
         if name is None or not len(name):
             raise InvalidRequest('Missing experiment name.')
         name = Encoder.decode(name)
-        response = self.experimentSessionControllerImpl.stopExperiment(name).getFullJsonRep()
-        self.logger.debug('Returning: %s' % response)
+        experiment = self.experimentSessionControllerImpl.getExperimentByName(name)
+        if not self.hasAdministratorRole() and not self.hasManagerRole(experiment['experimentStationId']):
+            raise AuthorizationError('User %s cannot stop experiment %s.' % (self.getSessionUsername(), name))
+        response = self.experimentSessionControllerImpl.stopExperiment(experiment).getFullJsonRep()
+        self.logger.debug('Stopped experiment: %s' % response)
         return response
 
     @cherrypy.expose
-    @DmSessionController.require(DmSessionController.isAdministrator())
+    @DmSessionController.require(DmSessionController.isLoggedIn())
     @DmSessionController.execute
     def authorizeDownload(self, username, experimentName, **kwargs):
         if not username:
             raise InvalidRequest('Invalid username provided.')
         if not experimentName:
             raise InvalidRequest('Invalid experiment name provided.')
-        response = self.experimentSessionControllerImpl.authorizeDownload(username, experimentName).getFullJsonRep()
+        experiment = self.experimentSessionControllerImpl.getExperimentByName(experimentName)
+        if not self.hasAdministratorRole() and not self.hasManagerRole(experiment['experimentStationId']):
+            raise AuthorizationError('User %s is not allowed to authorize download for experiment %s.' % (self.getSessionUsername(), experimentName))
+        response = self.experimentSessionControllerImpl.authorizeDownload(username, experiment).getFullJsonRep()
         return response
 
     @cherrypy.expose
-    @DmSessionController.require(DmSessionController.isAdministrator())
+    @DmSessionController.require(DmSessionController.isLoggedIn())
     @DmSessionController.execute
     def deauthorizeDownload(self, username, experimentName, **kwargs):
         if not username:
             raise InvalidRequest('Invalid username provided.')
         if not experimentName:
             raise InvalidRequest('Invalid experiment name provided.')
-        response = self.experimentSessionControllerImpl.deauthorizeDownload(username, experimentName).getFullJsonRep()
+        experiment = self.experimentSessionControllerImpl.getExperimentByName(experimentName)
+        if not self.hasAdministratorRole() and not self.hasManagerRole(experiment['experimentStationId']):
+            raise AuthorizationError('User %s is not allowed to de-authorize download for experiment %s.' % (self.getSessionUsername(), experimentName))
+        response = self.experimentSessionControllerImpl.deauthorizeDownload(username, experiment).getFullJsonRep()
         return response
 
diff --git a/src/python/dm/ds_web_service/service/fileSessionController.py b/src/python/dm/ds_web_service/service/fileSessionController.py
index 914cc2677f8bf928b76a185f40b1c4933427d19c..bf89064c86eeca7649f5821973e5a679851e32f7 100755
--- a/src/python/dm/ds_web_service/service/fileSessionController.py
+++ b/src/python/dm/ds_web_service/service/fileSessionController.py
@@ -5,6 +5,8 @@ import json
 
 from dm.common.service.dmSessionController import DmSessionController
 from dm.common.exceptions.invalidRequest import InvalidRequest
+from dm.common.exceptions.authorizationError import AuthorizationError 
+from dm.common.db.api.experimentDbApi import ExperimentDbApi
 from dm.common.utility.encoder import Encoder
 
 from dm.ds_web_service.service.impl.fileSessionControllerImpl import FileSessionControllerImpl
@@ -14,6 +16,7 @@ class FileSessionController(DmSessionController):
 
     def __init__(self):
         DmSessionController.__init__(self)
+        self.experimentDbApi = ExperimentDbApi()
         self.fileSessionControllerImpl = FileSessionControllerImpl()
 
     @cherrypy.expose
@@ -30,11 +33,11 @@ class FileSessionController(DmSessionController):
         if not fileInfo.has_key('experimentName'):
             raise InvalidRequest('Experiment name is missing.')
         response = self.fileSessionControllerImpl.processFile(fileInfo).getFullJsonRep()
-        self.logger.debug('Returning: %s' % response)
+        self.logger.debug('Processed file: %s' % response)
         return response
 
     @cherrypy.expose
-    @DmSessionController.require(DmSessionController.isAdministrator())
+    @DmSessionController.require(DmSessionController.isLoggedIn())
     @DmSessionController.execute
     def statFile(self, **kwargs):
         encodedFileInfo = kwargs.get('fileInfo')
@@ -44,10 +47,14 @@ class FileSessionController(DmSessionController):
 
         if not fileInfo.has_key('experimentFilePath'):
             raise InvalidRequest('Experiment file path is missing.')
-        if not fileInfo.has_key('experimentName'):
+        experimentName = fileInfo.get('experimentName')
+        if not experimentName:
             raise InvalidRequest('Experiment name is missing.')
-        response = self.fileSessionControllerImpl.statFile(fileInfo).getFullJsonRep()
-        self.logger.debug('Returning: %s' % response)
+        experiment = self.experimentDbApi.getExperimentByName(experimentName)
+        if not self.hasAdministratorRole() and not self.hasManagerRole(experiment['experimentStationId']):
+            raise AuthorizationError('User %s cannot stat file for experiment %s.' % (self.getSessionUsername(),experimentName))
+        response = self.fileSessionControllerImpl.statFile(fileInfo, experiment).getFullJsonRep()
+        self.logger.debug('File stat: %s' % response)
         return response
 
     @cherrypy.expose
@@ -62,6 +69,6 @@ class FileSessionController(DmSessionController):
         if not directoryInfo.has_key('experimentName'):
             raise InvalidRequest('Experiment name is missing.')
         response = self.fileSessionControllerImpl.processDirectory(directoryInfo).getFullJsonRep()
-        self.logger.debug('Returning: %s' % response)
+        self.logger.debug('Processed directory: %s' % response)
         return response
 
diff --git a/src/python/dm/ds_web_service/service/impl/authSessionControllerImpl.py b/src/python/dm/ds_web_service/service/impl/authSessionControllerImpl.py
index 44a9db0f468e0888d45e81a99a5803bd73eb981e..fd34cab585bad66734fb10ef89a23b92dea7dfda 100755
--- a/src/python/dm/ds_web_service/service/impl/authSessionControllerImpl.py
+++ b/src/python/dm/ds_web_service/service/impl/authSessionControllerImpl.py
@@ -21,13 +21,19 @@ class AuthSessionControllerImpl(DmObjectManager):
         self.userDbApi = UserDbApi()
 
     def getAuthorizationPrincipal(self, username):
-        user = self.userDbApi.getUserWithPasswordByUsername(username)
-        principal = AuthorizationPrincipal(name=username, token=user.get('password'))
-        principal.setRole(dmRole.DM_USER_ROLE)
-        principal.setUserInfo(user)
-        for userSystemRoleName in user.get('userSystemRoleNameList', []):
-            if userSystemRoleName == dmRole.DM_ADMIN_ROLE:
-                principal.setRole(dmRole.DM_ADMIN_ROLE)
+        principal = None
+        try:
+            user = self.userDbApi.getUserWithPasswordByUsername(username)
+            principal = AuthorizationPrincipal(name=username, token=user.get('password'))
+            principal.setUserSystemRoleDict(user.get('userSystemRoleDict', {}))
+            principal.setUserExperimentRoleDict(user.get('userExperimentRoleDict', {}))
+            principal.setSessionRole(dmRole.DM_USER_SESSION_ROLE)
+            for userSystemRoleId in principal.get('userSystemRoleDict', {}).keys():
+                if userSystemRoleId == dmRole.DM_ADMIN_SYSTEM_ROLE_ID:
+                    principal.setSessionRole(dmRole.DM_ADMIN_SESSION_ROLE)
+                    break
+        except Exception, ex:
+            self.logger.debug(ex)
         return principal
 
     def addSession(self, sessionId, sessionInfo):
diff --git a/src/python/dm/ds_web_service/service/impl/experimentManager.py b/src/python/dm/ds_web_service/service/impl/experimentManager.py
index eb6a697afc804498a386e16059654b047755eb74..8c4cc6bf81502d1fb38c8d67d3bddb7de8c5f1a5 100755
--- a/src/python/dm/ds_web_service/service/impl/experimentManager.py
+++ b/src/python/dm/ds_web_service/service/impl/experimentManager.py
@@ -72,7 +72,7 @@ class ExperimentManager(Singleton):
         self.logger.debug('Manage storage permissions: %s' % self.manageStoragePermissions)
 
     def __getExperimentStorageDataDirectory(self, experiment):
-        experimentTypeName = experiment.get('experimentType').get('rootDataPath')
+        experimentTypeName = experiment.get('experimentType').get('name')
         experimentName = experiment.get('name')
         storageDirectory = '%s/%s/%s' % (self.storageDirectory, experimentTypeName, experimentName)
         storageDirectory = os.path.normpath(storageDirectory)
@@ -114,9 +114,9 @@ class ExperimentManager(Singleton):
         self.logger.debug('Removing rsync script %s' % (fileName))
         OsUtility.removeFile(fileName)
 
-    def authorizeDownload(self, username, experimentName):
+    def authorizeDownload(self, username, experiment):
+        experimentName = experiment['name']
         self.logger.debug('Authorizing download for %s from experiment %s' % (username, experimentName))
-        experiment = self.experimentDbApi.getExperimentByName(experimentName)
         storageDirectory = self.updateExperimentWithStorageDataDirectory(experiment)
         if os.path.exists(storageDirectory):
             self.platformUtility.addLocalUserToGroup(username, experimentName)
@@ -125,8 +125,8 @@ class ExperimentManager(Singleton):
         self.createRsyncScript(username, experimentName)
         return experiment
 
-    def deauthorizeDownload(self, username, experimentName):
-        experiment = self.experimentDbApi.getExperimentByName(experimentName)
+    def deauthorizeDownload(self, username, experiment):
+        experimentName = experiment['name']
         self.logger.debug('De-authorizing download for %s from experiment %s' % (username, experimentName))
         storageDirectory = self.updateExperimentWithStorageDataDirectory(experiment)
         if os.path.exists(storageDirectory):
diff --git a/src/python/dm/ds_web_service/service/impl/experimentSessionControllerImpl.py b/src/python/dm/ds_web_service/service/impl/experimentSessionControllerImpl.py
index 24b69ee995b25bffca10a2e44c66e8d196aebb34..4ca854acdb185cfe41248dd6e47efaaa2cdcdf04 100755
--- a/src/python/dm/ds_web_service/service/impl/experimentSessionControllerImpl.py
+++ b/src/python/dm/ds_web_service/service/impl/experimentSessionControllerImpl.py
@@ -27,6 +27,10 @@ class ExperimentSessionControllerImpl(DmObjectManager):
         experimentList = self.experimentDbApi.getExperiments()
         return experimentList
 
+    def getExperimentsByStation(self, stationName):
+        experimentList = self.experimentDbApi.getExperimentsByStation(stationName)
+        return experimentList
+
     def getExperimentByName(self, name):
         experiment = self.experimentDbApi.getExperimentWithUsers(name)
         ExperimentManager.getInstance().updateExperimentWithStorageDataDirectory(experiment)
@@ -37,33 +41,27 @@ class ExperimentSessionControllerImpl(DmObjectManager):
         ExperimentManager.getInstance().updateExperimentWithStorageDataDirectory(experiment)
         return experiment
 
-    def addExperiment(self, name, experimentTypeId, description, startDate, endDate):
-        experiment = self.experimentDbApi.addExperiment(name, experimentTypeId, description, startDate, endDate)
+    def addExperiment(self, name, stationName, typeId, description, startDate, endDate):
+        experiment = self.experimentDbApi.addExperiment(name, stationName, typeId, description, startDate, endDate)
+        ExperimentManager.getInstance().createExperimentDataDirectory(experiment)
         return experiment
 
-    def startExperiment(self, name):
-        experiment = self.experimentDbApi.getExperimentWithUsers(name)
-        if experiment.get('startDate') is None:
-            experiment2 = self.experimentDbApi.setExperimentStartDateToNow(name)
-            experiment['startDate'] = experiment2['startDate']
-        ExperimentManager.getInstance().createExperimentDataDirectory(experiment)
+    def startExperiment(self, experiment):
+        experiment2 = self.experimentDbApi.setExperimentStartDateToNow(experiment['name'])
+        experiment['startDate'] = experiment2['startDate']
         return experiment
 
-    def updateExperiment(self, name):
-        experiment = self.experimentDbApi.getExperimentWithUsers(name)
-        if experiment.get('startDate') is not None:
-            ExperimentManager.getInstance().updateExperimentGroupUsers(experiment)
+    def updateExperiment(self, experiment):
+        ExperimentManager.getInstance().updateExperimentGroupUsers(experiment)
         return experiment
 
-    def stopExperiment(self, name):
-        experiment = self.experimentDbApi.getExperimentByName(name)
-        if experiment.get('endDate') is None:
-            experiment = self.experimentDbApi.setExperimentEndDateToNow(name)
+    def stopExperiment(self, experiment):
+        experiment = self.experimentDbApi.setExperimentEndDateToNow(experiment['name'])
         ExperimentManager.getInstance().updateExperimentWithStorageDataDirectory(experiment)
         return experiment
 
-    def authorizeDownload(self, username, experimentName):
-        return ExperimentManager.getInstance().authorizeDownload(username, experimentName)
+    def authorizeDownload(self, username, experiment):
+        return ExperimentManager.getInstance().authorizeDownload(username, experiment)
 
-    def deauthorizeDownload(self, username, experimentName):
-        return ExperimentManager.getInstance().deauthorizeDownload(username, experimentName)
+    def deauthorizeDownload(self, username, experiment):
+        return ExperimentManager.getInstance().deauthorizeDownload(username, experiment)
diff --git a/src/python/dm/ds_web_service/service/impl/fileSessionControllerImpl.py b/src/python/dm/ds_web_service/service/impl/fileSessionControllerImpl.py
index 0c9d9ac21922f56047b8c9437ebb3a0170d2dd9d..5f71ce52909ce24513e86d6772beab6736e5d434 100755
--- a/src/python/dm/ds_web_service/service/impl/fileSessionControllerImpl.py
+++ b/src/python/dm/ds_web_service/service/impl/fileSessionControllerImpl.py
@@ -27,10 +27,11 @@ class FileSessionControllerImpl(DmObjectManager):
         ExperimentManager.getInstance().processExperimentFile(experimentFilePath, experiment, fileInfo)
         return FileMetadata(fileInfo)
 
-    def statFile(self, fileInfo):
+    def statFile(self, fileInfo, experiment=None):
         experimentFilePath = fileInfo.get('experimentFilePath')
-        experimentName = fileInfo.get('experimentName')
-        experiment = self.experimentDbApi.getExperimentByName(experimentName)
+        if not experiment:
+            experimentName = fileInfo.get('experimentName')
+            experiment = self.experimentDbApi.getExperimentByName(experimentName)
         ExperimentManager.getInstance().statExperimentFile(experimentFilePath, experiment, fileInfo)
         return FileMetadata(fileInfo)
 
diff --git a/src/python/dm/ds_web_service/service/impl/userInfoSessionControllerImpl.py b/src/python/dm/ds_web_service/service/impl/userInfoSessionControllerImpl.py
index 6a973d35c4f2dbf8713daee9f04f300e3ca6b63c..35219a62c5e2239ab5a5f1b459918acfc3c671d5 100755
--- a/src/python/dm/ds_web_service/service/impl/userInfoSessionControllerImpl.py
+++ b/src/python/dm/ds_web_service/service/impl/userInfoSessionControllerImpl.py
@@ -25,21 +25,21 @@ class UserInfoSessionControllerImpl(DmObjectManager):
     def getUserByUsername(self, username):
         return self.userDbApi.getUserByUsername(username)
 
-    def addUser(self, username, firstName, lastName, middleName, email, badge, globusUsername, description, password, isLocalUser, lastUpdate):
-        userInfo = self.userDbApi.addUser(username, firstName, lastName, middleName, email, badge, globusUsername, description, password, isLocalUser, lastUpdate)
-        return userInfo
+    def addUserSystemRole(self, username, roleName, experimentStationName):
+        userSystemRole = self.userDbApi.addUserSystemRole(username, roleName, experimentStationName)
+        return userSystemRole
 
-    def updateUser(self, id, username, firstName, lastName, middleName, email, badge, globusUsername, description, password, isLocalUser, lastUpdate):
-        userInfo = self.userDbApi.updateUser(id, username, firstName, lastName, middleName, email, badge, globusUsername, description, password, isLocalUser, lastUpdate)
-        return userInfo
+    def deleteUserSystemRole(self, username, roleName, experimentStationName):
+        userSystemRole = self.userDbApi.deleteUserSystemRole(username, roleName, experimentStationName)
+        return userSystemRole
 
-    def addUserExperimentRole(self, username, experimentName, roleName):
-        userInfo = self.userDbApi.addUserExperimentRole(username, experimentName, roleName)
+    def addUserExperimentRole(self, username, roleName, experimentName):
+        userExperimentRole = self.userDbApi.addUserExperimentRole(username, roleName, experimentName)
         ExperimentManager.getInstance().addUserToGroup(username, experimentName)
-        return userInfo
+        return userExperimentRole 
 
-    def deleteUserExperimentRole(self, username, experimentName, roleName):
-        userInfo = self.userDbApi.deleteUserExperimentRole(username, experimentName, roleName)
+    def deleteUserExperimentRole(self, username, roleName, experimentName):
+        userExperimentRole = self.userDbApi.deleteUserExperimentRole(username, roleName, experimentName)
         ExperimentManager.getInstance().deleteUserFromGroup(username, experimentName)
-        return userInfo
+        return userExperimentRole
 
diff --git a/src/python/dm/ds_web_service/service/userInfoSessionController.py b/src/python/dm/ds_web_service/service/userInfoSessionController.py
index d72fd6373defa5b74d4146ea10d7b55423a1dd54..7957dfbeb3ee48d3b37d3ade9306fd96d9ccc14d 100755
--- a/src/python/dm/ds_web_service/service/userInfoSessionController.py
+++ b/src/python/dm/ds_web_service/service/userInfoSessionController.py
@@ -1,25 +1,27 @@
 #!/usr/bin/env python
 
 import cherrypy
-
-from dm.common.utility.encoder import Encoder
 from dm.common.service.dmSessionController import DmSessionController
 from dm.ds_web_service.service.impl.userInfoSessionControllerImpl import UserInfoSessionControllerImpl
+from dm.common.db.api.experimentDbApi import ExperimentDbApi
+from dm.common.exceptions.invalidRequest import InvalidRequest
+from dm.common.exceptions.authorizationError import AuthorizationError
 
 class UserInfoSessionController(DmSessionController):
 
     def __init__(self):
         DmSessionController.__init__(self)
+        self.experimentDbApi = ExperimentDbApi()
         self.userInfoSessionControllerImpl = UserInfoSessionControllerImpl()
 
     @cherrypy.expose
-    @DmSessionController.require(DmSessionController.isAdministrator())
+    @DmSessionController.require(DmSessionController.isLoggedIn())
     @DmSessionController.execute
     def getUsers(self, **kwargs):
         return self.listToJson(self.userInfoSessionControllerImpl.getUsers())
 
     @cherrypy.expose
-    @DmSessionController.require(DmSessionController.isAdministrator())
+    @DmSessionController.require(DmSessionController.isLoggedIn())
     @DmSessionController.execute
     def getUserById(self, id, **kwargs):
         if not id:
@@ -29,7 +31,7 @@ class UserInfoSessionController(DmSessionController):
         return response
 
     @cherrypy.expose
-    @DmSessionController.require(DmSessionController.isAdministrator())
+    @DmSessionController.require(DmSessionController.isLoggedIn())
     @DmSessionController.execute
     def getUserByUsername(self, username, **kwargs):
         if not len(username):
@@ -39,79 +41,78 @@ class UserInfoSessionController(DmSessionController):
         return response
 
     @cherrypy.expose
-    @DmSessionController.require(DmSessionController.isAdministrator())
+    @DmSessionController.require(DmSessionController.isLoggedIn())
     @DmSessionController.execute
-    def addUser(self, **kwargs):
-        username = kwargs.get('username')
+    def addUserSystemRole(self, username, roleName, **kwargs):
         if not username:
             raise InvalidRequest('Invalid username provided.')
-        firstName = kwargs.get('firstName')
-        if not firstName:
-            raise InvalidRequest('Invalid first name provided.')
-        firstName = Encoder.decode(firstName)
-        lastName = kwargs.get('lastName')
-        if not lastName:
-            raise InvalidRequest('Invalid last name provided.')
-        lastName = Encoder.decode(lastName)
-        middleName = Encoder.decode(kwargs.get('middleName'))
-        email = Encoder.decode(kwargs.get('email'))
-        badge = Encoder.decode(kwargs.get('badge'))
-        globusUsername = Encoder.decode(kwargs.get('globusUsername'))
-        description = Encoder.decode(kwargs.get('description'))
-        password = Encoder.decode(kwargs.get('password'))
-        isLocalUser = kwargs.get('isLocalUser')
-        lastUpdate = Encoder.decode(kwargs.get('lastUpdate'))
-
-        response = self.userInfoSessionControllerImpl.addUser(username, firstName, lastName, middleName, email, badge, globusUsername, description, password, isLocalUser, lastUpdate).getFullJsonRep()
+        if not roleName:
+            raise InvalidRequest('Invalid role name provided.')
+        experimentStationName = kwargs.get('experimentStationName')
+        if experimentStationName:
+            experimentStation = self.experimentDbApi.getExperimentStationByName(experimentStationName)
+            if not self.hasAdministratorRole() and not self.hasManagerRole(experimentStation['id']):
+                raise AuthorizationError('User %s cannot modify system roles for experiment station %s.' % (self.getSessionUsername(),experimentStationName))
+        else:
+            if not self.hasAdministratorRole():
+                raise AuthorizationError('User %s cannot modify system roles.' % (self.getSessionUsername()))
+
+        response = self.userInfoSessionControllerImpl.addUserSystemRole(username, roleName, experimentStationName).getFullJsonRep()
         return response
 
     @cherrypy.expose
-    @DmSessionController.require(DmSessionController.isAdministrator())
+    @DmSessionController.require(DmSessionController.isLoggedIn())
     @DmSessionController.execute
-    def updateUser(self, id, **kwargs):
-        if not id:
-            raise InvalidRequest('Invalid user id provided.')
-        username = kwargs.get('username')
-        firstName = Encoder.decode(kwargs.get('firstName'))
-        lastName = Encoder.decode(kwargs.get('lastName'))
-        middleName = Encoder.decode(kwargs.get('middleName'))
-        email = Encoder.decode(kwargs.get('email'))
-        badge = Encoder.decode(kwargs.get('badge'))
-        globusUsername = Encoder.decode(kwargs.get('globusUsername'))
-        description = Encoder.decode(kwargs.get('description'))
-        password = Encoder.decode(kwargs.get('password'))
-        isLocalUser = kwargs.get('isLocalUser')
-        lastUpdate = Encoder.decode(kwargs.get('lastUpdate'))
-
-        response = self.userInfoSessionControllerImpl.updateUser(id, username, firstName, lastName, middleName, email, badge, globusUsername, description, password, isLocalUser, lastUpdate).getFullJsonRep()
+    def deleteUserSystemRole(self, username, roleName, **kwargs):
+        if not username:
+            raise InvalidRequest('Invalid username provided.')
+        if not roleName:
+            raise InvalidRequest('Invalid role name provided.')
+        experimentStationName = kwargs.get('experimentStationName')
+        if experimentStationName:
+            experimentStation = self.experimentDbApi.getExperimentStationByName(experimentStationName)
+            if not self.hasAdministratorRole() and not self.hasManagerRole(experimentStation['id']):
+                raise AuthorizationError('User %s cannot modify system roles for experiment station %s.' % (self.getSessionUsername(),experimentStationName))
+        else:
+            if not self.hasAdministratorRole():
+                raise AuthorizationError('User %s cannot modify system roles.' % (self.getSessionUsername()))
+
+        response = self.userInfoSessionControllerImpl.deleteUserSystemRole(username, roleName, experimentStationName).getFullJsonRep()
         return response
 
     @cherrypy.expose
-    @DmSessionController.require(DmSessionController.isAdministrator())
-    @DmSessionController.execute
-    @cherrypy.expose
-    @DmSessionController.require(DmSessionController.isAdministrator())
+    @DmSessionController.require(DmSessionController.isLoggedIn())
     @DmSessionController.execute
-    def addUserExperimentRole(self, username, experimentName, roleName, **kwargs):
+    def addUserExperimentRole(self, username, roleName, experimentName, **kwargs):
         if not username:
             raise InvalidRequest('Invalid username provided.')
         if not experimentName:
             raise InvalidRequest('Invalid experiment name provided.')
         if not roleName:
             raise InvalidRequest('Invalid role name provided.')
-        response = self.userInfoSessionControllerImpl.addUserExperimentRole(username, experimentName, roleName).getFullJsonRep()
+ 
+        experiment = self.experimentDbApi.getExperimentByName(experimentName)
+        if not self.hasAdministratorRole() and not self.hasManagerRole(experiment['experimentStationId']) and not self.hasPiRole(experiment['id']):
+            raise AuthorizationError('User %s cannot modify users for experiment %s.' % (self.getSessionUsername(),experimentName))
+
+        response = self.userInfoSessionControllerImpl.addUserExperimentRole(username, roleName, experimentName).getFullJsonRep()
         return response
 
     @cherrypy.expose
-    @DmSessionController.require(DmSessionController.isAdministrator())
+    @DmSessionController.require(DmSessionController.isLoggedIn())
     @DmSessionController.execute
-    def deleteUserExperimentRole(self, username, experimentName, roleName, **kwargs):
+    def deleteUserExperimentRole(self, username, roleName, experimentName, **kwargs):
         if not username:
             raise InvalidRequest('Invalid username provided.')
         if not experimentName:
             raise InvalidRequest('Invalid experiment name provided.')
         if not roleName:
             raise InvalidRequest('Invalid role name provided.')
-        response = self.userInfoSessionControllerImpl.deleteUserExperimentRole(username, experimentName, roleName).getFullJsonRep()
+
+        experiment = self.experimentDbApi.getExperimentByName(experimentName)
+        if not self.hasAdministratorRole() and not self.hasManagerRole(experiment['experimentStationId']) and not self.hasPiRole(experiment['id']):
+            raise AuthorizationError('User %s cannot modify users for experiment %s.' % (self.getSessionUsername(),experimentName))
+
+        response = self.userInfoSessionControllerImpl.deleteUserExperimentRole(username, roleName, experimentName).getFullJsonRep()
         return response
 
diff --git a/src/python/dm/ds_web_service/service/userRouteDescriptor.py b/src/python/dm/ds_web_service/service/userRouteDescriptor.py
index ddffb965d72daa1e0b26a81d85d269a0caa94b79..75d1ff3e8e3b446c88a50985c4dd1e5198b8b9d2 100755
--- a/src/python/dm/ds_web_service/service/userRouteDescriptor.py
+++ b/src/python/dm/ds_web_service/service/userRouteDescriptor.py
@@ -46,28 +46,28 @@ class UserRouteDescriptor:
                 'method' : ['GET']
             },
 
-            # Add user
+            # Add user system role
             {
-                'name' : 'addUser',
-                'path' : '%s/users' % contextRoot,
+                'name' : 'addUserSystemRole',
+                'path' : '%s/userSystemRoles/:(username)/:(roleName)' % contextRoot,
                 'controller' : userInfoSessionController,
-                'action' : 'addUser',
+                'action' : 'addUserSystemRole',
                 'method' : ['POST']
             },
 
-            # Update user
+            # Delete user system role
             {
-                'name' : 'updateUser',
-                'path' : '%s/users/:(id)' % contextRoot,
+                'name' : 'deleteUserSystemRole',
+                'path' : '%s/userSystemRoles/:(username)/:(roleName)' % contextRoot,
                 'controller' : userInfoSessionController,
-                'action' : 'updateUser',
-                'method' : ['PUT']
+                'action' : 'deleteUserSystemRole',
+                'method' : ['DELETE']
             },
 
             # Add user experiment role
             {
                 'name' : 'addUserExperimentRole',
-                'path' : '%s/usersByExperiment/:(username)/:(experimentName)/:(roleName)' % contextRoot,
+                'path' : '%s/userExperimentRoles/:(username)/:(roleName)/:(experimentName)' % contextRoot,
                 'controller' : userInfoSessionController,
                 'action' : 'addUserExperimentRole',
                 'method' : ['POST']
@@ -76,7 +76,7 @@ class UserRouteDescriptor:
             # Delete user experiment role
             {
                 'name' : 'deleteUserExperimentRole',
-                'path' : '%s/usersByExperiment/:(username)/:(experimentName)/:(roleName)' % contextRoot,
+                'path' : '%s/userExperimentRoles/:(username)/:(roleName)/:(experimentName)' % contextRoot,
                 'controller' : userInfoSessionController,
                 'action' : 'deleteUserExperimentRole',
                 'method' : ['DELETE']