Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2839_HiveProjectManagement/HeuristicLab.Services.Hive/3.3/HiveService.cs @ 16007

Last change on this file since 16007 was 15995, checked in by jzenisek, 6 years ago

#2839: adapted illustration of project and resource ancestry in HiveAdministrator and HiveJobAdministrator

File size: 78.7 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using System.Security;
26using System.ServiceModel;
27using HeuristicLab.Services.Access;
28using HeuristicLab.Services.Hive.DataAccess.Interfaces;
29using HeuristicLab.Services.Hive.DataTransfer;
30using HeuristicLab.Services.Hive.Manager;
31using HeuristicLab.Services.Hive.ServiceContracts;
32using DA = HeuristicLab.Services.Hive.DataAccess;
33using DT = HeuristicLab.Services.Hive.DataTransfer;
34
35namespace HeuristicLab.Services.Hive {
36  /// <summary>
37  /// Implementation of the Hive service (interface <see cref="IHiveService"/>).
38  /// We need 'IgnoreExtensionDataObject' Attribute for the slave to work.
39  /// </summary>
40  [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, IgnoreExtensionDataObject = true)]
41  [HiveOperationContextBehavior]
42  public class HiveService : IHiveService {
43    private const string NOT_AUTHORIZED_PROJECTRESOURCE = "Selected project is not authorized to access the requested resource";
44    private const string NOT_AUTHORIZED_USERPROJECT = "Current user is not authorized to access the requested project";
45    private const string NOT_AUTHORIZED_PROJECTOWNER = "The set user is not authorized to own the project";
46    private const string NO_JOB_UPDATE_POSSIBLE = "This job has already been flagged for deletion, thus, it can not be updated anymore.";
47
48    private static readonly DA.TaskState[] CompletedStates = { DA.TaskState.Finished, DA.TaskState.Aborted, DA.TaskState.Failed };
49
50    private IPersistenceManager PersistenceManager {
51      get { return ServiceLocator.Instance.PersistenceManager; }
52    }
53
54    private IUserManager UserManager {
55      get { return ServiceLocator.Instance.UserManager; }
56    }
57
58    private IRoleVerifier RoleVerifier {
59      get { return ServiceLocator.Instance.RoleVerifier; }
60    }
61
62    private IAuthorizationManager AuthorizationManager {
63      get { return ServiceLocator.Instance.AuthorizationManager; }
64    }
65    private IEventManager EventManager {
66      get { return ServiceLocator.Instance.EventManager; }
67    }
68    private HeartbeatManager HeartbeatManager {
69      get { return ServiceLocator.Instance.HeartbeatManager; }
70    }
71
72    #region Task Methods
73
74    public Guid AddTask(DT.Task task, DT.TaskData taskData) {
75      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
76      AuthorizationManager.AuthorizeForJob(task.JobId, DT.Permission.Full);
77      var pm = PersistenceManager;
78      using (new PerformanceLogger("AddTask")) {
79        var taskDao = pm.TaskDao;
80        var stateLogDao = pm.StateLogDao;
81        var newTask = task.ToEntity();
82        newTask.JobData = taskData.ToEntity();
83        newTask.JobData.LastUpdate = DateTime.Now;
84        newTask.State = DA.TaskState.Waiting;
85        return pm.UseTransaction(() => {
86          taskDao.Save(newTask);
87          pm.SubmitChanges();
88          stateLogDao.Save(new DA.StateLog {
89            State = DA.TaskState.Waiting,
90            DateTime = DateTime.Now,
91            TaskId = newTask.TaskId,
92            UserId = UserManager.CurrentUserId,
93            SlaveId = null,
94            Exception = null
95          });
96          pm.SubmitChanges();
97          return newTask.TaskId;
98        }, false, true);
99      }
100    }
101
102    public Guid AddChildTask(Guid parentTaskId, DT.Task task, DT.TaskData taskData) {
103      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
104      task.ParentTaskId = parentTaskId;
105      return AddTask(task, taskData);
106    }
107
108    public DT.Task GetTask(Guid taskId) {
109      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
110      AuthorizationManager.AuthorizeForTask(taskId, Permission.Read);
111      var pm = PersistenceManager;
112      using (new PerformanceLogger("GetTask")) {
113        var taskDao = pm.TaskDao;
114        return pm.UseTransaction(() => {
115          var task = taskDao.GetById(taskId);
116          return task.ToDto();
117        });
118      }
119    }
120
121    public IEnumerable<DT.LightweightTask> GetLightweightJobTasks(Guid jobId) {
122      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
123      AuthorizationManager.AuthorizeForJob(jobId, Permission.Read);
124      var pm = PersistenceManager;
125      using (new PerformanceLogger("GetLightweightJobTasks")) {
126        var taskDao = pm.TaskDao;
127        return pm.UseTransaction(() => {
128          return taskDao.GetByJobId(jobId)
129            .ToList()
130            .Select(x => new DT.LightweightTask {
131              Id = x.TaskId,
132              ExecutionTime = TimeSpan.FromMilliseconds(x.ExecutionTimeMs),
133              ParentTaskId = x.ParentTaskId,
134              StateLog = x.StateLogs.OrderBy(y => y.DateTime)
135                                    .Select(z => z.ToDto())
136                                    .ToList(),
137              State = x.State.ToDto(),
138              Command = x.Command.ToDto(),
139              LastTaskDataUpdate = x.JobData.LastUpdate
140            })
141            .ToList();
142        }, false, true);
143      }
144    }
145
146    public IEnumerable<DT.LightweightTask> GetLightweightJobTasksWithoutStateLog(Guid jobId) {
147      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
148      AuthorizationManager.AuthorizeForJob(jobId, Permission.Read);
149      var pm = PersistenceManager;
150      using (new PerformanceLogger("GetLightweightJobTasksWithoutStateLog")) {
151        var taskDao = pm.TaskDao;
152        return pm.UseTransaction(() => {
153          return taskDao.GetByJobId(jobId)
154            .ToList()
155            .Select(x => new DT.LightweightTask {
156              Id = x.TaskId,
157              ExecutionTime = TimeSpan.FromMilliseconds(x.ExecutionTimeMs),
158              ParentTaskId = x.ParentTaskId,
159              StateLog = new List<DT.StateLog>(),
160              State = x.State.ToDto(),
161              Command = x.Command.ToDto(),
162              LastTaskDataUpdate = x.JobData.LastUpdate
163            })
164            .ToList();
165        }, false, true);
166      }
167    }
168
169    public DT.TaskData GetTaskData(Guid taskId) {
170      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
171      AuthorizationManager.AuthorizeForTask(taskId, Permission.Read);
172      var pm = PersistenceManager;
173      using (new PerformanceLogger("GetTaskData")) {
174        var taskDataDao = pm.TaskDataDao;
175        return pm.UseTransaction(() => taskDataDao.GetById(taskId).ToDto());
176      }
177    }
178
179    public void UpdateTask(DT.Task taskDto) {
180      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
181      AuthorizationManager.AuthorizeForTask(taskDto.Id, Permission.Full);
182      var pm = PersistenceManager;
183      using (new PerformanceLogger("UpdateTask")) {
184        var taskDao = pm.TaskDao;
185        pm.UseTransaction(() => {
186          var task = taskDao.GetById(taskDto.Id);
187          taskDto.CopyToEntity(task);
188          pm.SubmitChanges();
189        });
190      }
191    }
192
193    public void UpdateTaskData(DT.Task taskDto, DT.TaskData taskDataDto) {
194      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
195      AuthorizationManager.AuthorizeForTask(taskDto.Id, Permission.Full);
196      var pm = PersistenceManager;
197      using (new PerformanceLogger("UpdateTaskData")) {
198        var taskDao = pm.TaskDao;
199        var taskDataDao = pm.TaskDataDao;
200        pm.UseTransaction(() => {
201          var task = taskDao.GetById(taskDto.Id);
202          var taskData = taskDataDao.GetById(taskDataDto.TaskId);
203          taskDto.CopyToEntity(task);
204          taskDataDto.CopyToEntity(taskData);
205          taskData.LastUpdate = DateTime.Now;
206          pm.SubmitChanges();
207        });
208      }
209    }
210
211    public DT.Task UpdateTaskState(Guid taskId, DT.TaskState taskState, Guid? slaveId, Guid? userId, string exception) {
212      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
213      AuthorizationManager.AuthorizeForTask(taskId, Permission.Full);
214      var pm = PersistenceManager;
215      using (new PerformanceLogger("UpdateTaskState")) {
216        var taskDao = pm.TaskDao;
217        return pm.UseTransaction(() => {
218          var task = taskDao.GetById(taskId);
219          UpdateTaskState(pm, task, taskState, slaveId, userId, exception);
220          pm.SubmitChanges();
221          return task.ToDto();
222        });
223      }
224    }
225    #endregion
226
227    #region Task Control Methods
228    public void StopTask(Guid taskId) {
229      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
230      AuthorizationManager.AuthorizeForTask(taskId, Permission.Full);
231      var pm = PersistenceManager;
232      using (new PerformanceLogger("StopTask")) {
233        var taskDao = pm.TaskDao;
234        pm.UseTransaction(() => {
235          var task = taskDao.GetById(taskId);
236          if (task.State == DA.TaskState.Calculating || task.State == DA.TaskState.Transferring) {
237            task.Command = DA.Command.Stop;
238          } else if (task.State != DA.TaskState.Aborted
239                     && task.State != DA.TaskState.Finished
240                     && task.State != DA.TaskState.Failed) {
241            UpdateTaskState(pm, task, DT.TaskState.Aborted, null, null, string.Empty);
242          }
243          pm.SubmitChanges();
244        });
245      }
246    }
247
248    public void PauseTask(Guid taskId) {
249      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
250      AuthorizationManager.AuthorizeForTask(taskId, Permission.Full);
251      var pm = PersistenceManager;
252      using (new PerformanceLogger("PauseTask")) {
253        var taskDao = pm.TaskDao;
254        pm.UseTransaction(() => {
255          var task = taskDao.GetById(taskId);
256          if (task.State == DA.TaskState.Calculating || task.State == DA.TaskState.Transferring) {
257            task.Command = DA.Command.Pause;
258          } else if (task.State != DA.TaskState.Paused
259                     && task.State != DA.TaskState.Aborted
260                     && task.State != DA.TaskState.Finished
261                     && task.State != DA.TaskState.Failed) {
262            UpdateTaskState(pm, task, DT.TaskState.Paused, null, null, string.Empty);
263          }
264          pm.SubmitChanges();
265        });
266      }
267    }
268
269    public void RestartTask(Guid taskId) {
270      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
271      AuthorizationManager.AuthorizeForTask(taskId, Permission.Full);
272      var pm = PersistenceManager;
273      using (new PerformanceLogger("RestartTask")) {
274        var taskDao = pm.TaskDao;
275        pm.UseTransaction(() => {
276          var task = taskDao.GetById(taskId);
277          task.Command = null;
278          UpdateTaskState(pm, task, DT.TaskState.Waiting, null, UserManager.CurrentUserId, string.Empty);
279          pm.SubmitChanges();
280        });
281      }
282    }
283    #endregion
284
285    #region Job Methods
286    public DT.Job GetJob(Guid id) {
287      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
288      AuthorizationManager.AuthorizeForJob(id, DT.Permission.Read);
289      var pm = PersistenceManager;
290      using (new PerformanceLogger("GetJob")) {
291        var jobDao = pm.JobDao;
292        var jobPermissionDao = pm.JobPermissionDao;
293        var taskDao = pm.TaskDao;
294        var currentUserId = UserManager.CurrentUserId;
295        return pm.UseTransaction(() => {
296          var job = jobDao.GetById(id).ToDto();
297          if (job != null) {
298            var statistics = taskDao.GetByJobId(job.Id)
299              .GroupBy(x => x.JobId)
300              .Select(x => new {
301                TotalCount = x.Count(),
302                CalculatingCount = x.Count(y => y.State == DA.TaskState.Calculating),
303                FinishedCount = x.Count(y => CompletedStates.Contains(y.State))
304              }).FirstOrDefault();
305            if (statistics != null) {
306              job.JobCount = statistics.TotalCount;
307              job.CalculatingCount = statistics.CalculatingCount;
308              job.FinishedCount = statistics.FinishedCount;
309            }
310            job.OwnerUsername = UserManager.GetUserNameById(job.OwnerUserId);
311            if (currentUserId == job.OwnerUserId) {
312              job.Permission = Permission.Full;
313            } else {
314              var jobPermission = jobPermissionDao.GetByJobAndUserId(job.Id, currentUserId);
315              job.Permission = jobPermission == null ? Permission.NotAllowed : jobPermission.Permission.ToDto();
316            }
317          }
318          return job;
319        });
320      }
321    }
322
323    public IEnumerable<DT.Job> GetJobs() {
324      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
325      var pm = PersistenceManager;
326      using (new PerformanceLogger("GetJobs")) {
327        var jobDao = pm.JobDao;
328        var jobPermissionDao = pm.JobPermissionDao;
329        var taskDao = pm.TaskDao;
330        var currentUserId = UserManager.CurrentUserId;
331        return pm.UseTransaction(() => {
332          var jobs = jobDao.GetAll()
333            .Where(x => x.State == DA.JobState.Online
334                          && (x.OwnerUserId == currentUserId
335                            || x.JobPermissions.Count(y => y.Permission != DA.Permission.NotAllowed
336                              && y.GrantedUserId == currentUserId) > 0)
337                          )
338            .Select(x => x.ToDto())
339            .ToList();
340
341          EvaluateJobs(pm, jobs);
342          return jobs;
343        });
344      }
345    }
346
347    public IEnumerable<DT.Job> GetJobsByProjectId(Guid projectId) {
348      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
349      var pm = PersistenceManager;
350      using (new PerformanceLogger("GetJobsByProjectId")) {
351        var currentUserId = UserManager.CurrentUserId;
352        var projectDao = pm.ProjectDao;
353        var jobDao = pm.JobDao;
354
355        return pm.UseTransaction(() => {
356          // check if user is granted to administer the requested projectId
357          var administrationGrantedProjects = projectDao
358            .GetAdministrationGrantedProjectsForUser(currentUserId)
359            .ToList();
360
361          if(administrationGrantedProjects.Select(x => x.ProjectId).Contains(projectId)) {
362            var jobs = jobDao.GetByProjectId(projectId)
363            .Select(x => x.ToDto())
364            .ToList();
365
366            EvaluateJobs(pm, jobs);
367            return jobs;
368          } else {
369            return Enumerable.Empty<DT.Job>();
370          }
371        });
372      }
373    }
374
375    public IEnumerable<DT.Job> GetJobsByProjectIds(IEnumerable<Guid> projectIds) {
376      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
377      var pm = PersistenceManager;
378      using (new PerformanceLogger("GetJobsByProjectIds")) {
379        var currentUserId = UserManager.CurrentUserId;
380        var projectDao = pm.ProjectDao;
381        var jobDao = pm.JobDao;
382        return pm.UseTransaction(() => {
383          // check for which of requested projectIds the user is granted to administer
384          var administrationGrantedProjectIds = projectDao
385            .GetAdministrationGrantedProjectsForUser(currentUserId)
386            .Select(x => x.ProjectId)
387            .ToList();
388          var requestedAndGrantedProjectIds = projectIds.Intersect(administrationGrantedProjectIds);
389
390          if(requestedAndGrantedProjectIds.Any()) {
391            var jobs = jobDao.GetByProjectIds(requestedAndGrantedProjectIds)
392              .Select(x => x.ToDto())
393              .ToList();
394
395            EvaluateJobs(pm, jobs);
396            return jobs;
397          } else {
398            return Enumerable.Empty<DT.Job>();
399          }
400        });
401      }
402    }
403
404    public Guid AddJob(DT.Job jobDto, IEnumerable<Guid> resourceIds) {
405      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
406      var dateCreated = DateTime.Now;
407      var pm = PersistenceManager;
408
409      // check project availability (cf. duration)
410      CheckProjectAvailability(pm, jobDto.ProjectId, dateCreated);
411
412      // check user - project
413      AuthorizationManager.AuthorizeUserForProjectUse(UserManager.CurrentUserId, jobDto.ProjectId);
414
415      // check project - resources
416      AuthorizationManager.AuthorizeProjectForResourcesUse(jobDto.ProjectId, resourceIds);
417     
418      using (new PerformanceLogger("AddJob")) {
419        var jobDao = pm.JobDao;
420        var userPriorityDao = pm.UserPriorityDao;
421
422        return pm.UseTransaction(() => {
423          var newJob = jobDto.ToEntity();
424          newJob.OwnerUserId = UserManager.CurrentUserId;
425          newJob.DateCreated = dateCreated;
426
427          // add resource assignments
428          if (resourceIds != null && resourceIds.Any()) {           
429            newJob.AssignedJobResources.AddRange(resourceIds.Select(
430              x => new DA.AssignedJobResource {
431                ResourceId = x
432              }));
433          }
434
435          var job = jobDao.Save(newJob);
436          if (userPriorityDao.GetById(newJob.OwnerUserId) == null) {
437            userPriorityDao.Save(new DA.UserPriority {
438              UserId = newJob.OwnerUserId,
439              DateEnqueued = newJob.DateCreated
440            });
441          }
442          pm.SubmitChanges();
443          return job.JobId;
444        });
445      }
446    }
447
448    public void UpdateJob(DT.Job jobDto, IEnumerable<Guid> resourceIds) {
449      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
450      AuthorizationManager.AuthorizeForJob(jobDto.Id, DT.Permission.Full);
451      var pm = PersistenceManager;
452      var dateUpdated = DateTime.Now;
453
454      // check project availability
455      CheckProjectAvailability(pm, jobDto.ProjectId, dateUpdated);
456      // check user - project permission
457      AuthorizationManager.AuthorizeUserForProjectUse(UserManager.CurrentUserId, jobDto.ProjectId);
458      // check project - resources permission
459      AuthorizationManager.AuthorizeProjectForResourcesUse(jobDto.ProjectId, resourceIds);
460
461      using (new PerformanceLogger("UpdateJob")) {
462        bool exists = true;
463        var jobDao = pm.JobDao;
464        pm.UseTransaction(() => {
465          var job = jobDao.GetById(jobDto.Id);
466          if (job == null) {
467            exists = false;
468            job = new DA.Job();
469          } else if(job.State != DA.JobState.Online) {
470            throw new InvalidOperationException(NO_JOB_UPDATE_POSSIBLE);
471          }
472
473
474          jobDto.CopyToEntity(job);
475
476          if (!exists) {
477            // add resource assignments
478            if (resourceIds != null && resourceIds.Any()) {
479              job.AssignedJobResources.AddRange(resourceIds.Select(
480                x => new DA.AssignedJobResource {
481                  ResourceId = x
482              }));
483            }
484            jobDao.Save(job);
485          } else if(resourceIds != null) {
486            var addedJobResourceIds = resourceIds.Except(job.AssignedJobResources.Select(x => x.ResourceId));
487            var removedJobResourceIds = job.AssignedJobResources
488              .Select(x => x.ResourceId)
489              .Except(resourceIds)
490              .ToArray();
491           
492            // remove resource assignments
493            foreach(var rid in removedJobResourceIds) {
494              var ajr = job.AssignedJobResources.Where(x => x.ResourceId == rid).SingleOrDefault();
495              if (ajr != null) job.AssignedJobResources.Remove(ajr);
496            }
497
498            // add resource assignments
499            job.AssignedJobResources.AddRange(addedJobResourceIds.Select(
500              x => new DA.AssignedJobResource {
501                ResourceId = x
502              }));
503          }
504          pm.SubmitChanges();
505        });
506      }
507    }
508
509    public void UpdateJobState(Guid jobId, DT.JobState jobState) {
510      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
511      AuthorizationManager.AuthorizeForJob(jobId, DT.Permission.Full);
512      var pm = PersistenceManager;
513      using (new PerformanceLogger("UpdateJobState")) {
514        var jobDao = pm.JobDao;
515        pm.UseTransaction(() => {
516          var job = jobDao.GetById(jobId);
517          if(job != null) {
518            var jobStateEntity = jobState.ToEntity();
519            // note: allow solely state changes from "Online" to "StatisticsPending" = deletion request by user for HiveStatisticGenerator
520            // and from "StatisticsPending" to "DeletionPending" = deletion request by HiveStatisticGenerator for EventManager
521            if (job.State == DA.JobState.Online && jobStateEntity == DA.JobState.StatisticsPending) {
522              job.State = jobStateEntity;
523              foreach(var task in job.Tasks
524              .Where(x => x.State == DA.TaskState.Waiting
525                || x.State == DA.TaskState.Paused
526                || x.State == DA.TaskState.Offline)) {
527                task.State = DA.TaskState.Aborted;
528              }
529              pm.SubmitChanges();
530            } else if(job.State == DA.JobState.StatisticsPending && jobStateEntity == DA.JobState.DeletionPending) {
531              job.State = jobStateEntity;
532              pm.SubmitChanges();
533            }
534          }
535        });
536      }
537    }
538
539    public void UpdateJobStates(IEnumerable<Guid> jobIds, DT.JobState jobState) {
540      if (jobState != JobState.StatisticsPending) return; // only process requests for "StatisticsPending"
541
542      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
543      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
544      var currentUserId = UserManager.CurrentUserId;
545
546      var pm = PersistenceManager;
547      using (new PerformanceLogger("UpdateJobStates")) {
548        var jobDao = pm.JobDao;
549        var projectDao = pm.ProjectDao;
550        pm.UseTransaction(() => {
551          foreach(var jobId in jobIds) {
552            var job = jobDao.GetById(jobId);
553            if (job != null) {
554
555              var administrationGrantedProjects = projectDao
556                .GetAdministrationGrantedProjectsForUser(currentUserId)
557                .ToList();
558
559              // check if user is granted to administer the job-parenting project
560              if (isAdministrator || administrationGrantedProjects.Contains(job.Project)) {
561                // note: allow solely state changes from "Online" to "StatisticsPending" = deletion request by user for HiveStatisticGenerator
562                if (job.State == DA.JobState.Online) {
563                  job.State = DA.JobState.StatisticsPending;
564                  foreach (var task in job.Tasks
565                  .Where(x => x.State == DA.TaskState.Waiting
566                    || x.State == DA.TaskState.Paused
567                    || x.State == DA.TaskState.Offline)) {
568                      task.State = DA.TaskState.Aborted;
569                  }
570                  pm.SubmitChanges();
571                }
572              }
573            }
574          }
575        });
576      }
577    }
578
579    public IEnumerable<DT.AssignedJobResource> GetAssignedResourcesForJob(Guid jobId) {
580      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
581      AuthorizationManager.AuthorizeForJob(jobId, DT.Permission.Full);
582      var pm = PersistenceManager;
583      var assignedJobResourceDao = pm.AssignedJobResourceDao;
584      using (new PerformanceLogger("GetAssignedResourcesForProject")) {
585        return pm.UseTransaction(() =>
586          assignedJobResourceDao.GetByJobId(jobId)
587          .Select(x => x.ToDto())
588          .ToList()
589        );
590      }
591    }
592    #endregion
593
594    #region JobPermission Methods
595    public void GrantPermission(Guid jobId, Guid grantedUserId, DT.Permission permission) {
596      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
597      AuthorizationManager.AuthorizeForJob(jobId, Permission.Full);
598      var pm = PersistenceManager;
599      using (new PerformanceLogger("GrantPermission")) {
600        var jobPermissionDao = pm.JobPermissionDao;
601        var currentUserId = UserManager.CurrentUserId;
602        pm.UseTransaction(() => {
603          jobPermissionDao.SetJobPermission(jobId, currentUserId, grantedUserId, permission.ToEntity());
604          pm.SubmitChanges();
605        });
606      }
607    }
608
609    public void RevokePermission(Guid jobId, Guid grantedUserId) {
610      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
611      AuthorizationManager.AuthorizeForJob(jobId, Permission.Full);
612      var pm = PersistenceManager;
613      using (new PerformanceLogger("RevokePermission")) {
614        var jobPermissionDao = pm.JobPermissionDao;
615        var currentUserId = UserManager.CurrentUserId;
616        pm.UseTransaction(() => {
617          jobPermissionDao.SetJobPermission(jobId, currentUserId, grantedUserId, DA.Permission.NotAllowed);
618          pm.SubmitChanges();
619        });
620      }
621    }
622
623    public IEnumerable<JobPermission> GetJobPermissions(Guid jobId) {
624      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
625      AuthorizationManager.AuthorizeForJob(jobId, Permission.Full);
626      var pm = PersistenceManager;
627      using (new PerformanceLogger("GetJobPermissions")) {
628        var jobPermissionDao = pm.JobPermissionDao;
629        return pm.UseTransaction(() => jobPermissionDao.GetByJobId(jobId)
630          .Select(x => x.ToDto())
631          .ToList()
632        );
633      }
634    }
635
636    // BackwardsCompatibility3.3
637    #region Backwards compatible code, remove with 3.4
638    public bool IsAllowedPrivileged() {
639      return true;
640    }
641    #endregion
642    #endregion
643
644    #region Login Methods
645    public void Hello(DT.Slave slaveInfo) {
646      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
647      if (UserManager.CurrentUser.UserName != "hiveslave") {
648        slaveInfo.OwnerUserId = UserManager.CurrentUserId;
649      }
650      var pm = PersistenceManager;
651      using (new PerformanceLogger("Hello")) {
652        var slaveDao = pm.SlaveDao;
653        pm.UseTransaction(() => {
654          var slave = slaveDao.GetById(slaveInfo.Id);
655          if (slave == null) {
656            slaveDao.Save(slaveInfo.ToEntity());
657          } else {
658            bool oldIsAllowedToCalculate = slave.IsAllowedToCalculate;
659            Guid? oldParentResourceId = slave.ParentResourceId;
660            slaveInfo.CopyToEntity(slave);
661            slave.IsAllowedToCalculate = oldIsAllowedToCalculate;
662            slave.ParentResourceId = oldParentResourceId;
663            slave.LastHeartbeat = DateTime.Now;
664            slave.SlaveState = DA.SlaveState.Idle;
665          }
666          pm.SubmitChanges();
667        });
668      }
669    }
670
671    public void GoodBye(Guid slaveId) {
672      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
673      var pm = PersistenceManager;
674      using (new PerformanceLogger("GoodBye")) {
675        var slaveDao = pm.SlaveDao;
676        pm.UseTransaction(() => {
677          var slave = slaveDao.GetById(slaveId);
678          if (slave != null) {
679            slave.SlaveState = DA.SlaveState.Offline;
680            pm.SubmitChanges();
681          }
682        });
683      }
684    }
685    #endregion
686
687    #region Heartbeat Methods
688    public List<MessageContainer> Heartbeat(DT.Heartbeat heartbeat) {
689      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
690      List<MessageContainer> result = new List<MessageContainer>();
691      try {
692        using (new PerformanceLogger("ProcessHeartbeat")) {
693          result = HeartbeatManager.ProcessHeartbeat(heartbeat);
694        }
695      } catch (Exception ex) {
696        DA.LogFactory.GetLogger(this.GetType().Namespace).Log(string.Format("Exception processing Heartbeat: {0}", ex));
697      }
698      if (HeuristicLab.Services.Hive.Properties.Settings.Default.TriggerEventManagerInHeartbeat) {
699        TriggerEventManager(false);
700      }
701      return result;
702    }
703    #endregion
704
705    #region Plugin Methods
706    public DT.Plugin GetPlugin(Guid pluginId) {
707      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
708      var pm = PersistenceManager;
709      using (new PerformanceLogger("GetPlugin")) {
710        var pluginDao = pm.PluginDao;
711        return pm.UseTransaction(() => pluginDao.GetById(pluginId).ToDto());
712      }
713    }
714
715    public Guid AddPlugin(DT.Plugin plugin, List<DT.PluginData> pluginData) {
716      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
717      var pm = PersistenceManager;
718      using (new PerformanceLogger("AddPlugin")) {
719        var pluginDao = pm.PluginDao;
720        plugin.UserId = UserManager.CurrentUserId;
721        plugin.DateCreated = DateTime.Now;
722        return pm.UseTransaction(() => {
723          var pluginEntity = pluginDao.GetByHash(plugin.Hash).SingleOrDefault();
724          if (pluginEntity != null) {
725            throw new FaultException<PluginAlreadyExistsFault>(new PluginAlreadyExistsFault(pluginEntity.PluginId));
726          }
727          pluginEntity = plugin.ToEntity();
728          foreach (var data in pluginData) {
729            data.PluginId = default(Guid); // real id will be assigned from linq2sql
730            pluginEntity.PluginData.Add(data.ToEntity());
731          }
732          pluginDao.Save(pluginEntity);
733          pm.SubmitChanges();
734          return pluginEntity.PluginId;
735        });
736      }
737    }
738
739    public IEnumerable<DT.Plugin> GetPlugins() {
740      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
741      var pm = PersistenceManager;
742      using (new PerformanceLogger("GetPlugins")) {
743        var pluginDao = pm.PluginDao;
744        return pm.UseTransaction(() => pluginDao.GetAll()
745          .Where(x => x.Hash != null)
746          .Select(x => x.ToDto())
747          .ToList()
748        );
749      }
750    }
751
752    public IEnumerable<DT.PluginData> GetPluginDatas(List<Guid> pluginIds) {
753      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
754      var pm = PersistenceManager;
755      using (new PerformanceLogger("GetPluginDatas")) {
756        var pluginDataDao = pm.PluginDataDao;
757        return pm.UseTransaction(() => pluginDataDao.GetAll()
758            .Where(x => pluginIds.Contains(x.PluginId))
759            .Select(x => x.ToDto())
760            .ToList()
761        );
762      }
763    }
764    #endregion
765
766    #region Project Methods
767    public Guid AddProject(DT.Project projectDto) {
768      if (projectDto == null || projectDto.Id != Guid.Empty) return Guid.Empty;
769      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
770      // check if current (non-admin) user is owner of one of projectDto's-parents
771      // note: non-admin users are not allowed to administer root projects (i.e. projects without parental entry)
772      if (!RoleVerifier.IsInRole(HiveRoles.Administrator)) {
773        if(projectDto != null && projectDto.ParentProjectId.HasValue) {
774          AuthorizationManager.AuthorizeForProjectAdministration(projectDto.ParentProjectId.Value, false);
775        } else {
776          throw new SecurityException(NOT_AUTHORIZED_USERPROJECT);
777        }
778      }
779
780      // check that non-admins can not be set as owner of root projects
781      if (projectDto != null && !projectDto.ParentProjectId.HasValue) {
782        var owner = UserManager.GetUserById(projectDto.OwnerUserId);
783        if (owner == null || !RoleVerifier.IsUserInRole(owner.UserName, HiveRoles.Administrator)) {
784          throw new SecurityException(NOT_AUTHORIZED_PROJECTOWNER);
785        }
786      }
787
788      var pm = PersistenceManager;
789      using (new PerformanceLogger("AddProject")) {
790        var projectDao = pm.ProjectDao;
791
792        return pm.UseTransaction(() => {
793          var project = projectDao.Save(projectDto.ToEntity());
794          project.ProjectPermissions.Clear();
795          project.ProjectPermissions.Add(new DA.ProjectPermission {
796            GrantedUserId = project.OwnerUserId,
797            GrantedByUserId = UserManager.CurrentUserId
798          });
799
800          pm.SubmitChanges();
801          return project.ProjectId;
802        });
803      }
804    }
805
806    public void UpdateProject(DT.Project projectDto) {
807      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
808      // check if current (non-admin) user is owner of the project or the projectDto's-parents
809      // note: non-admin users are not allowed to administer root projects (i.e. projects without parental entry)
810      if (!RoleVerifier.IsInRole(HiveRoles.Administrator)) {
811        if (projectDto != null && projectDto.ParentProjectId.HasValue) {
812          AuthorizationManager.AuthorizeForProjectAdministration(projectDto.Id, false);
813        } else {
814          throw new SecurityException(NOT_AUTHORIZED_USERPROJECT);
815        }
816      }
817
818      // check that non-admins can not be set as owner of root projects
819      if(projectDto != null && !projectDto.ParentProjectId.HasValue) {
820        var owner = UserManager.GetUserById(projectDto.OwnerUserId);
821        if(owner == null || !RoleVerifier.IsUserInRole(owner.UserName, HiveRoles.Administrator)) {
822          throw new SecurityException(NOT_AUTHORIZED_PROJECTOWNER);
823        }
824      }
825     
826      var pm = PersistenceManager;
827      using (new PerformanceLogger("UpdateProject")) {
828        var projectDao = pm.ProjectDao;
829        var assignedJobResourceDao = pm.AssignedJobResourceDao;
830        pm.UseTransaction(() => {
831          var project = projectDao.GetById(projectDto.Id);
832          if (project != null) { // update existent project
833            var formerOwnerId = project.OwnerUserId;
834            projectDto.CopyToEntity(project);
835
836            // if owner has changed...
837            if(formerOwnerId != projectDto.OwnerUserId) {
838              // OBSOLETE: former owner looses permission and project-related jobs
839              //var formerPermissionItem = project.ProjectPermissions.Where(x => x.GrantedUserId == formerOwnerId).FirstOrDefault();
840              //if (formerPermissionItem != null) {
841              //  // remove permissions
842              //  project.ProjectPermissions.Remove(formerPermissionItem);
843              //  // remove jobs if former owner is no member of a still permitted group
844              //  var ugt = GetUserGroupTree();
845              //  var permittedGuids = new HashSet<Guid>(); // User- and Group-Guids
846              //  // get all member-Guids of all still permitted groups
847              //  foreach (var item in project.ProjectPermissions) {
848              //    permittedGuids.Add(item.GrantedUserId);
849              //    if(ugt.ContainsKey(item.GrantedUserId)) {
850              //      ugt[item.GrantedUserId].ToList().ForEach(x => permittedGuids.Add(x));
851              //    }
852
853              //    // check if former owner Guid is in Member-Guids
854              //    // if yes: do nothing, if not do:
855              //    if (!permittedGuids.Contains(formerOwnerId)) {
856              //      assignedJobResourceDao.DeleteByProjectIdAndUserIds(project.ProjectId, new List<Guid> { formerOwnerId });
857              //    }
858              //  }
859              //}
860              // Add permission for new owner if not already done
861              if(!project.ProjectPermissions
862                .Select(pp => pp.GrantedUserId)
863                .Contains(projectDto.OwnerUserId)) {
864                project.ProjectPermissions.Add(new DA.ProjectPermission {
865                  GrantedUserId = projectDto.OwnerUserId,
866                  GrantedByUserId = UserManager.CurrentUserId
867                });
868              }
869            }
870
871          } else { // save new project
872            var newProject = projectDao.Save(projectDto.ToEntity());
873            newProject.ProjectPermissions.Clear();
874            newProject.ProjectPermissions.Add(new DA.ProjectPermission {
875              GrantedUserId = projectDto.OwnerUserId,
876              GrantedByUserId = UserManager.CurrentUserId
877            });
878          }
879          pm.SubmitChanges();
880        });
881      }
882    }
883
884    public void DeleteProject(Guid projectId) {
885      if (projectId == Guid.Empty) return;
886      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
887      // check if current (non-admin) user is owner of one of the projectDto's-parents
888      // note: non-admin users are not allowed to administer root projects (i.e. projects without parental entry)
889      if (!RoleVerifier.IsInRole(HiveRoles.Administrator)) {       
890        AuthorizationManager.AuthorizeForProjectAdministration(projectId, true);
891      }
892
893      var pm = PersistenceManager;
894      using (new PerformanceLogger("DeleteProject")) {
895        var projectDao = pm.ProjectDao;
896        var jobDao = pm.JobDao;
897        var assignedJobResourceDao = pm.AssignedJobResourceDao;
898        pm.UseTransaction(() => {
899          var projectIds = new HashSet<Guid> { projectId };
900          projectIds.Union(projectDao.GetChildProjectIdsById(projectId));
901
902          var jobs = jobDao.GetByProjectIds(projectIds)
903            .Select(x => x.ToDto())
904            .ToList();
905
906          if(jobs.Count > 0) {
907            throw new InvalidOperationException("There are " + jobs.Count + " job(s) using this project and/or child-projects. It is necessary to delete them before the project.");
908          } else {
909            assignedJobResourceDao.DeleteByProjectIds(projectIds);
910            projectDao.DeleteByIds(projectIds);
911            pm.SubmitChanges();
912          }
913        });
914      }
915    }
916
917    // query granted project for use (i.e. to calculate on)
918    public DT.Project GetProject(Guid projectId) {
919      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
920      var pm = PersistenceManager;
921      using (new PerformanceLogger("GetProject")) {
922        var projectDao = pm.ProjectDao;
923        var currentUserId = UserManager.CurrentUserId;
924        var userAndGroupIds = new List<Guid> { currentUserId };
925        userAndGroupIds.AddRange(UserManager.GetUserGroupIdsOfUser(currentUserId));
926        return pm.UseTransaction(() => {
927          return projectDao.GetUsageGrantedProjectsForUser(userAndGroupIds)
928          .Where(x => x.ProjectId == projectId)
929          .Select(x => x.ToDto())
930          .SingleOrDefault();
931        });
932      }
933    }
934
935    // query granted projects for use (i.e. to calculate on)
936    public IEnumerable<DT.Project> GetProjects() {
937      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
938      var pm = PersistenceManager;
939      using (new PerformanceLogger("GetProjects")) {
940        var projectDao = pm.ProjectDao;
941        var currentUserId = UserManager.CurrentUserId;
942        var userAndGroupIds = new List<Guid> { currentUserId };
943        userAndGroupIds.AddRange(UserManager.GetUserGroupIdsOfUser(currentUserId));
944        return pm.UseTransaction(() => {
945          var projects = projectDao.GetUsageGrantedProjectsForUser(userAndGroupIds)
946            .Select(x => x.ToDto()).ToList();
947          var now = DateTime.Now;
948          return projects.Where(x => x.StartDate <= now && (x.EndDate == null || x.EndDate >= now)).ToList();
949        });
950      }
951    }
952
953    public IEnumerable<DT.Project> GetProjectsForAdministration() {
954      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
955      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
956      var pm = PersistenceManager;
957      using (new PerformanceLogger("GetProjectsForAdministration")) {
958        var projectDao = pm.ProjectDao;
959       
960        return pm.UseTransaction(() => {
961          if(isAdministrator) {
962            return projectDao.GetAll().Select(x => x.ToDto()).ToList();
963          } else {
964            var currentUserId = UserManager.CurrentUserId;
965            return projectDao.GetAdministrationGrantedProjectsForUser(currentUserId)
966              .Select(x => x.ToDto()).ToList();
967
968          }
969        });
970      }
971    }
972
973    public IDictionary<Guid, HashSet<Guid>> GetProjectGenealogy() {
974      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
975      var pm = PersistenceManager;
976      using(new PerformanceLogger("GetProjectGenealogy")) {
977        var projectDao = pm.ProjectDao;
978        var projectAncestors = new Dictionary<Guid, HashSet<Guid>>();
979        return pm.UseTransaction(() => {
980          var projects = projectDao.GetAll().ToList();
981          projects.ForEach(p => projectAncestors.Add(p.ProjectId, new HashSet<Guid>()));
982          foreach (var p in projects) {
983            var parentProject = p.ParentProject;
984            while(parentProject != null) {
985              projectAncestors[p.ProjectId].Add(parentProject.ProjectId);
986              parentProject = parentProject.ParentProject;
987            }
988          }
989          return projectAncestors;
990        });
991      }
992    }
993
994    public IDictionary<Guid, string> GetProjectNames() {
995      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
996      var pm = PersistenceManager;
997      using (new PerformanceLogger("GetProjectNames")) {
998        var projectDao = pm.ProjectDao;
999        var projectNames = new Dictionary<Guid, string>();
1000        return pm.UseTransaction(() => {
1001          projectDao
1002            .GetAll().ToList()
1003            .ForEach(p=> projectNames.Add(p.ProjectId, p.Name));
1004          return projectNames;
1005        });
1006      }
1007    }
1008    #endregion
1009
1010    #region ProjectPermission Methods
1011    public void SaveProjectPermissions(Guid projectId, List<Guid> grantedUserIds, bool reassign, bool cascading, bool reassignCascading) {
1012      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1013      if (projectId == null || grantedUserIds == null) return;
1014      AuthorizationManager.AuthorizeForProjectAdministration(projectId, false);
1015      var pm = PersistenceManager;
1016      using (new PerformanceLogger("SaveProjectPermissions")) {
1017        var projectDao = pm.ProjectDao;
1018        var projectPermissionDao = pm.ProjectPermissionDao;
1019        var assignedJobResourceDao = pm.AssignedJobResourceDao;
1020
1021        pm.UseTransaction(() => {
1022          var project = projectDao.GetById(projectId);
1023          if (project == null) return;
1024          var projectPermissions = project.ProjectPermissions.Select(x => x.GrantedUserId).ToArray();
1025
1026          // guarantee that project owner is always permitted
1027          if(!grantedUserIds.Contains(project.OwnerUserId)) {
1028            grantedUserIds.Add(project.OwnerUserId);
1029          }
1030
1031          //var addedPermissions = grantedUserIds.Except(projectPermissions);
1032          var removedPermissions = projectPermissions.Except(grantedUserIds);
1033
1034          // remove job assignments and project permissions
1035          if (reassign) {
1036            assignedJobResourceDao.DeleteByProjectId(project.ProjectId);
1037            project.ProjectPermissions.Clear();
1038          } else {
1039
1040            var ugt = GetUserGroupTree();
1041            var permittedGuids = new HashSet<Guid>(); // User- and Group-Guids
1042            var notpermittedGuids = new HashSet<Guid>();
1043
1044            // remove job assignments:
1045            // (1) get all member-Guids of all still or fresh permitted user/groups
1046            foreach (var item in grantedUserIds) {
1047              permittedGuids.Add(item);
1048              if (ugt.ContainsKey(item)) {
1049                ugt[item].ToList().ForEach(x => permittedGuids.Add(x));
1050              }
1051            }
1052
1053            // (2) get all member-Guids of users and groups in removedPermissions
1054            foreach (var item in removedPermissions) {
1055              notpermittedGuids.Add(item);
1056              if (ugt.ContainsKey(item)) {
1057                ugt[item].ToList().ForEach(x => notpermittedGuids.Add(x));
1058              }
1059            }
1060
1061            // (3) get all Guids which are in removedPermissions but not in grantedUserIds
1062            var definitelyNotPermittedGuids = notpermittedGuids.Except(permittedGuids);
1063
1064            // (4) delete jobs of those
1065            assignedJobResourceDao.DeleteByProjectIdAndUserIds(project.ProjectId, definitelyNotPermittedGuids);
1066
1067
1068            // remove project permissions
1069            foreach (var item in project.ProjectPermissions
1070              .Where(x => removedPermissions.Contains(x.GrantedUserId))
1071              .ToList()) {
1072              project.ProjectPermissions.Remove(item);
1073            }
1074          }
1075          pm.SubmitChanges();
1076
1077          // add project permissions
1078          foreach (var id in grantedUserIds) {
1079            if(project.ProjectPermissions.All(x => x.GrantedUserId != id)) {
1080              project.ProjectPermissions.Add(new DA.ProjectPermission {
1081                GrantedUserId = id,
1082                GrantedByUserId = UserManager.CurrentUserId
1083              });
1084            }
1085          }
1086          pm.SubmitChanges();
1087
1088          if (cascading) {
1089            var childProjects = projectDao.GetChildProjectsById(projectId).ToList();
1090            var childProjectIds = childProjects.Select(x => x.ProjectId).ToList();
1091
1092            // remove job assignments
1093            if (reassignCascading) {
1094              assignedJobResourceDao.DeleteByProjectIds(childProjectIds);
1095            } else {
1096              assignedJobResourceDao.DeleteByProjectIdsAndUserIds(childProjectIds, removedPermissions);
1097            }
1098
1099            foreach(var p in childProjects) {
1100              var cpAssignedPermissions = p.ProjectPermissions.Select(x => x.GrantedUserId).ToList();
1101              // guarantee that project owner is always permitted
1102              if (!cpAssignedPermissions.Contains(p.OwnerUserId)) {
1103                cpAssignedPermissions.Add(p.OwnerUserId);
1104              }
1105              var cpRemovedPermissions = cpAssignedPermissions.Where(x => x != p.OwnerUserId).Except(grantedUserIds);
1106
1107              // remove left-over job assignments (for non-reassignments)
1108              if(!reassignCascading) {
1109                assignedJobResourceDao.DeleteByProjectIdAndUserIds(p.ProjectId, cpRemovedPermissions);
1110              }
1111
1112              // remove project permissions
1113              if (reassignCascading) {
1114                p.ProjectPermissions.Clear();
1115              } else {
1116                foreach(var item in p.ProjectPermissions
1117                  .Where(x => x.GrantedUserId != p.OwnerUserId
1118                    && (removedPermissions.Contains(x.GrantedUserId) || cpRemovedPermissions.Contains(x.GrantedUserId)))
1119                  .ToList()) {
1120                  p.ProjectPermissions.Remove(item);
1121                }
1122              }
1123              pm.SubmitChanges();
1124
1125              // add project permissions
1126              var cpGrantedUserIds = new HashSet<Guid>(grantedUserIds);
1127              cpGrantedUserIds.Add(p.OwnerUserId);
1128
1129              foreach (var id in cpGrantedUserIds) {
1130                if (p.ProjectPermissions.All(x => x.GrantedUserId != id)) {
1131                  p.ProjectPermissions.Add(new DA.ProjectPermission {
1132                    GrantedUserId = id,
1133                    GrantedByUserId = UserManager.CurrentUserId
1134                  });
1135                }
1136              }
1137            }
1138          }
1139          pm.SubmitChanges();
1140        });
1141      }
1142    }
1143
1144    //private void GrantProjectPermissions(Guid projectId, List<Guid> grantedUserIds, bool cascading) {
1145    //  throw new NotImplementedException();
1146    //}
1147
1148    //private void RevokeProjectPermissions(Guid projectId, List<Guid> grantedUserIds, bool cascading) {
1149    //  RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1150    //  if (projectId == null || grantedUserIds == null || !grantedUserIds.Any()) return;
1151    //  AuthorizationManager.AuthorizeForProjectAdministration(projectId, false);
1152    //  var pm = PersistenceManager;
1153    //  using (new PerformanceLogger("RevokeProjectPermissions")) {
1154    //    var projectPermissionDao = pm.ProjectPermissionDao;
1155    //    var projectDao = pm.ProjectDao;
1156    //    var assignedJobResourceDao = pm.AssignedJobResourceDao;
1157    //    pm.UseTransaction(() => {
1158    //      if (cascading) {
1159    //        var childProjectIds = projectDao.GetChildProjectIdsById(projectId).ToList();
1160    //        projectPermissionDao.DeleteByProjectIdsAndGrantedUserIds(childProjectIds, grantedUserIds);
1161    //        assignedJobResourceDao.DeleteByProjectIdsAndUserIds(childProjectIds, grantedUserIds);
1162    //      }
1163    //      projectPermissionDao.DeleteByProjectIdAndGrantedUserIds(projectId, grantedUserIds);
1164    //      assignedJobResourceDao.DeleteByProjectIdAndUserIds(projectId, grantedUserIds);
1165    //      pm.SubmitChanges();
1166    //    });
1167    //  }
1168    //}
1169
1170    public IEnumerable<DT.ProjectPermission> GetProjectPermissions(Guid projectId) {
1171      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1172      AuthorizationManager.AuthorizeForProjectAdministration(projectId, false);
1173      var pm = PersistenceManager;
1174      using (new PerformanceLogger("GetProjectPermissions")) {
1175        var projectPermissionDao = pm.ProjectPermissionDao;
1176        return pm.UseTransaction(() => projectPermissionDao.GetByProjectId(projectId)
1177          .Select(x => x.ToDto())
1178          .ToList()
1179        );
1180      }
1181    }
1182    #endregion
1183
1184    #region AssignedProjectResource Methods
1185    // basic: remove and add assignments (resourceIds) to projectId and its depending jobs
1186    // reassign: clear all assignments from project and its depending jobs, before adding new ones (resourceIds)
1187    // cascading: "basic" mode for child-projects
1188    // reassignCascading: "reassign" mode for child-projects
1189    public void SaveProjectResourceAssignments(Guid projectId, List<Guid> resourceIds, bool reassign, bool cascading, bool reassignCascading) {
1190      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1191      if (projectId == null || resourceIds == null) return;
1192      AuthorizationManager.AuthorizeForProjectResourceAdministration(projectId, resourceIds);
1193      var pm = PersistenceManager;
1194      using (new PerformanceLogger("SaveProjectResourceAssignments")) {
1195        var projectDao = pm.ProjectDao;
1196        var assignedProjectResourceDao = pm.AssignedProjectResourceDao;
1197        var assignedJobResourceDao = pm.AssignedJobResourceDao;
1198        pm.UseTransaction(() => {
1199          var project = projectDao.GetById(projectId);
1200          var assignedResources = project.AssignedProjectResources.Select(x => x.ResourceId).ToArray();
1201          var removedAssignments = assignedResources.Except(resourceIds);
1202
1203          // remove job and project assignments
1204          if (reassign) {
1205            assignedJobResourceDao.DeleteByProjectId(project.ProjectId);
1206            project.AssignedProjectResources.Clear();
1207          } else {
1208            assignedJobResourceDao.DeleteByProjectIdAndResourceIds(projectId, removedAssignments);
1209            foreach (var item in project.AssignedProjectResources
1210              .Where(x => removedAssignments.Contains(x.ResourceId))
1211              .ToList()) {
1212              project.AssignedProjectResources.Remove(item);
1213            }
1214          }
1215          pm.SubmitChanges();
1216
1217          // add project assignments
1218          foreach (var id in resourceIds) {
1219            if (project.AssignedProjectResources.All(x => x.ResourceId != id)) {
1220              project.AssignedProjectResources.Add(new DA.AssignedProjectResource {
1221                ResourceId = id
1222              });
1223            }
1224          }
1225          pm.SubmitChanges();
1226
1227          if (cascading) {
1228            var childProjects = projectDao.GetChildProjectsById(projectId).ToList();
1229            var childProjectIds = childProjects.Select(x => x.ProjectId).ToList();
1230
1231            // remove job assignments
1232            if (reassignCascading) {
1233              assignedJobResourceDao.DeleteByProjectIds(childProjectIds);
1234            } else {
1235              assignedJobResourceDao.DeleteByProjectIdsAndResourceIds(childProjectIds, removedAssignments);
1236            }
1237            foreach (var p in childProjects) {
1238              var cpAssignedResources = p.AssignedProjectResources.Select(x => x.ResourceId).ToArray();
1239              var cpRemovedAssignments = cpAssignedResources.Except(resourceIds);
1240
1241              // remove left-over job assignments (for non-reassignments)
1242              if(!reassignCascading) {
1243                assignedJobResourceDao.DeleteByProjectIdAndResourceIds(p.ProjectId, cpRemovedAssignments);
1244              }
1245
1246              // remove project assignments
1247              if (reassignCascading) {
1248                p.AssignedProjectResources.Clear();
1249              } else {
1250                foreach (var item in p.AssignedProjectResources
1251                  .Where(x => removedAssignments.Contains(x.ResourceId) || cpRemovedAssignments.Contains(x.ResourceId))
1252                  .ToList()) {
1253                  p.AssignedProjectResources.Remove(item);
1254                }
1255              }
1256              pm.SubmitChanges();
1257
1258              // add project assignments
1259              foreach (var id in resourceIds) {
1260                if(p.AssignedProjectResources.All(x => x.ResourceId != id)) {
1261                  p.AssignedProjectResources.Add(new DA.AssignedProjectResource {
1262                    ResourceId = id
1263                  });
1264                }
1265              }
1266            }
1267          }
1268          pm.SubmitChanges();
1269        });
1270      }
1271    }
1272
1273    //private void AssignProjectResources(Guid projectId, List<Guid> resourceIds, bool cascading) {
1274    //  throw new NotImplementedException();
1275    //}
1276
1277    //private void UnassignProjectResources(Guid projectId, List<Guid> resourceIds, bool cascading) {
1278    //  RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1279    //  if (projectId == null || resourceIds == null || !resourceIds.Any()) return;
1280    //  AuthorizationManager.AuthorizeForProjectResourceAdministration(projectId, resourceIds);
1281    //  var pm = PersistenceManager;
1282    //  using (new PerformanceLogger("UnassignProjectResources")) {
1283    //    var assignedProjectResourceDao = pm.AssignedProjectResourceDao;
1284    //    var assignedJobResourceDao = pm.AssignedJobResourceDao;
1285    //    var projectDao = pm.ProjectDao;
1286    //    pm.UseTransaction(() => {
1287    //      if (cascading) {
1288    //        var childProjectIds = projectDao.GetChildProjectIdsById(projectId).ToList();
1289    //        assignedProjectResourceDao.DeleteByProjectIdsAndResourceIds(childProjectIds, resourceIds);
1290    //        assignedJobResourceDao.DeleteByProjectIdsAndResourceIds(childProjectIds, resourceIds);
1291    //      }
1292    //      assignedProjectResourceDao.DeleteByProjectIdAndResourceIds(projectId, resourceIds);
1293    //      assignedJobResourceDao.DeleteByProjectIdAndResourceIds(projectId, resourceIds);
1294    //      pm.SubmitChanges();
1295    //    });
1296    //  }
1297    //}
1298
1299    public IEnumerable<DT.AssignedProjectResource> GetAssignedResourcesForProject(Guid projectId) {
1300      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1301      AuthorizationManager.AuthorizeUserForProjectUse(UserManager.CurrentUserId, projectId);
1302      var pm = PersistenceManager;
1303      using (new PerformanceLogger("GetAssignedResourcesForProject")) {
1304        var assignedProjectResourceDao = pm.AssignedProjectResourceDao;
1305        return pm.UseTransaction(() => assignedProjectResourceDao.GetByProjectId(projectId)
1306          .Select(x => x.ToDto())
1307          .ToList()
1308        );
1309      }
1310    }
1311
1312    public IEnumerable<DT.AssignedProjectResource> GetAssignedResourcesForProjectAdministration(Guid projectId) {
1313      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1314      AuthorizationManager.AuthorizeForProjectAdministration(projectId, false);
1315      var pm = PersistenceManager;
1316      using (new PerformanceLogger("GetAssignedResourcesForProject")) {
1317        var assignedProjectResourceDao = pm.AssignedProjectResourceDao;
1318        return pm.UseTransaction(() => assignedProjectResourceDao.GetByProjectId(projectId)
1319          .Select(x => x.ToDto())
1320          .ToList()
1321        );
1322      }
1323    }
1324
1325    public IEnumerable<DT.AssignedProjectResource> GetAssignedResourcesForProjectsAdministration(IEnumerable<Guid> projectIds) {
1326      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1327      foreach(var id in projectIds)
1328        AuthorizationManager.AuthorizeForProjectAdministration(id, false);
1329
1330      var pm = PersistenceManager;
1331      using (new PerformanceLogger("GetAssignedResourcesForProject")) {
1332        var assignedProjectResourceDao = pm.AssignedProjectResourceDao;
1333        var assignments = new List<DT.AssignedProjectResource>();
1334        pm.UseTransaction(() => {
1335          foreach (var id in projectIds) {
1336            assignments.AddRange(assignedProjectResourceDao.GetByProjectId(id)
1337              .Select(x => x.ToDto()));
1338          }
1339        });
1340        return assignments.Distinct();
1341      }
1342    }
1343
1344    #endregion
1345
1346    #region Slave Methods
1347    public Guid AddSlave(DT.Slave slaveDto) {
1348      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
1349      var pm = PersistenceManager;
1350      using (new PerformanceLogger("AddSlave")) {
1351        var slaveDao = pm.SlaveDao;
1352        return pm.UseTransaction(() => {
1353          var slave = slaveDao.Save(slaveDto.ToEntity());
1354          pm.SubmitChanges();
1355          return slave.ResourceId;
1356        });
1357      }
1358    }
1359
1360    public Guid AddSlaveGroup(DT.SlaveGroup slaveGroupDto) {
1361      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
1362      var pm = PersistenceManager;
1363      using (new PerformanceLogger("AddSlaveGroup")) {
1364        var slaveGroupDao = pm.SlaveGroupDao;
1365        return pm.UseTransaction(() => {
1366          if (slaveGroupDto.Id == Guid.Empty) {
1367            slaveGroupDto.Id = Guid.NewGuid();
1368          }
1369          var slaveGroup = slaveGroupDao.Save(slaveGroupDto.ToEntity());
1370          pm.SubmitChanges();
1371          return slaveGroup.ResourceId;
1372        });
1373      }
1374    }
1375
1376    public DT.Slave GetSlave(Guid slaveId) {
1377      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
1378      var pm = PersistenceManager;
1379      using (new PerformanceLogger("GetSlave")) {
1380        var slaveDao = pm.SlaveDao;
1381        return pm.UseTransaction(() => slaveDao.GetById(slaveId).ToDto());
1382      }
1383    }
1384
1385    // query granted slaves for use (i.e. to calculate on)
1386    public IEnumerable<DT.Slave> GetSlaves() {
1387      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1388      var pm = PersistenceManager;
1389      using (new PerformanceLogger("GetSlaves")) {
1390        var slaveDao = pm.SlaveDao;
1391        var projectDao = pm.ProjectDao;
1392        var assignedProjectResourceDao = pm.AssignedProjectResourceDao;
1393
1394        // collect user information
1395        var currentUserId = UserManager.CurrentUserId;
1396        var userAndGroupIds = new List<Guid> { currentUserId };
1397        userAndGroupIds.AddRange(UserManager.GetUserGroupIdsOfUser(currentUserId));
1398
1399        return pm.UseTransaction(() => {
1400          var slaves = slaveDao.GetAll()
1401            .Select(x => x.ToDto())
1402            .ToList();
1403          var grantedProjectIds = projectDao.GetUsageGrantedProjectsForUser(userAndGroupIds)
1404            .Select(x => x.ProjectId)
1405            .ToList();
1406          var grantedResourceIds = assignedProjectResourceDao.GetAllGrantedResourcesByProjectIds(grantedProjectIds)
1407            .Select(x => x.ResourceId)
1408            .ToList();
1409
1410          return slaves
1411            .Where(x => grantedResourceIds.Contains(x.Id))
1412            .ToList();
1413        });
1414      }
1415    }
1416
1417    // query granted slave groups for use (i.e. to calculate on)
1418    public IEnumerable<DT.SlaveGroup> GetSlaveGroups() {
1419      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1420      var pm = PersistenceManager;
1421      using (new PerformanceLogger("GetSlaveGroups")) {
1422        var slaveGroupDao = pm.SlaveGroupDao;
1423        var projectDao = pm.ProjectDao;
1424        var assignedProjectResourceDao = pm.AssignedProjectResourceDao;
1425
1426        // collect user information
1427        var currentUserId = UserManager.CurrentUserId;
1428        var userAndGroupIds = new List<Guid> { currentUserId };
1429        userAndGroupIds.AddRange(UserManager.GetUserGroupIdsOfUser(currentUserId));
1430
1431        return pm.UseTransaction(() => {
1432          var slaveGroups = slaveGroupDao.GetAll()
1433            .Select(x => x.ToDto())
1434            .ToList();
1435          var grantedProjectIds = projectDao.GetUsageGrantedProjectsForUser(userAndGroupIds)
1436            .Select(x => x.ProjectId)
1437            .ToList();
1438          var grantedResourceIds = assignedProjectResourceDao.GetAllGrantedResourcesByProjectIds(grantedProjectIds)
1439            .Select(x => x.ResourceId)
1440            .ToList();
1441
1442          return slaveGroups
1443            .Where(x => grantedResourceIds.Contains(x.Id))
1444            .ToList();
1445        });
1446      }
1447    }
1448
1449    // query granted slaves for resource administration
1450    public IEnumerable<DT.Slave> GetSlavesForAdministration() {
1451      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1452      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
1453      var pm = PersistenceManager;
1454      using (new PerformanceLogger("GetSlavesForAdministration")) {
1455        var slaveDao = pm.SlaveDao;
1456        var currentUserId = UserManager.CurrentUserId;
1457
1458        if (isAdministrator) {
1459          return pm.UseTransaction(() => {
1460            return slaveDao.GetAll()
1461              .Select(x => x.ToDto())
1462              .ToList();
1463          });
1464        } else {
1465          var slaves = slaveDao.GetAll()
1466            .Select(x => x.ToDto())
1467            .ToList();
1468          var projectDao = pm.ProjectDao;
1469          var assignedProjectResourceDao = pm.AssignedProjectResourceDao;
1470          var projects = projectDao.GetAdministrationGrantedProjectsForUser(currentUserId).ToList();
1471          var resourceIds = assignedProjectResourceDao
1472            .GetAllGrantedResourcesByProjectIds(projects.Select(x => x.ProjectId).ToList())
1473            .Select(x => x.ResourceId)
1474            .ToList();
1475
1476          return slaves
1477            .Where(x => resourceIds.Contains(x.Id))
1478            .ToList();
1479        }
1480      }
1481    }
1482
1483    // query granted slave groups for resource administration
1484    public IEnumerable<DT.SlaveGroup> GetSlaveGroupsForAdministration() {
1485      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1486      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
1487      var pm = PersistenceManager;
1488      using (new PerformanceLogger("GetSlaveGroupsForAdministration")) {
1489        var slaveGroupDao = pm.SlaveGroupDao;
1490        var currentUserId = UserManager.CurrentUserId;
1491
1492        if (isAdministrator) {
1493          return pm.UseTransaction(() => {
1494            return slaveGroupDao.GetAll()
1495              .Select(x => x.ToDto())
1496              .ToList();
1497          });
1498        } else {
1499          var slaveGroups = slaveGroupDao.GetAll()
1500            .Select(x => x.ToDto())
1501            .ToList();
1502          var projectDao = pm.ProjectDao;
1503          var assignedProjectResourceDao = pm.AssignedProjectResourceDao;
1504          var projects = projectDao.GetAdministrationGrantedProjectsForUser(currentUserId).ToList();
1505          var resourceIds = assignedProjectResourceDao
1506            .GetAllGrantedResourcesByProjectIds(projects.Select(x => x.ProjectId).ToList())
1507            .Select(x => x.ResourceId)
1508            .ToList();
1509
1510          return slaveGroups
1511            .Where(x => resourceIds.Contains(x.Id))
1512            .ToList();
1513        }
1514      }
1515    }
1516
1517    public IDictionary<Guid, HashSet<Guid>> GetResourceGenealogy() {
1518      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1519      var pm = PersistenceManager;
1520      using (new PerformanceLogger("GetResourceGenealogy")) {
1521        var resourceDao = pm.ResourceDao;
1522        var resourceAncestors = new Dictionary<Guid, HashSet<Guid>>();
1523        return pm.UseTransaction(() => {
1524          var resources = resourceDao.GetAll().ToList();
1525          resources.ForEach(r => resourceAncestors.Add(r.ResourceId, new HashSet<Guid>()));
1526         
1527          foreach(var r in resources) {
1528            var parentResource = r.ParentResource;
1529            while(parentResource != null) {
1530              resourceAncestors[r.ResourceId].Add(parentResource.ResourceId);
1531              parentResource = parentResource.ParentResource;
1532            }
1533          }
1534          return resourceAncestors;
1535        });
1536      }
1537    }
1538
1539    public IDictionary<Guid, string> GetResourceNames() {
1540      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1541      var pm = PersistenceManager;
1542      using (new PerformanceLogger("GetResourceNames")) {
1543        var resourceDao = pm.ResourceDao;
1544        var resourceNames = new Dictionary<Guid, string>();
1545        return pm.UseTransaction(() => {
1546          resourceDao
1547            .GetAll().ToList()
1548            .ForEach(p => resourceNames.Add(p.ResourceId, p.Name));
1549          return resourceNames;
1550        });
1551      }
1552    }
1553
1554    public void UpdateSlave(DT.Slave slaveDto) {
1555      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1556      if (slaveDto == null) return;
1557      AuthorizationManager.AuthorizeForResourceAdministration(slaveDto.Id);
1558      var pm = PersistenceManager;
1559      using (new PerformanceLogger("UpdateSlave")) {
1560        var slaveDao = pm.SlaveDao;
1561        pm.UseTransaction(() => {
1562          var slave = slaveDao.GetById(slaveDto.Id);
1563          if (slave != null) {
1564            slaveDto.CopyToEntity(slave);
1565          } else {
1566            slaveDao.Save(slaveDto.ToEntity());
1567          }
1568          pm.SubmitChanges();
1569        });
1570      }
1571    }
1572
1573    public void UpdateSlaveGroup(DT.SlaveGroup slaveGroupDto) {
1574      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1575      if (slaveGroupDto == null) return;
1576      AuthorizationManager.AuthorizeForResourceAdministration(slaveGroupDto.Id);
1577      var pm = PersistenceManager;
1578      using (new PerformanceLogger("UpdateSlaveGroup")) {
1579        var slaveGroupDao = pm.SlaveGroupDao;
1580        pm.UseTransaction(() => {
1581          var slaveGroup = slaveGroupDao.GetById(slaveGroupDto.Id);
1582          if (slaveGroup != null) {
1583            slaveGroupDto.CopyToEntity(slaveGroup);
1584          } else {
1585            slaveGroupDao.Save(slaveGroupDto.ToEntity());
1586          }
1587          pm.SubmitChanges();
1588        });
1589      }
1590    }
1591
1592    public void DeleteSlave(Guid slaveId) {
1593      if (slaveId == Guid.Empty) return;
1594      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1595      AuthorizationManager.AuthorizeForResourceAdministration(slaveId);
1596      var pm = PersistenceManager;
1597      using (new PerformanceLogger("DeleteSlave")) {
1598        var slaveDao = pm.SlaveDao;
1599        pm.UseTransaction(() => {
1600          slaveDao.Delete(slaveId);
1601          pm.SubmitChanges();
1602        });
1603      }
1604    }
1605
1606    public void DeleteSlaveGroup(Guid slaveGroupId) {
1607      if (slaveGroupId == Guid.Empty) return;
1608      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1609      AuthorizationManager.AuthorizeForResourceAdministration(slaveGroupId);
1610      var pm = PersistenceManager;
1611      using (new PerformanceLogger("DeleteSlaveGroup")) {
1612        var resourceDao = pm.ResourceDao;
1613        pm.UseTransaction(() => {
1614          var resourceIds = new HashSet<Guid> { slaveGroupId };
1615          resourceIds.Union(resourceDao.GetChildResourceIdsById(slaveGroupId));
1616          resourceDao.DeleteByIds(resourceIds);
1617          pm.SubmitChanges();
1618        });
1619      }
1620    }
1621
1622    public void AddResourceToGroup(Guid slaveGroupId, Guid resourceId) {
1623      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
1624      var pm = PersistenceManager;
1625      using (new PerformanceLogger("AddResourceToGroup")) {
1626        var resourceDao = pm.ResourceDao;
1627        pm.UseTransaction(() => {
1628          var resource = resourceDao.GetById(resourceId);
1629          resource.ParentResourceId = slaveGroupId;
1630          pm.SubmitChanges();
1631        });
1632      }
1633    }
1634
1635    public void RemoveResourceFromGroup(Guid slaveGroupId, Guid resourceId) {
1636      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
1637      var pm = PersistenceManager;
1638      using (new PerformanceLogger("RemoveResourceFromGroup")) {
1639        var resourceDao = pm.ResourceDao;
1640        pm.UseTransaction(() => {
1641          var resource = resourceDao.GetById(resourceId);
1642          resource.ParentResourceId = null;
1643          pm.SubmitChanges();
1644        });
1645      }
1646    }
1647
1648    public Guid GetResourceId(string resourceName) {
1649      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1650      var pm = PersistenceManager;
1651      using (new PerformanceLogger("GetResourceId")) {
1652        var resourceDao = pm.ResourceDao;
1653        return pm.UseTransaction(() => {
1654          var resource = resourceDao.GetByName(resourceName);
1655          return resource != null ? resource.ResourceId : Guid.Empty;
1656        });
1657      }
1658    }
1659
1660    public void TriggerEventManager(bool force) {
1661      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
1662      // use a serializable transaction here to ensure not two threads execute this simultaniously (mutex-lock would not work since IIS may use multiple AppDomains)
1663      bool cleanup;
1664      var pm = PersistenceManager;
1665      using (new PerformanceLogger("TriggerEventManager")) {
1666        cleanup = false;
1667        var lifecycleDao = pm.LifecycleDao;
1668        pm.UseTransaction(() => {
1669          var lastLifecycle = lifecycleDao.GetLastLifecycle();
1670          DateTime lastCleanup = lastLifecycle != null ? lastLifecycle.LastCleanup : DateTime.MinValue;
1671          if (force || DateTime.Now - lastCleanup > HeuristicLab.Services.Hive.Properties.Settings.Default.CleanupInterval) {
1672            lifecycleDao.UpdateLifecycle();
1673            cleanup = true;
1674            pm.SubmitChanges();
1675          }
1676        }, true);
1677      }
1678      if (cleanup) {
1679        EventManager.Cleanup();
1680      }
1681    }
1682
1683    public int GetNewHeartbeatInterval(Guid slaveId) {
1684      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
1685      var pm = PersistenceManager;
1686      using (new PerformanceLogger("GetNewHeartbeatInterval")) {
1687        var slaveDao = pm.SlaveDao;
1688        return pm.UseTransaction(() => {
1689          var slave = slaveDao.GetById(slaveId);
1690          if (slave != null) {
1691            return slave.HbInterval;
1692          }
1693          return -1;
1694        });
1695      }
1696    }
1697    #endregion
1698
1699    #region Downtime Methods
1700    public Guid AddDowntime(DT.Downtime downtimeDto) {
1701      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1702      AuthorizationManager.AuthorizeForResourceAdministration(downtimeDto.ResourceId);
1703      var pm = PersistenceManager;
1704      using (new PerformanceLogger("AddDowntime")) {
1705        var downtimeDao = pm.DowntimeDao;
1706        return pm.UseTransaction(() => {
1707          var downtime = downtimeDao.Save(downtimeDto.ToEntity());
1708          pm.SubmitChanges();
1709          return downtime.ResourceId;
1710        });
1711      }
1712    }
1713
1714    public void DeleteDowntime(Guid downtimeId) {
1715      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1716      var pm = PersistenceManager;
1717      using (new PerformanceLogger("DeleteDowntime")) {
1718        var downtimeDao = pm.DowntimeDao;
1719        pm.UseTransaction(() => {
1720          downtimeDao.Delete(downtimeId);
1721          pm.SubmitChanges();
1722        });
1723      }
1724    }
1725
1726    public void UpdateDowntime(DT.Downtime downtimeDto) {
1727      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1728      AuthorizationManager.AuthorizeForResourceAdministration(downtimeDto.ResourceId);
1729      var pm = PersistenceManager;
1730      using (new PerformanceLogger("UpdateDowntime")) {
1731        var downtimeDao = pm.DowntimeDao;
1732        pm.UseTransaction(() => {
1733          var downtime = downtimeDao.GetById(downtimeDto.Id);
1734          if (downtime != null) {
1735            downtimeDto.CopyToEntity(downtime);
1736          } else {
1737            downtimeDao.Save(downtimeDto.ToEntity());
1738          }
1739          pm.SubmitChanges();
1740        });
1741      }
1742    }
1743
1744    public IEnumerable<DT.Downtime> GetDowntimesForResource(Guid resourceId) {
1745      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1746      var pm = PersistenceManager;
1747      using (new PerformanceLogger("GetDowntimesForResource")) {
1748        var downtimeDao = pm.DowntimeDao;
1749        return pm.UseTransaction(() => downtimeDao.GetByResourceId(resourceId)
1750          .Select(x => x.ToDto())
1751          .ToList()
1752        );
1753      }
1754    }
1755    #endregion
1756
1757    #region User Methods
1758    public string GetUsernameByUserId(Guid userId) {
1759      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1760      var user = UserManager.GetUserById(userId);
1761      return user != null ? user.UserName : null;
1762    }
1763
1764    public Guid GetUserIdByUsername(string username) {
1765      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1766      var user = ServiceLocator.Instance.UserManager.GetUserByName(username);
1767      return user != null ? (Guid?)user.ProviderUserKey ?? Guid.Empty : Guid.Empty;
1768    }
1769   
1770    public Dictionary<Guid, HashSet<Guid>> GetUserGroupTree() {
1771      var userGroupTree = new Dictionary<Guid, HashSet<Guid>>();
1772      var userGroupMapping = UserManager.GetUserGroupMapping();
1773
1774      foreach(var ugm in userGroupMapping) {
1775        if (ugm.Parent == null || ugm.Child == null) continue;
1776
1777        if (!userGroupTree.ContainsKey(ugm.Parent)) {
1778          userGroupTree.Add(ugm.Parent, new HashSet<Guid>());
1779        }
1780        userGroupTree[ugm.Parent].Add(ugm.Child);
1781      }
1782
1783      return userGroupTree;
1784    }
1785
1786    public bool CheckAccessToAdminAreaGranted() {
1787      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1788      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
1789      var pm = PersistenceManager;
1790      using(new PerformanceLogger("CheckAccessToAdminAreaGranted")) {
1791        if (isAdministrator) {
1792          return true;
1793        } else {
1794          var projectDao = pm.ProjectDao;
1795          var currentUserId = UserManager.CurrentUserId;
1796          return projectDao.GetAdministrationGrantedProjectsForUser(currentUserId).Any();
1797        }
1798      }
1799    }
1800    #endregion
1801
1802    #region UserPriorities Methods
1803    public IEnumerable<DT.UserPriority> GetUserPriorities() {
1804      var pm = PersistenceManager;
1805      using (new PerformanceLogger("GetUserPriorities")) {
1806        var userPriorityDao = pm.UserPriorityDao;
1807        return pm.UseTransaction(() => userPriorityDao.GetAll()
1808          .Select(x => x.ToDto())
1809          .ToList()
1810        );
1811      }
1812    }
1813    #endregion
1814
1815    #region Private Helper Methods
1816    private void UpdateTaskState(IPersistenceManager pm, DA.Task task, DT.TaskState taskState, Guid? slaveId, Guid? userId, string exception) {
1817      var stateLogDao = pm.StateLogDao;
1818      var taskStateEntity = taskState.ToEntity();
1819
1820      if (task.State == DA.TaskState.Transferring && taskStateEntity == DA.TaskState.Paused && task.Command == null) {
1821        // slave paused and uploaded the task (no user-command) -> set waiting.
1822        taskStateEntity = DA.TaskState.Waiting;
1823      }
1824
1825      stateLogDao.Save(new DA.StateLog {
1826        State = taskStateEntity,
1827        DateTime = DateTime.Now,
1828        TaskId = task.TaskId,
1829        UserId = userId,
1830        SlaveId = slaveId,
1831        Exception = exception
1832      });
1833
1834      task.State = taskStateEntity;
1835
1836      if (task.Command == DA.Command.Pause && task.State == DA.TaskState.Paused
1837          || task.Command == DA.Command.Abort && task.State == DA.TaskState.Aborted
1838          || task.Command == DA.Command.Stop && task.State == DA.TaskState.Aborted) {
1839        task.Command = null;
1840      }
1841    }
1842
1843    private void CheckProjectAvailability(IPersistenceManager pm, Guid projectId, DateTime date) {
1844      var projectDao = pm.ProjectDao;
1845      using (new PerformanceLogger("UpdateJob")) {
1846        var project = pm.UseTransaction(() => {
1847          return projectDao.GetById(projectId);
1848        });
1849        if (project != null) {
1850          if (project.StartDate > date) throw new ArgumentException("Cannot add job to specified project. The start date of the project is still in the future.");
1851          else if (project.EndDate != null && project.EndDate < date) throw new ArgumentException("Cannot add job to specified project. The end date of the project is already reached.");
1852        } else {
1853          throw new ArgumentException("Cannot add job to specified project. The project seems not to be available anymore.");
1854        }
1855      }
1856    }
1857
1858    private void EvaluateJobs(IPersistenceManager pm, IEnumerable<DT.Job> jobs) {
1859      if (jobs == null || !jobs.Any()) return;
1860
1861      var currentUserId = UserManager.CurrentUserId;     
1862      var taskDao = pm.TaskDao;
1863      var jobPermissionDao = pm.JobPermissionDao;
1864
1865      var statistics = taskDao.GetAll()
1866        .Where(x => jobs.Select(y => y.Id).Contains(x.JobId))
1867        .GroupBy(x => x.JobId)
1868        .Select(x => new {
1869          x.Key,
1870          TotalCount = x.Count(),
1871          CalculatingCount = x.Count(y => y.State == DA.TaskState.Calculating),
1872          FinishedCount = x.Count(y => CompletedStates.Contains(y.State))
1873        })
1874        .ToList();
1875
1876      foreach (var job in jobs) {
1877        var statistic = statistics.FirstOrDefault(x => x.Key == job.Id);
1878        if (statistic != null) {
1879          job.JobCount = statistic.TotalCount;
1880          job.CalculatingCount = statistic.CalculatingCount;
1881          job.FinishedCount = statistic.FinishedCount;
1882        }
1883
1884        job.OwnerUsername = UserManager.GetUserNameById(job.OwnerUserId);
1885
1886        if (currentUserId == job.OwnerUserId) {
1887          job.Permission = Permission.Full;
1888        } else {
1889          var jobPermission = jobPermissionDao.GetByJobAndUserId(job.Id, currentUserId);
1890          job.Permission = jobPermission == null ? Permission.NotAllowed : jobPermission.Permission.ToDto();
1891        }
1892      }
1893    }
1894    #endregion
1895  }
1896}
Note: See TracBrowser for help on using the repository browser.