Index: /trunk/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectJobsView.cs
===================================================================
--- /trunk/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectJobsView.cs	(revision 16208)
+++ /trunk/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectJobsView.cs	(revision 16209)
@@ -44,6 +44,8 @@
     private const string JOB_STATE = "State";
     private const string JOB_EXECUTIONSTATE = "Execution State";
+    private const string JOB_EXECUTIONTIME = "Execution Time";
     private const string JOB_DESCRIPTION = "Description";
     private const string JOB_TASKCOUNT = "Tasks";
+    private const string JOB_WAITINGTASKCOUNT = "Waiting";
     private const string JOB_CALCULATINGTASKCOUNT = "Calculating";
     private const string JOB_FINISHEDTASKCOUNT = "Finished";
@@ -112,9 +114,8 @@
         var jobs = GetSelectedJobs().ToList();
         if (jobs.Any()) {
-
-          // TODO: include isControllable?!
+                    
           startButton.Enabled = jobs.All(x =>
-            !x.IsProgressing && x.HiveTasks != null && x.HiveTasks.Count > 0
-            && x.Job.ProjectId != null && x.Job.ProjectId != Guid.Empty && x.Job.ResourceIds != null && x.Job.ResourceIds.Any()
+            !x.IsProgressing && HiveAdminClient.Instance.Tasks.ContainsKey(x.Id) && HiveAdminClient.Instance.Tasks[x.Id].Count > 0
+            && x.Job.ProjectId != Guid.Empty //&& x.Job.ResourceIds != null && x.Job.ResourceIds.Any()
             && (x.ExecutionState == ExecutionState.Prepared || x.ExecutionState == ExecutionState.Paused));
           pauseButton.Enabled = jobs.All(x => !x.IsProgressing && x.ExecutionState == ExecutionState.Started);
@@ -138,10 +139,11 @@
 
     private void refreshButton_Click(object sender, EventArgs e) {
-      var task = System.Threading.Tasks.Task.Factory.StartNew(RefreshJobsAsync);
       progress.Start("Refreshing jobs...");
       SetEnabledStateOfControls();
+      var task = System.Threading.Tasks.Task.Factory.StartNew(RefreshJobsAsync);
 
       task.ContinueWith((t) => {
-        matrixView.DataGridView.ClearSelection();
+        progress.Finish();        
+        SetEnabledStateOfControls();
       });
     }
@@ -157,20 +159,20 @@
           MessageBoxIcon.Question);
 
-        if (result == DialogResult.Yes) {          
+        if (result == DialogResult.Yes) {
+          progress.Start("Removing job(s)...");
+          SetEnabledStateOfControls();
           var task = System.Threading.Tasks.Task.Factory.StartNew(RemoveJobsAsync, jobs);
-          progress.Start();
-          SetEnabledStateOfControls();
-
-          task.ContinueWith((t) => {
-            matrixView.DataGridView.ClearSelection();
-            RefreshJobs();
-            progress.Finish();
+
+          task.ContinueWith((t) => {
+            RefreshJobs();
+            progress.Finish();
+            SetEnabledStateOfControls();
           }, TaskContinuationOptions.NotOnFaulted);
 
           task.ContinueWith((t) => {
-            matrixView.DataGridView.ClearSelection();
-            RefreshJobs();
-            progress.Finish();
-            MessageBox.Show("An error occured removing the job(s). " + t.Exception.Message, "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
+            RefreshJobs();
+            progress.Finish();
+            SetEnabledStateOfControls();
+            MessageBox.Show("An error occured removing the job(s).", "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
           }, TaskContinuationOptions.OnlyOnFaulted);
         }
@@ -189,18 +191,18 @@
 
         if (result == DialogResult.Yes) {
+          progress.Start("Resuming job(s)...");
+          SetEnabledStateOfControls();
           var task = System.Threading.Tasks.Task.Factory.StartNew(ResumeJobsAsync, jobs);
-          progress.Start();
-          SetEnabledStateOfControls();
-
-          task.ContinueWith((t) => {
-            matrixView.DataGridView.ClearSelection();
-            RefreshJobs();
-            progress.Finish();
-          });
-
-          task.ContinueWith((t) => {
-            matrixView.DataGridView.ClearSelection();
-            RefreshJobs();
-            progress.Finish();
+
+          task.ContinueWith((t) => {
+            RefreshJobs();            
+            progress.Finish();
+            SetEnabledStateOfControls();
+          }, TaskContinuationOptions.NotOnFaulted);
+
+          task.ContinueWith((t) => {
+            RefreshJobs();
+            progress.Finish();
+            SetEnabledStateOfControls();
             MessageBox.Show("An error occured resuming the job(s).", "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
           }, TaskContinuationOptions.OnlyOnFaulted);
@@ -220,18 +222,18 @@
 
         if (result == DialogResult.Yes) {
+          progress.Start("Pausing job(s)...");
+          SetEnabledStateOfControls();
           var task = System.Threading.Tasks.Task.Factory.StartNew(PauseJobsAsync, jobs);
-          progress.Start();
-          SetEnabledStateOfControls();
-
-          task.ContinueWith((t) => {
-            matrixView.DataGridView.ClearSelection();
-            RefreshJobs();
-            progress.Finish();
-          });
-
-          task.ContinueWith((t) => {
-            matrixView.DataGridView.ClearSelection();
-            RefreshJobs();
-            progress.Finish();
+
+          task.ContinueWith((t) => {
+            RefreshJobs();            
+            progress.Finish();
+            SetEnabledStateOfControls();
+          }, TaskContinuationOptions.NotOnFaulted);
+
+          task.ContinueWith((t) => {
+            RefreshJobs();
+            progress.Finish();
+            SetEnabledStateOfControls();
             MessageBox.Show("An error occured pausing the job(s).", "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
           }, TaskContinuationOptions.OnlyOnFaulted);
@@ -251,18 +253,18 @@
 
         if (result == DialogResult.Yes) {
+          progress.Start("Stopping job(s)...");
+          SetEnabledStateOfControls();
           var task = System.Threading.Tasks.Task.Factory.StartNew(StopJobsAsync, jobs);
-          progress.Start();
-          SetEnabledStateOfControls();
-
-          task.ContinueWith((t) => {
-            matrixView.DataGridView.ClearSelection();
-            RefreshJobs();
-            progress.Finish();
-          });
-
-          task.ContinueWith((t) => {
-            matrixView.DataGridView.ClearSelection();
-            RefreshJobs();
-            progress.Finish();
+
+          task.ContinueWith((t) => {
+            RefreshJobs();
+            progress.Finish();
+            SetEnabledStateOfControls();
+          }, TaskContinuationOptions.NotOnFaulted);
+
+          task.ContinueWith((t) => {
+            RefreshJobs();
+            progress.Finish();
+            SetEnabledStateOfControls();
             MessageBox.Show("An error occured stopping the job(s).", "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);            
           }, TaskContinuationOptions.OnlyOnFaulted);
@@ -287,5 +289,5 @@
       foreach (DataGridViewRow r in matrixView.DataGridView.SelectedRows) {
         if (((string)r.Cells[0].Value) == JobState.Online.ToString()) {
-          jobs.Add(HiveAdminClient.Instance.Jobs[Content.Id].FirstOrDefault(x => x.Id == Guid.Parse((string) r.Cells[9].Value)));
+          jobs.Add(HiveAdminClient.Instance.Jobs[Content.Id].FirstOrDefault(x => x.Id == Guid.Parse((string) r.Cells[11].Value)));
         }
       }
@@ -306,5 +308,5 @@
       var jobs = HiveAdminClient.Instance.Jobs[Content.Id];
       var resources = HiveAdminClient.Instance.Resources;
-      string[,] values = new string[jobs.Count, 11];
+      string[,] values = new string[jobs.Count, 13];
 
       for(int i = 0; i < jobs.Count; i++) {
@@ -312,17 +314,19 @@
         values[i, 0] = job.Job.State.ToString();
         values[i, 1] = job.ExecutionState.ToString();
-        values[i, 2] = job.Job.DateCreated.ToString();
-        values[i, 3] = job.Job.OwnerUsername;
-        values[i, 4] = job.Job.Name;
-        values[i, 5] = job.Job.JobCount.ToString();
-        values[i, 6] = job.Job.CalculatingCount.ToString();
-        values[i, 7] = job.Job.FinishedCount.ToString();
-        values[i, 8] = job.Job.Description;        
-        values[i, 9] = job.Job.Id.ToString();
-        values[i, 10] = job.Job.OwnerUserId.ToString();
+        values[i, 2] = job.ExecutionTime.ToString();
+        values[i, 3] = job.Job.DateCreated.ToString();
+        values[i, 4] = job.Job.OwnerUsername;
+        values[i, 5] = job.Job.Name;
+        values[i, 6] = job.Job.JobCount.ToString();
+        values[i, 7] = (job.Job.JobCount - job.Job.CalculatingCount - job.Job.FinishedCount).ToString();
+        values[i, 8] = job.Job.CalculatingCount.ToString();
+        values[i, 9] = job.Job.FinishedCount.ToString();
+        values[i, 10] = job.Job.Description;        
+        values[i, 11] = job.Job.Id.ToString();
+        values[i, 12] = job.Job.OwnerUserId.ToString();
       }
       
       var matrix = new StringMatrix(values);
-      matrix.ColumnNames = new string[] { JOB_STATE, JOB_EXECUTIONSTATE, JOB_DATECREATED, JOB_OWNER, JOB_NAME, JOB_TASKCOUNT, JOB_CALCULATINGTASKCOUNT, JOB_FINISHEDTASKCOUNT, JOB_DESCRIPTION, JOB_ID, JOB_OWNERID };
+      matrix.ColumnNames = new string[] { JOB_STATE, JOB_EXECUTIONSTATE, JOB_EXECUTIONTIME, JOB_DATECREATED, JOB_OWNER, JOB_NAME, JOB_TASKCOUNT, JOB_WAITINGTASKCOUNT, JOB_CALCULATINGTASKCOUNT, JOB_FINISHEDTASKCOUNT, JOB_DESCRIPTION, JOB_ID, JOB_OWNERID };
       matrix.SortableView = true;
       return matrix;
@@ -356,5 +360,6 @@
 
     private void RefreshJobsAsync() {
-      RefreshJobs();
+      HiveAdminClient.Instance.RefreshJobs();
+      UpdateJobs();
     }
 
@@ -387,5 +392,5 @@
       progress.Start();
       foreach (var job in jobList) {
-        progress.Status = "Deleting job \"" + job.Job.Name + "\"...";
+        progress.Status = "Removing job \"" + job.Job.Name + "\"...";
         HiveAdminClient.RemoveJob(job);
       }
Index: /trunk/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.cs
===================================================================
--- /trunk/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.cs	(revision 16208)
+++ /trunk/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.cs	(revision 16209)
@@ -318,5 +318,5 @@
 
     private void treeSlaveGroup_BeforeCheck(object sender, TreeViewCancelEventArgs e) {
-      if (e.Node == ungroupedGroupNode) {
+      if (!IsAdmin() || e.Node == ungroupedGroupNode) {
         e.Cancel = true;
       } else {
Index: /trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobView.cs
===================================================================
--- /trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobView.cs	(revision 16208)
+++ /trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobView.cs	(revision 16209)
@@ -139,4 +139,5 @@
           }
 
+          // project look up
           if (Content.Job != null && Content.Job.ProjectId == Guid.Empty) {
             if (HiveClient.Instance != null && HiveClient.Instance.Projects != null && HiveClient.Instance.Projects.Count == 1) {
@@ -150,16 +151,8 @@
               }                
             }
-          }
-
-
-          nameTextBox.Text = Content.Job.Name;
-          descriptionTextBox.Text = Content.Job.Description;
-          executionTimeTextBox.Text = Content.ExecutionTime.ToString();
-          refreshAutomaticallyCheckBox.Checked = Content.RefreshAutomatically;
-
-          // project look up
-          if(Content.Job.ProjectId != null && Content.Job.ProjectId != Guid.Empty) {
-            if(selectedProject == null || selectedProject.Id != Content.Job.ProjectId) {
+          } else if (Content.Job != null && Content.Job.ProjectId != Guid.Empty) {
+            if (selectedProject == null || selectedProject.Id != Content.Job.ProjectId) {
               selectedProject = GetProject(Content.Job.ProjectId);
+              hiveResourceSelectorDialog = null;
               if (selectedProject != null) {
                 projectNameTextBox.Text = selectedProject.Name;
@@ -168,4 +161,15 @@
               }
             }
+
+            if(hiveResourceSelectorDialog == null)
+              hiveResourceSelectorDialog = new HiveResourceSelectorDialog(Content.Job.Id, Content.Job.ProjectId);
+
+            if (Content.Job.ResourceIds == null) {
+              Content.Job.ResourceIds = HiveClient.Instance.GetAssignedResourcesForJob(Content.Job.Id)
+                .Select(x => x.Id)
+                .ToList();
+              hiveResourceSelectorDialog.SelectedResourceIds = Content.Job.ResourceIds;
+            }
+
           } else {
             selectedProject = null;
@@ -173,4 +177,10 @@
             Content.Job.ResourceIds = null;
           }
+
+
+          nameTextBox.Text = Content.Job.Name;
+          descriptionTextBox.Text = Content.Job.Description;
+          executionTimeTextBox.Text = Content.ExecutionTime.ToString();
+          refreshAutomaticallyCheckBox.Checked = Content.RefreshAutomatically;
           
           logView.Content = Content.Log;
@@ -501,17 +511,4 @@
     }
 
-    private void updateButton_Click2(object sender, EventArgs e) {
-      if (Content.ExecutionState == ExecutionState.Stopped) {
-        MessageBox.Show("Job cannot be updated once it stopped.", "HeuristicLab Hive Job Manager", MessageBoxButtons.OK, MessageBoxIcon.Information);
-        return;
-      }
-
-      HiveClient.UpdateJob(
-        (Exception ex) => ErrorHandling.ShowErrorDialog(this, "Update failed.", ex), 
-        Content, 
-        new CancellationToken());
-      UpdateSelectorDialog();
-    }
-
     private void updateButton_Click(object sender, EventArgs e) {
       if (Content.ExecutionState == ExecutionState.Stopped) {
@@ -556,5 +553,5 @@
       } else {
         startButton.Enabled = Content.IsControllable && Content.HiveTasks != null && Content.HiveTasks.Count > 0 
-          && Content.Job.ProjectId != null && Content.Job.ProjectId != Guid.Empty && Content.Job.ResourceIds != null  && Content.Job.ResourceIds.Any() 
+          && Content.Job.ProjectId != Guid.Empty && Content.Job.ResourceIds != null  && Content.Job.ResourceIds.Any() 
           && (Content.ExecutionState == ExecutionState.Prepared || Content.ExecutionState == ExecutionState.Paused) && !Content.IsProgressing;
         pauseButton.Enabled = Content.IsControllable && Content.ExecutionState == ExecutionState.Started && !Content.IsProgressing;
Index: /trunk/HeuristicLab.Clients.Hive/3.3/HiveAdminClient.cs
===================================================================
--- /trunk/HeuristicLab.Clients.Hive/3.3/HiveAdminClient.cs	(revision 16208)
+++ /trunk/HeuristicLab.Clients.Hive/3.3/HiveAdminClient.cs	(revision 16209)
@@ -80,4 +80,9 @@
     }
 
+    private Dictionary<Guid, List<LightweightTask>> tasks;
+    public Dictionary<Guid, List<LightweightTask>> Tasks {
+      get { return tasks; }
+    }
+
     private Dictionary<Guid, HashSet<Guid>> projectAncestors;
     public Dictionary<Guid, HashSet<Guid>> ProjectAncestors {
@@ -145,4 +150,5 @@
         projectResourceAssignments = new ItemList<AssignedProjectResource>();
         jobs = new Dictionary<Guid, HiveItemCollection<RefreshableJob>>();
+        tasks = new Dictionary<Guid, List<LightweightTask>>();
         projectNames = new Dictionary<Guid, string>();
         resourceNames = new Dictionary<Guid, string>();
@@ -311,4 +317,5 @@
       var projectIds = new List<Guid>();
       jobs = new Dictionary<Guid, HiveItemCollection<RefreshableJob>>();
+      tasks = new Dictionary<Guid, List<LightweightTask>>();
 
       HiveServiceLocator.Instance.CallHiveService(service => {
@@ -329,9 +336,17 @@
     }
 
-    public static void LoadLightweightJob(RefreshableJob refreshableJob) {
+    public void LoadLightweightJob(RefreshableJob refreshableJob) {
       var job = refreshableJob.Job;
-      var tasks = HiveServiceLocator.Instance.CallHiveService(s => s.GetLightweightJobTasksWithoutStateLog(job.Id));
-      if (tasks != null && tasks.Count > 0 && tasks.All(x => x.Id != Guid.Empty)) {
-        if (tasks.All(x =>
+      var lightweightTasks = HiveServiceLocator.Instance.CallHiveService(s => s.GetLightweightJobTasksWithoutStateLog(job.Id));
+
+      if (tasks.ContainsKey(job.Id)) {
+        tasks[job.Id].Clear();
+        tasks[job.Id].AddRange(lightweightTasks);
+      } else {
+        tasks.Add(job.Id, new List<LightweightTask>(lightweightTasks));        
+      }
+
+      if (lightweightTasks != null && lightweightTasks.Count > 0 && lightweightTasks.All(x => x.Id != Guid.Empty)) {
+        if (lightweightTasks.All(x =>
           x.State == TaskState.Finished 
           || x.State == TaskState.Aborted 
@@ -340,5 +355,5 @@
           refreshableJob.RefreshAutomatically = false;
         } else if (
-          tasks
+          lightweightTasks
             .Where(x => x.ParentTaskId != null)
             .All(x =>
@@ -346,14 +361,16 @@
               || x.State != TaskState.Transferring
               || x.State != TaskState.Calculating)
-          && tasks
+          && lightweightTasks
              .Where(x => x.ParentTaskId != null)
              .Any(x => x.State == TaskState.Paused)) {
           refreshableJob.ExecutionState = ExecutionState.Paused;
           refreshableJob.RefreshAutomatically = false;
-        } else if (tasks.Any(x => x.State == TaskState.Calculating 
+        } else if (lightweightTasks.Any(x => x.State == TaskState.Calculating 
                                   || x.State == TaskState.Transferring 
                                   || x.State == TaskState.Waiting)) {
           refreshableJob.ExecutionState = ExecutionState.Started;
         }
+
+        refreshableJob.ExecutionTime = TimeSpan.FromMilliseconds(lightweightTasks.Sum(x => x.ExecutionTime.TotalMilliseconds));
       }
     }
@@ -451,7 +468,8 @@
     public static void ResumeJob(RefreshableJob refreshableJob) {
       HiveServiceLocator.Instance.CallHiveService(service => {
-        foreach (HiveTask task in refreshableJob.GetAllHiveTasks()) {
-          if (task.Task.State == TaskState.Paused) {
-            service.RestartTask(task.Task.Id);
+        var tasks = service.GetLightweightJobTasksWithoutStateLog(refreshableJob.Id);
+        foreach (var task in tasks) {
+          if (task.State == TaskState.Paused) {
+            service.RestartTask(task.Id);
           }
         }
@@ -462,7 +480,8 @@
     public static void PauseJob(RefreshableJob refreshableJob) {
       HiveServiceLocator.Instance.CallHiveService(service => {
-        foreach (HiveTask task in refreshableJob.GetAllHiveTasks()) {
-          if (task.Task.State != TaskState.Finished && task.Task.State != TaskState.Aborted && task.Task.State != TaskState.Failed)
-            service.PauseTask(task.Task.Id);
+        var tasks = service.GetLightweightJobTasksWithoutStateLog(refreshableJob.Id);
+        foreach (var task in tasks) {
+          if (task.State != TaskState.Finished && task.State != TaskState.Aborted && task.State != TaskState.Failed)
+            service.PauseTask(task.Id);
         }
       });
@@ -472,7 +491,8 @@
     public static void StopJob(RefreshableJob refreshableJob) {
       HiveServiceLocator.Instance.CallHiveService(service => {
-        foreach (HiveTask task in refreshableJob.GetAllHiveTasks()) {
-          if (task.Task.State != TaskState.Finished && task.Task.State != TaskState.Aborted && task.Task.State != TaskState.Failed)
-            service.StopTask(task.Task.Id);
+        var tasks = service.GetLightweightJobTasksWithoutStateLog(refreshableJob.Id);
+        foreach (var task in tasks) {
+          if (task.State != TaskState.Finished && task.State != TaskState.Aborted && task.State != TaskState.Failed)
+            service.StopTask(task.Id);
         }
       });
@@ -481,6 +501,6 @@
 
     public static void RemoveJob(RefreshableJob refreshableJob) {
-      HiveServiceLocator.Instance.CallHiveService((s) => {
-        s.UpdateJobState(refreshableJob.Id, JobState.StatisticsPending);
+      HiveServiceLocator.Instance.CallHiveService((service) => {
+        service.UpdateJobState(refreshableJob.Id, JobState.StatisticsPending);
       });
     }
@@ -624,4 +644,9 @@
     }
 
+    public IEnumerable<Resource> GetAssignedResourcesForJob(Guid jobId) {
+      var assignedJobResource =  HiveServiceLocator.Instance.CallHiveService(service => service.GetAssignedResourcesForJob(jobId));
+      return Resources.Where(x => assignedJobResource.Select(y => y.ResourceId).Contains(x.Id));
+    }
+
     private bool IsAdmin() {
       return HiveRoles.CheckAdminUserPermissions();
Index: /trunk/HeuristicLab.Clients.Hive/3.3/HiveClient.cs
===================================================================
--- /trunk/HeuristicLab.Clients.Hive/3.3/HiveClient.cs	(revision 16208)
+++ /trunk/HeuristicLab.Clients.Hive/3.3/HiveClient.cs	(revision 16209)
@@ -756,4 +756,9 @@
       return string.Join(" » ", projects.Select(x => ProjectNames[x]).ToArray());
     }
+
+    public IEnumerable<Resource> GetAssignedResourcesForJob(Guid jobId) {
+      var assignedJobResource = HiveServiceLocator.Instance.CallHiveService(service => service.GetAssignedResourcesForJob(jobId));
+      return Resources.Where(x => assignedJobResource.Select(y => y.ResourceId).Contains(x.Id));
+    }
   }
 }
Index: /trunk/HeuristicLab.Services.Hive/3.3/HiveService.cs
===================================================================
--- /trunk/HeuristicLab.Services.Hive/3.3/HiveService.cs	(revision 16208)
+++ /trunk/HeuristicLab.Services.Hive/3.3/HiveService.cs	(revision 16209)
@@ -483,5 +483,4 @@
           }
 
-
           jobDto.CopyToEntity(job);
 
@@ -523,22 +522,13 @@
 
       RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
-      var currentUserId = UserManager.CurrentUserId;
+      // check if user is an admin, or granted to administer a job-parenting project, or job owner
+      AuthorizationManager.AuthorizeForJob(jobId, DT.Permission.Full);
 
       var pm = PersistenceManager;
       using (new PerformanceLogger("UpdateJobState")) {
-        var jobDao = pm.JobDao;
-        var projectDao = pm.ProjectDao;
+        var jobDao = pm.JobDao;        
         pm.UseTransaction(() => {
           var job = jobDao.GetById(jobId);
-          if (job != null) {
-
-            var administrationGrantedProjects = projectDao
-              .GetAdministrationGrantedProjectsForUser(currentUserId)
-              .ToList();
-
-            // check if user is an admin, or granted to administer a job-parenting project,...
-            if (!isAdministrator && !administrationGrantedProjects.Contains(job.Project))
-              AuthorizationManager.AuthorizeForJob(jobId, DT.Permission.Full); // ... or job owner
+          if (job != null) {            
 
             // note: allow solely state changes from "Online" to "StatisticsPending" = deletion request by user for HiveStatisticGenerator            
@@ -563,6 +553,7 @@
 
       RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
-      var currentUserId = UserManager.CurrentUserId;
+      // check if user is an admin, or granted to administer a job-parenting project, or job owner
+      foreach (var jobId in jobIds)
+          AuthorizationManager.AuthorizeForJob(jobId, DT.Permission.Full);
 
       var pm = PersistenceManager;
@@ -571,15 +562,7 @@
         var projectDao = pm.ProjectDao;
         pm.UseTransaction(() => {
-          var administrationGrantedProjects = projectDao
-            .GetAdministrationGrantedProjectsForUser(currentUserId)
-            .ToList();
-
           foreach (var jobId in jobIds) {
             var job = jobDao.GetById(jobId);
             if (job != null) {
-
-              // check if user is an admin, or granted to administer a job-parenting project,...
-              if (!isAdministrator && !administrationGrantedProjects.Contains(job.Project))
-                AuthorizationManager.AuthorizeForJob(jobId, DT.Permission.Full); // ... or job owner
 
               // note: allow solely state changes from "Online" to "StatisticsPending" = deletion request by user for HiveStatisticGenerator
Index: /trunk/HeuristicLab.Services.Hive/3.3/Manager/AuthorizationManager.cs
===================================================================
--- /trunk/HeuristicLab.Services.Hive/3.3/Manager/AuthorizationManager.cs	(revision 16208)
+++ /trunk/HeuristicLab.Services.Hive/3.3/Manager/AuthorizationManager.cs	(revision 16209)
@@ -38,4 +38,5 @@
     private const string NOT_AUTHORIZED_PROJECTRESOURCE = "Selected project is not authorized to access the requested resource";
     private const string USER_NOT_IDENTIFIED = "User could not be identified";
+    private const string JOB_NOT_EXISTENT = "Queried job could not be found";
     private const string TASK_NOT_EXISTENT = "Queried task could not be found";
     private const string PROJECT_NOT_EXISTENT = "Queried project could not be found";
@@ -60,9 +61,19 @@
     public void AuthorizeForTask(Guid taskId, DT.Permission requiredPermission) {
       if (ServiceLocator.Instance.RoleVerifier.IsInRole(HiveRoles.Slave)) return; // slave-users can access all tasks
+      if (ServiceLocator.Instance.RoleVerifier.IsInRole(HiveRoles.Administrator)) return; // administrator can access all tasks
+      var currentUserId = UserManager.CurrentUserId;
       var pm = PersistenceManager;
       var taskDao = pm.TaskDao;
+      var projectDao = pm.ProjectDao;
       pm.UseTransaction(() => {
         var task = taskDao.GetById(taskId);
         if (task == null) throw new SecurityException(TASK_NOT_EXISTENT);
+
+        // check if user is granted to administer a job-parenting project
+        var administrationGrantedProjects = projectDao
+          .GetAdministrationGrantedProjectsForUser(currentUserId)
+          .ToList();
+        if (administrationGrantedProjects.Contains(task.Job.Project)) return;
+
         AuthorizeJob(pm, task.JobId, requiredPermission);
       });
@@ -70,6 +81,19 @@
 
     public void AuthorizeForJob(Guid jobId, DT.Permission requiredPermission) {
-      var pm = PersistenceManager;
-      pm.UseTransaction(() => {
+      if (ServiceLocator.Instance.RoleVerifier.IsInRole(HiveRoles.Administrator)) return; // administrator can access all jobs
+      var currentUserId = UserManager.CurrentUserId;
+      var pm = PersistenceManager;
+      var jobDao = pm.JobDao;
+      var projectDao = pm.ProjectDao;
+      pm.UseTransaction(() => {
+        var job = jobDao.GetById(jobId);
+        if(job == null) throw new SecurityException(JOB_NOT_EXISTENT);
+
+        // check if user is granted to administer a job-parenting project
+        var administrationGrantedProjects = projectDao
+          .GetAdministrationGrantedProjectsForUser(currentUserId)
+          .ToList();
+        if (administrationGrantedProjects.Contains(job.Project)) return;
+
         AuthorizeJob(pm, jobId, requiredPermission);
       });
