Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.Services.Hive/3.3/HiveService.cs @ 17472

Last change on this file since 17472 was 17376, checked in by jkarder, 5 years ago

#3041: fixed overwriting of IsDisposable for known slaves

File size: 81.7 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 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          bool isAdmin = RoleVerifier.IsInRole(HiveRoles.Administrator);
358          List<DA.Project> administrationGrantedProjects;
359          if (isAdmin) {
360            administrationGrantedProjects = projectDao.GetAll().ToList();
361          } else {
362            administrationGrantedProjects = projectDao
363              .GetAdministrationGrantedProjectsForUser(currentUserId)             
364              .ToList();
365          }
366
367          if (administrationGrantedProjects.Select(x => x.ProjectId).Contains(projectId)) {
368            var jobs = jobDao.GetByProjectId(projectId)
369            .Select(x => x.ToDto())
370            .ToList();
371
372            EvaluateJobs(pm, jobs);
373            return jobs;
374          } else {
375            return Enumerable.Empty<DT.Job>();
376          }
377        });
378      }
379    }
380
381    public IEnumerable<DT.Job> GetJobsByProjectIds(IEnumerable<Guid> projectIds) {
382      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
383      var pm = PersistenceManager;
384      using (new PerformanceLogger("GetJobsByProjectIds")) {
385        var currentUserId = UserManager.CurrentUserId;
386        var projectDao = pm.ProjectDao;
387        var jobDao = pm.JobDao;
388        return pm.UseTransaction(() => {
389          // check for which of requested projectIds the user is granted to administer
390          bool isAdmin = RoleVerifier.IsInRole(HiveRoles.Administrator);
391          List<Guid> administrationGrantedProjectIds;
392          if (isAdmin) {
393            administrationGrantedProjectIds = projectDao.GetAll().Select(x => x.ProjectId).ToList();
394          } else {
395            administrationGrantedProjectIds = projectDao
396              .GetAdministrationGrantedProjectsForUser(currentUserId)
397              .Select(x => x.ProjectId)
398              .ToList();
399          }
400          var requestedAndGrantedProjectIds = projectIds.Intersect(administrationGrantedProjectIds);
401
402          if (requestedAndGrantedProjectIds.Any()) {
403            var jobs = jobDao.GetByProjectIds(requestedAndGrantedProjectIds)
404              .Select(x => x.ToDto())
405              .ToList();
406
407            EvaluateJobs(pm, jobs);
408            return jobs;
409          } else {
410            return Enumerable.Empty<DT.Job>();
411          }
412        });
413      }
414    }
415
416    public Guid AddJob(DT.Job jobDto, IEnumerable<Guid> resourceIds) {
417      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
418      var dateCreated = DateTime.Now;
419      var pm = PersistenceManager;
420
421      // check project availability (cf. duration)
422      CheckProjectAvailability(pm, jobDto.ProjectId, dateCreated);
423
424      // check user - project
425      AuthorizationManager.AuthorizeUserForProjectUse(UserManager.CurrentUserId, jobDto.ProjectId);
426
427      // check project - resources
428      AuthorizationManager.AuthorizeProjectForResourcesUse(jobDto.ProjectId, resourceIds);
429
430      using (new PerformanceLogger("AddJob")) {
431        var jobDao = pm.JobDao;
432        var userPriorityDao = pm.UserPriorityDao;
433
434        return pm.UseTransaction(() => {
435          var newJob = jobDto.ToEntity();
436          newJob.OwnerUserId = UserManager.CurrentUserId;
437          newJob.DateCreated = dateCreated;
438
439          // add resource assignments
440          if (resourceIds != null && resourceIds.Any()) {
441            newJob.AssignedJobResources.AddRange(resourceIds.Select(
442              x => new DA.AssignedJobResource {
443                ResourceId = x
444              }));
445          }
446
447          var job = jobDao.Save(newJob);
448          if (userPriorityDao.GetById(newJob.OwnerUserId) == null) {
449            userPriorityDao.Save(new DA.UserPriority {
450              UserId = newJob.OwnerUserId,
451              DateEnqueued = newJob.DateCreated
452            });
453          }
454          pm.SubmitChanges();
455          return job.JobId;
456        });
457      }
458    }
459
460    public void UpdateJob(DT.Job jobDto, IEnumerable<Guid> resourceIds) {
461      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
462      AuthorizationManager.AuthorizeForJob(jobDto.Id, DT.Permission.Full);
463      var pm = PersistenceManager;
464      var dateUpdated = DateTime.Now;
465
466      // check project availability
467      CheckProjectAvailability(pm, jobDto.ProjectId, dateUpdated);
468      // check user - project permission
469      AuthorizationManager.AuthorizeUserForProjectUse(UserManager.CurrentUserId, jobDto.ProjectId);
470      // check project - resources permission
471      AuthorizationManager.AuthorizeProjectForResourcesUse(jobDto.ProjectId, resourceIds);
472
473      using (new PerformanceLogger("UpdateJob")) {
474        bool exists = true;
475        var jobDao = pm.JobDao;
476        pm.UseTransaction(() => {
477          var job = jobDao.GetById(jobDto.Id);
478          if (job == null) {
479            exists = false;
480            job = new DA.Job();
481          } else if (job.State != DA.JobState.Online) {
482            throw new InvalidOperationException(NO_JOB_UPDATE_POSSIBLE);
483          }
484
485          jobDto.CopyToEntity(job);
486
487          if (!exists) {
488            // add resource assignments
489            if (resourceIds != null && resourceIds.Any()) {
490              job.AssignedJobResources.AddRange(resourceIds.Select(
491                x => new DA.AssignedJobResource {
492                  ResourceId = x
493                }));
494            }
495            jobDao.Save(job);
496          } else if (resourceIds != null) {
497            var addedJobResourceIds = resourceIds.Except(job.AssignedJobResources.Select(x => x.ResourceId));
498            var removedJobResourceIds = job.AssignedJobResources
499              .Select(x => x.ResourceId)
500              .Except(resourceIds)
501              .ToArray();
502
503            // remove resource assignments
504            foreach (var rid in removedJobResourceIds) {
505              var ajr = job.AssignedJobResources.Where(x => x.ResourceId == rid).SingleOrDefault();
506              if (ajr != null) job.AssignedJobResources.Remove(ajr);
507            }
508
509            // add resource assignments
510            job.AssignedJobResources.AddRange(addedJobResourceIds.Select(
511              x => new DA.AssignedJobResource {
512                ResourceId = x
513              }));
514          }
515          pm.SubmitChanges();
516        });
517      }
518    }
519
520    public void UpdateJobState(Guid jobId, DT.JobState jobState) {
521      if (jobState != JobState.StatisticsPending) return; // only process requests for "StatisticsPending"
522
523      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
524      // check if user is an admin, or granted to administer a job-parenting project, or job owner
525      AuthorizationManager.AuthorizeForJob(jobId, DT.Permission.Full);
526
527      var pm = PersistenceManager;
528      using (new PerformanceLogger("UpdateJobState")) {
529        var jobDao = pm.JobDao;       
530        pm.UseTransaction(() => {
531          var job = jobDao.GetById(jobId);
532          if (job != null) {           
533
534            // note: allow solely state changes from "Online" to "StatisticsPending" = deletion request by user for HiveStatisticGenerator           
535            var jobStateEntity = jobState.ToEntity();
536            if (job.State == DA.JobState.Online && jobStateEntity == DA.JobState.StatisticsPending) {
537              job.State = jobStateEntity;
538              foreach (var task in job.Tasks
539              .Where(x => x.State == DA.TaskState.Waiting
540                || x.State == DA.TaskState.Paused
541                || x.State == DA.TaskState.Offline)) {
542                task.State = DA.TaskState.Aborted;
543              }
544              pm.SubmitChanges();
545            }
546          }
547        });
548      }
549    }
550
551    public void UpdateJobStates(IEnumerable<Guid> jobIds, DT.JobState jobState) {
552      if (jobState != JobState.StatisticsPending) return; // only process requests for "StatisticsPending"
553
554      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
555      // check if user is an admin, or granted to administer a job-parenting project, or job owner
556      foreach (var jobId in jobIds)
557          AuthorizationManager.AuthorizeForJob(jobId, DT.Permission.Full);
558
559      var pm = PersistenceManager;
560      using (new PerformanceLogger("UpdateJobStates")) {
561        var jobDao = pm.JobDao;
562        var projectDao = pm.ProjectDao;
563        pm.UseTransaction(() => {
564          foreach (var jobId in jobIds) {
565            var job = jobDao.GetById(jobId);
566            if (job != null) {
567
568              // note: allow solely state changes from "Online" to "StatisticsPending" = deletion request by user for HiveStatisticGenerator
569              var jobStateEntity = jobState.ToEntity();
570              if (job.State == DA.JobState.Online && jobStateEntity == DA.JobState.StatisticsPending) {
571                job.State = jobStateEntity;
572                foreach (var task in job.Tasks
573                .Where(x => x.State == DA.TaskState.Waiting
574                  || x.State == DA.TaskState.Paused
575                  || x.State == DA.TaskState.Offline)) {
576                  task.State = DA.TaskState.Aborted;
577                }
578                pm.SubmitChanges();
579              }             
580            }
581          }
582        });
583      }
584    }
585
586    public IEnumerable<DT.AssignedJobResource> GetAssignedResourcesForJob(Guid jobId) {
587      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
588      AuthorizationManager.AuthorizeForJob(jobId, DT.Permission.Full);
589      var pm = PersistenceManager;
590      var assignedJobResourceDao = pm.AssignedJobResourceDao;
591      using (new PerformanceLogger("GetAssignedResourcesForProject")) {
592        return pm.UseTransaction(() =>
593          assignedJobResourceDao.GetByJobId(jobId)
594          .Select(x => x.ToDto())
595          .ToList()
596        );
597      }
598    }
599    #endregion
600
601    #region JobPermission Methods
602    public void GrantPermission(Guid jobId, Guid grantedUserId, DT.Permission permission) {
603      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
604      AuthorizationManager.AuthorizeForJob(jobId, Permission.Full);
605      var pm = PersistenceManager;
606      using (new PerformanceLogger("GrantPermission")) {
607        var jobPermissionDao = pm.JobPermissionDao;
608        var currentUserId = UserManager.CurrentUserId;
609        pm.UseTransaction(() => {
610          jobPermissionDao.SetJobPermission(jobId, currentUserId, grantedUserId, permission.ToEntity());
611          pm.SubmitChanges();
612        });
613      }
614    }
615
616    public void RevokePermission(Guid jobId, Guid grantedUserId) {
617      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
618      AuthorizationManager.AuthorizeForJob(jobId, Permission.Full);
619      var pm = PersistenceManager;
620      using (new PerformanceLogger("RevokePermission")) {
621        var jobPermissionDao = pm.JobPermissionDao;
622        var currentUserId = UserManager.CurrentUserId;
623        pm.UseTransaction(() => {
624          jobPermissionDao.SetJobPermission(jobId, currentUserId, grantedUserId, DA.Permission.NotAllowed);
625          pm.SubmitChanges();
626        });
627      }
628    }
629
630    public IEnumerable<JobPermission> GetJobPermissions(Guid jobId) {
631      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
632      AuthorizationManager.AuthorizeForJob(jobId, Permission.Full);
633      var pm = PersistenceManager;
634      using (new PerformanceLogger("GetJobPermissions")) {
635        var jobPermissionDao = pm.JobPermissionDao;
636        return pm.UseTransaction(() => jobPermissionDao.GetByJobId(jobId)
637          .Select(x => x.ToDto())
638          .ToList()
639        );
640      }
641    }
642
643    // BackwardsCompatibility3.3
644    #region Backwards compatible code, remove with 3.4
645    public bool IsAllowedPrivileged() {
646      return true;
647    }
648    #endregion
649    #endregion
650
651    #region Login Methods
652    public void Hello(DT.Slave slaveInfo) {
653      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
654      if (UserManager.CurrentUser.UserName != "hiveslave") {
655        slaveInfo.OwnerUserId = UserManager.CurrentUserId;
656      }
657      var pm = PersistenceManager;
658      using (new PerformanceLogger("Hello")) {
659        var slaveDao = pm.SlaveDao;
660        pm.UseTransaction(() => {
661          var slave = slaveDao.GetById(slaveInfo.Id);
662          if (slave == null) {
663            slaveDao.Save(slaveInfo.ToEntity());
664          } else {
665            bool oldIsAllowedToCalculate = slave.IsAllowedToCalculate;
666            Guid? oldParentResourceId = slave.ParentResourceId;
667            bool? oldIsDisposable = slave.IsDisposable;
668            slaveInfo.CopyToEntity(slave);
669            slave.IsAllowedToCalculate = oldIsAllowedToCalculate;
670            slave.ParentResourceId = oldParentResourceId;
671            slave.IsDisposable = oldIsDisposable;
672            slave.LastHeartbeat = DateTime.Now;
673            slave.SlaveState = DA.SlaveState.Idle;
674          }
675          pm.SubmitChanges();
676        });
677      }
678    }
679
680    public void GoodBye(Guid slaveId) {
681      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
682      var pm = PersistenceManager;
683      using (new PerformanceLogger("GoodBye")) {
684        var slaveDao = pm.SlaveDao;
685        pm.UseTransaction(() => {
686          var slave = slaveDao.GetById(slaveId);
687          if (slave != null) {
688            slave.SlaveState = DA.SlaveState.Offline;
689            pm.SubmitChanges();
690          }
691        });
692      }
693    }
694    #endregion
695
696    #region Heartbeat Methods
697    public List<MessageContainer> Heartbeat(DT.Heartbeat heartbeat) {
698      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
699      List<MessageContainer> result = new List<MessageContainer>();
700      try {
701        using (new PerformanceLogger("ProcessHeartbeat")) {
702          result = HeartbeatManager.ProcessHeartbeat(heartbeat);
703        }
704      } catch (Exception ex) {
705        DA.LogFactory.GetLogger(this.GetType().Namespace).Log(string.Format("Exception processing Heartbeat: {0}", ex));
706      }
707      if (HeuristicLab.Services.Hive.Properties.Settings.Default.TriggerEventManagerInHeartbeat) {
708        TriggerEventManager(false);
709      }
710      return result;
711    }
712    #endregion
713
714    #region Plugin Methods
715    public DT.Plugin GetPlugin(Guid pluginId) {
716      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
717      var pm = PersistenceManager;
718      using (new PerformanceLogger("GetPlugin")) {
719        var pluginDao = pm.PluginDao;
720        return pm.UseTransaction(() => pluginDao.GetById(pluginId).ToDto());
721      }
722    }
723
724    public Guid AddPlugin(DT.Plugin plugin, List<DT.PluginData> pluginData) {
725      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
726      var pm = PersistenceManager;
727      using (new PerformanceLogger("AddPlugin")) {
728        var pluginDao = pm.PluginDao;
729        plugin.UserId = UserManager.CurrentUserId;
730        plugin.DateCreated = DateTime.Now;
731        return pm.UseTransaction(() => {
732          var pluginEntity = pluginDao.GetByHash(plugin.Hash).SingleOrDefault();
733          if (pluginEntity != null) {
734            throw new FaultException<PluginAlreadyExistsFault>(new PluginAlreadyExistsFault(pluginEntity.PluginId));
735          }
736          pluginEntity = plugin.ToEntity();
737          foreach (var data in pluginData) {
738            data.PluginId = default(Guid); // real id will be assigned from linq2sql
739            pluginEntity.PluginData.Add(data.ToEntity());
740          }
741          pluginDao.Save(pluginEntity);
742          pm.SubmitChanges();
743          return pluginEntity.PluginId;
744        });
745      }
746    }
747
748    public IEnumerable<DT.Plugin> GetPlugins() {
749      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
750      var pm = PersistenceManager;
751      using (new PerformanceLogger("GetPlugins")) {
752        var pluginDao = pm.PluginDao;
753        return pm.UseTransaction(() => pluginDao.GetAll()
754          .Where(x => x.Hash != null)
755          .Select(x => x.ToDto())
756          .ToList()
757        );
758      }
759    }
760
761    public IEnumerable<DT.PluginData> GetPluginDatas(List<Guid> pluginIds) {
762      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
763      var pm = PersistenceManager;
764      using (new PerformanceLogger("GetPluginDatas")) {
765        var pluginDataDao = pm.PluginDataDao;
766        return pm.UseTransaction(() => pluginDataDao.GetAll()
767            .Where(x => pluginIds.Contains(x.PluginId))
768            .Select(x => x.ToDto())
769            .ToList()
770        );
771      }
772    }
773    #endregion
774
775    #region Project Methods
776    public Guid AddProject(DT.Project projectDto) {
777      if (projectDto == null || projectDto.Id != Guid.Empty) return Guid.Empty;
778      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
779      // check if current (non-admin) user is owner of one of projectDto's-parents
780      // note: non-admin users are not allowed to administer root projects (i.e. projects without parental entry)
781      bool isAdmin = RoleVerifier.IsInRole(HiveRoles.Administrator);
782      if (!isAdmin) {
783        if (projectDto != null && projectDto.ParentProjectId.HasValue) {
784          AuthorizationManager.AuthorizeForProjectAdministration(projectDto.ParentProjectId.Value, false);
785        } else {
786          throw new SecurityException(NOT_AUTHORIZED_USERPROJECT);
787        }
788      }
789
790      // check that non-admins can not be set as owner of root projects
791      if (projectDto != null && !projectDto.ParentProjectId.HasValue) {
792        var owner = UserManager.GetUserById(projectDto.OwnerUserId);
793        if (owner == null || !RoleVerifier.IsUserInRole(owner.UserName, HiveRoles.Administrator)) {
794          throw new SecurityException(NOT_AUTHORIZED_PROJECTOWNER);
795        }
796      }
797
798      var pm = PersistenceManager;
799      using (new PerformanceLogger("AddProject")) {
800        var projectDao = pm.ProjectDao;
801
802        return pm.UseTransaction(() => {
803          var project = projectDao.Save(projectDto.ToEntity());
804
805          var parentProjects = projectDao.GetParentProjectsById(project.ProjectId).ToList();
806          bool isParent = parentProjects.Select(x => x.OwnerUserId == UserManager.CurrentUserId).Any();
807
808          // if user is no admin, but owner of a parent project
809          // check start/end date time boundaries of parent projects before updating child project
810          if (!isAdmin) {
811            var parentProject = parentProjects.Where(x => x.ProjectId == project.ParentProjectId).FirstOrDefault();
812            if (parentProject != null) {
813              if (project.StartDate < parentProject.StartDate) project.StartDate = parentProject.StartDate;
814              if ((parentProject.EndDate.HasValue && project.EndDate.HasValue && project.EndDate > parentProject.EndDate)
815              || (parentProject.EndDate.HasValue && !project.EndDate.HasValue))
816                project.EndDate = parentProject.EndDate;
817            }
818          }
819
820
821          project.ProjectPermissions.Clear();
822          project.ProjectPermissions.Add(new DA.ProjectPermission {
823            GrantedUserId = project.OwnerUserId,
824            GrantedByUserId = UserManager.CurrentUserId
825          });
826
827          pm.SubmitChanges();
828          return project.ProjectId;
829        });
830      }
831    }
832
833    public void UpdateProject(DT.Project projectDto) {
834      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
835      // check if current (non-admin) user is owner of the project or the projectDto's-parents
836      // note: non-admin users are not allowed to administer root projects (i.e. projects without parental entry)
837      bool isAdmin = RoleVerifier.IsInRole(HiveRoles.Administrator);
838      if (!isAdmin) {
839        if (projectDto != null && projectDto.ParentProjectId.HasValue) {
840          AuthorizationManager.AuthorizeForProjectAdministration(projectDto.Id, false);
841        } else {
842          throw new SecurityException(NOT_AUTHORIZED_USERPROJECT);
843        }
844      }
845
846      // check that non-admins can not be set as owner of root projects
847      if (projectDto != null && !projectDto.ParentProjectId.HasValue) {
848        var owner = UserManager.GetUserById(projectDto.OwnerUserId);
849        if (owner == null || !RoleVerifier.IsUserInRole(owner.UserName, HiveRoles.Administrator)) {
850          throw new SecurityException(NOT_AUTHORIZED_PROJECTOWNER);
851        }
852      }
853
854      var pm = PersistenceManager;
855      using (new PerformanceLogger("UpdateProject")) {
856        var projectDao = pm.ProjectDao;
857        var assignedJobResourceDao = pm.AssignedJobResourceDao;
858        pm.UseTransaction(() => {
859          var project = projectDao.GetById(projectDto.Id);
860          if (project != null) { // (1) update existent project
861            var parentProjects = projectDao.GetParentProjectsById(project.ProjectId).ToList();
862            bool isParent = parentProjects.Select(x => x.OwnerUserId == UserManager.CurrentUserId).Any();
863
864            var formerOwnerId = project.OwnerUserId;
865            var formerStartDate = project.StartDate;
866            var formerEndDate = project.EndDate;
867            projectDto.CopyToEntity(project);
868
869            // if user is no admin, but owner of parent project(s)
870            // check start/end date time boundaries of parent projects before updating child project
871            if (!isAdmin && isParent) {
872              var parentProject = parentProjects.Where(x => x.ProjectId == project.ParentProjectId).FirstOrDefault();
873              if (parentProject != null) {
874                if (project.StartDate < parentProject.StartDate) project.StartDate = formerStartDate;
875                if ((parentProject.EndDate.HasValue && project.EndDate.HasValue && project.EndDate > parentProject.EndDate)
876                || (parentProject.EndDate.HasValue && !project.EndDate.HasValue))
877                  project.EndDate = formerEndDate;
878              }
879            }
880
881            // if user is admin or owner of parent project(s)
882            if (isAdmin || isParent) {
883              // if owner has changed...
884              if (formerOwnerId != projectDto.OwnerUserId) {
885                // Add permission for new owner if not already done
886                if (!project.ProjectPermissions
887                  .Select(pp => pp.GrantedUserId)
888                  .Contains(projectDto.OwnerUserId)) {
889                  project.ProjectPermissions.Add(new DA.ProjectPermission {
890                    GrantedUserId = projectDto.OwnerUserId,
891                    GrantedByUserId = UserManager.CurrentUserId
892                  });
893                }
894              }
895            } else { // if user is only owner of current project, but no admin and no owner of parent project(s)
896              project.OwnerUserId = formerOwnerId;
897              project.StartDate = formerStartDate;
898              project.EndDate = formerEndDate;
899            }
900
901          } else { // (2) save new project
902            var newProject = projectDao.Save(projectDto.ToEntity());
903
904            var parentProjects = projectDao.GetParentProjectsById(project.ProjectId).ToList();
905            bool isParent = parentProjects.Select(x => x.OwnerUserId == UserManager.CurrentUserId).Any();
906
907            // if user is no admin, but owner of a parent project
908            // check start/end date time boundaries of parent projects before updating child project
909            if (!isAdmin) {
910              var parentProject = parentProjects.Where(x => x.ProjectId == project.ParentProjectId).FirstOrDefault();
911              if (parentProject != null) {
912                if (project.StartDate < parentProject.StartDate) project.StartDate = parentProject.StartDate;
913                if ((parentProject.EndDate.HasValue && project.EndDate.HasValue && project.EndDate > parentProject.EndDate)
914                || (parentProject.EndDate.HasValue && !project.EndDate.HasValue))
915                  project.EndDate = parentProject.EndDate;
916              }
917            }
918
919            newProject.ProjectPermissions.Clear();
920            newProject.ProjectPermissions.Add(new DA.ProjectPermission {
921              GrantedUserId = projectDto.OwnerUserId,
922              GrantedByUserId = UserManager.CurrentUserId
923            });
924          }
925
926          pm.SubmitChanges();
927        });
928      }
929    }
930
931    public void DeleteProject(Guid projectId) {
932      if (projectId == Guid.Empty) return;
933      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
934      // check if current (non-admin) user is owner of one of the projectDto's-parents
935      // note: non-admin users are not allowed to administer root projects (i.e. projects without parental entry)
936      if (!RoleVerifier.IsInRole(HiveRoles.Administrator)) {
937        AuthorizationManager.AuthorizeForProjectAdministration(projectId, true);
938      }
939
940      var pm = PersistenceManager;
941      using (new PerformanceLogger("DeleteProject")) {
942        var projectDao = pm.ProjectDao;
943        var jobDao = pm.JobDao;
944        var assignedJobResourceDao = pm.AssignedJobResourceDao;
945        pm.UseTransaction(() => {
946          var projectIds = new HashSet<Guid> { projectId };
947          projectIds.Union(projectDao.GetChildProjectIdsById(projectId));
948
949          var jobs = jobDao.GetByProjectIds(projectIds)
950            .Select(x => x.ToDto())
951            .ToList();
952
953          if (jobs.Count > 0) {
954            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.");
955          } else {
956            assignedJobResourceDao.DeleteByProjectIds(projectIds);
957            projectDao.DeleteByIds(projectIds);
958            pm.SubmitChanges();
959          }
960        });
961      }
962    }
963
964    // query granted project for use (i.e. to calculate on)
965    public DT.Project GetProject(Guid projectId) {
966      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
967      var pm = PersistenceManager;
968      using (new PerformanceLogger("GetProject")) {
969        var projectDao = pm.ProjectDao;
970        var currentUserId = UserManager.CurrentUserId;
971        var userAndGroupIds = new List<Guid> { currentUserId };
972        userAndGroupIds.AddRange(UserManager.GetUserGroupIdsOfUser(currentUserId));
973        return pm.UseTransaction(() => {
974          return projectDao.GetUsageGrantedProjectsForUser(userAndGroupIds)
975          .Where(x => x.ProjectId == projectId)
976          .Select(x => x.ToDto())
977          .SingleOrDefault();
978        });
979      }
980    }
981
982    // query granted projects for use (i.e. to calculate on)
983    public IEnumerable<DT.Project> GetProjects() {
984      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
985      var pm = PersistenceManager;
986      using (new PerformanceLogger("GetProjects")) {
987        var projectDao = pm.ProjectDao;
988        var currentUserId = UserManager.CurrentUserId;
989        var userAndGroupIds = new List<Guid> { currentUserId };
990        userAndGroupIds.AddRange(UserManager.GetUserGroupIdsOfUser(currentUserId));
991        return pm.UseTransaction(() => {
992          var projects = projectDao.GetUsageGrantedProjectsForUser(userAndGroupIds)
993            .Select(x => x.ToDto()).ToList();
994          var now = DateTime.Now;
995          return projects.Where(x => x.StartDate <= now && (x.EndDate == null || x.EndDate >= now)).ToList();
996        });
997      }
998    }
999
1000    public IEnumerable<DT.Project> GetProjectsForAdministration() {
1001      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1002      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
1003      var pm = PersistenceManager;
1004      using (new PerformanceLogger("GetProjectsForAdministration")) {
1005        var projectDao = pm.ProjectDao;
1006
1007        return pm.UseTransaction(() => {
1008          if (isAdministrator) {
1009            return projectDao.GetAll().Select(x => x.ToDto()).ToList();
1010          } else {
1011            var currentUserId = UserManager.CurrentUserId;
1012            return projectDao.GetAdministrationGrantedProjectsForUser(currentUserId)
1013              .Select(x => x.ToDto()).ToList();
1014
1015          }
1016        });
1017      }
1018    }
1019
1020    public IDictionary<Guid, HashSet<Guid>> GetProjectGenealogy() {
1021      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1022      var pm = PersistenceManager;
1023      using (new PerformanceLogger("GetProjectGenealogy")) {
1024        var projectDao = pm.ProjectDao;
1025        var projectAncestors = new Dictionary<Guid, HashSet<Guid>>();
1026        return pm.UseTransaction(() => {
1027          var projects = projectDao.GetAll().ToList();
1028          projects.ForEach(p => projectAncestors.Add(p.ProjectId, new HashSet<Guid>()));
1029          foreach (var p in projects) {
1030            var parentProject = p.ParentProject;
1031            while (parentProject != null) {
1032              projectAncestors[p.ProjectId].Add(parentProject.ProjectId);
1033              parentProject = parentProject.ParentProject;
1034            }
1035          }
1036          return projectAncestors;
1037        });
1038      }
1039    }
1040
1041    public IDictionary<Guid, string> GetProjectNames() {
1042      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1043      var pm = PersistenceManager;
1044      using (new PerformanceLogger("GetProjectNames")) {
1045        var projectDao = pm.ProjectDao;
1046        var projectNames = new Dictionary<Guid, string>();
1047        return pm.UseTransaction(() => {
1048          projectDao
1049            .GetAll().ToList()
1050            .ForEach(p => projectNames.Add(p.ProjectId, p.Name));
1051          return projectNames;
1052        });
1053      }
1054    }
1055    #endregion
1056
1057    #region ProjectPermission Methods
1058    public void SaveProjectPermissions(Guid projectId, List<Guid> grantedUserIds, bool reassign, bool cascading, bool reassignCascading) {
1059      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1060      if (projectId == null || grantedUserIds == null) return;
1061      AuthorizationManager.AuthorizeForProjectAdministration(projectId, false);
1062      var pm = PersistenceManager;
1063      using (new PerformanceLogger("SaveProjectPermissions")) {
1064        var projectDao = pm.ProjectDao;
1065        var projectPermissionDao = pm.ProjectPermissionDao;
1066        var assignedJobResourceDao = pm.AssignedJobResourceDao;
1067
1068        pm.UseTransaction(() => {
1069          var project = projectDao.GetById(projectId);
1070          if (project == null) return;
1071          var projectPermissions = project.ProjectPermissions.Select(x => x.GrantedUserId).ToArray();
1072
1073          // guarantee that project owner is always permitted
1074          if (!grantedUserIds.Contains(project.OwnerUserId)) {
1075            grantedUserIds.Add(project.OwnerUserId);
1076          }
1077
1078          //var addedPermissions = grantedUserIds.Except(projectPermissions);
1079          var removedPermissions = projectPermissions.Except(grantedUserIds);
1080
1081          // remove job assignments and project permissions
1082          if (reassign) {
1083            assignedJobResourceDao.DeleteByProjectId(project.ProjectId);
1084            project.ProjectPermissions.Clear();
1085          } else {
1086
1087            var ugt = GetUserGroupTree();
1088            var permittedGuids = new HashSet<Guid>(); // User- and Group-Guids
1089            var notpermittedGuids = new HashSet<Guid>();
1090
1091            // remove job assignments:
1092            // (1) get all member-Guids of all still or fresh permitted user/groups
1093            foreach (var item in grantedUserIds) {
1094              permittedGuids.Add(item);
1095              if (ugt.ContainsKey(item)) {
1096                ugt[item].ToList().ForEach(x => permittedGuids.Add(x));
1097              }
1098            }
1099
1100            // (2) get all member-Guids of users and groups in removedPermissions
1101            foreach (var item in removedPermissions) {
1102              notpermittedGuids.Add(item);
1103              if (ugt.ContainsKey(item)) {
1104                ugt[item].ToList().ForEach(x => notpermittedGuids.Add(x));
1105              }
1106            }
1107
1108            // (3) get all Guids which are in removedPermissions but not in grantedUserIds
1109            var definitelyNotPermittedGuids = notpermittedGuids.Except(permittedGuids);
1110
1111            // (4) delete jobs of those
1112            assignedJobResourceDao.DeleteByProjectIdAndUserIds(project.ProjectId, definitelyNotPermittedGuids);
1113
1114
1115            // remove project permissions
1116            foreach (var item in project.ProjectPermissions
1117              .Where(x => removedPermissions.Contains(x.GrantedUserId))
1118              .ToList()) {
1119              project.ProjectPermissions.Remove(item);
1120            }
1121          }
1122          pm.SubmitChanges();
1123
1124          // add project permissions
1125          foreach (var id in grantedUserIds) {
1126            if (project.ProjectPermissions.All(x => x.GrantedUserId != id)) {
1127              project.ProjectPermissions.Add(new DA.ProjectPermission {
1128                GrantedUserId = id,
1129                GrantedByUserId = UserManager.CurrentUserId
1130              });
1131            }
1132          }
1133          pm.SubmitChanges();
1134
1135          if (cascading) {
1136            var childProjects = projectDao.GetChildProjectsById(projectId).ToList();
1137            var childProjectIds = childProjects.Select(x => x.ProjectId).ToList();
1138
1139            // remove job assignments
1140            if (reassignCascading) {
1141              assignedJobResourceDao.DeleteByProjectIds(childProjectIds);
1142            } else {
1143              assignedJobResourceDao.DeleteByProjectIdsAndUserIds(childProjectIds, removedPermissions);
1144            }
1145
1146            foreach (var p in childProjects) {
1147              var cpAssignedPermissions = p.ProjectPermissions.Select(x => x.GrantedUserId).ToList();
1148              // guarantee that project owner is always permitted
1149              if (!cpAssignedPermissions.Contains(p.OwnerUserId)) {
1150                cpAssignedPermissions.Add(p.OwnerUserId);
1151              }
1152              var cpRemovedPermissions = cpAssignedPermissions.Where(x => x != p.OwnerUserId).Except(grantedUserIds);
1153
1154              // remove left-over job assignments (for non-reassignments)
1155              if (!reassignCascading) {
1156                assignedJobResourceDao.DeleteByProjectIdAndUserIds(p.ProjectId, cpRemovedPermissions);
1157              }
1158
1159              // remove project permissions
1160              if (reassignCascading) {
1161                p.ProjectPermissions.Clear();
1162              } else {
1163                foreach (var item in p.ProjectPermissions
1164                  .Where(x => x.GrantedUserId != p.OwnerUserId
1165                    && (removedPermissions.Contains(x.GrantedUserId) || cpRemovedPermissions.Contains(x.GrantedUserId)))
1166                  .ToList()) {
1167                  p.ProjectPermissions.Remove(item);
1168                }
1169              }
1170              pm.SubmitChanges();
1171
1172              // add project permissions
1173              var cpGrantedUserIds = new HashSet<Guid>(grantedUserIds);
1174              cpGrantedUserIds.Add(p.OwnerUserId);
1175
1176              foreach (var id in cpGrantedUserIds) {
1177                if (p.ProjectPermissions.All(x => x.GrantedUserId != id)) {
1178                  p.ProjectPermissions.Add(new DA.ProjectPermission {
1179                    GrantedUserId = id,
1180                    GrantedByUserId = UserManager.CurrentUserId
1181                  });
1182                }
1183              }
1184            }
1185          }
1186          pm.SubmitChanges();
1187        });
1188      }
1189    }
1190
1191    //private void GrantProjectPermissions(Guid projectId, List<Guid> grantedUserIds, bool cascading) {
1192    //  throw new NotImplementedException();
1193    //}
1194
1195    //private void RevokeProjectPermissions(Guid projectId, List<Guid> grantedUserIds, bool cascading) {
1196    //  RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1197    //  if (projectId == null || grantedUserIds == null || !grantedUserIds.Any()) return;
1198    //  AuthorizationManager.AuthorizeForProjectAdministration(projectId, false);
1199    //  var pm = PersistenceManager;
1200    //  using (new PerformanceLogger("RevokeProjectPermissions")) {
1201    //    var projectPermissionDao = pm.ProjectPermissionDao;
1202    //    var projectDao = pm.ProjectDao;
1203    //    var assignedJobResourceDao = pm.AssignedJobResourceDao;
1204    //    pm.UseTransaction(() => {
1205    //      if (cascading) {
1206    //        var childProjectIds = projectDao.GetChildProjectIdsById(projectId).ToList();
1207    //        projectPermissionDao.DeleteByProjectIdsAndGrantedUserIds(childProjectIds, grantedUserIds);
1208    //        assignedJobResourceDao.DeleteByProjectIdsAndUserIds(childProjectIds, grantedUserIds);
1209    //      }
1210    //      projectPermissionDao.DeleteByProjectIdAndGrantedUserIds(projectId, grantedUserIds);
1211    //      assignedJobResourceDao.DeleteByProjectIdAndUserIds(projectId, grantedUserIds);
1212    //      pm.SubmitChanges();
1213    //    });
1214    //  }
1215    //}
1216
1217    public IEnumerable<DT.ProjectPermission> GetProjectPermissions(Guid projectId) {
1218      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1219      AuthorizationManager.AuthorizeForProjectAdministration(projectId, false);
1220      var pm = PersistenceManager;
1221      using (new PerformanceLogger("GetProjectPermissions")) {
1222        var projectPermissionDao = pm.ProjectPermissionDao;
1223        return pm.UseTransaction(() => projectPermissionDao.GetByProjectId(projectId)
1224          .Select(x => x.ToDto())
1225          .ToList()
1226        );
1227      }
1228    }
1229    #endregion
1230
1231    #region AssignedProjectResource Methods
1232    // basic: remove and add assignments (resourceIds) to projectId and its depending jobs
1233    // reassign: clear all assignments from project and its depending jobs, before adding new ones (resourceIds)
1234    // cascading: "basic" mode for child-projects
1235    // reassignCascading: "reassign" mode for child-projects
1236    public void SaveProjectResourceAssignments(Guid projectId, List<Guid> resourceIds, bool reassign, bool cascading, bool reassignCascading) {
1237      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1238      if (projectId == null || resourceIds == null) return;
1239      AuthorizationManager.AuthorizeForProjectResourceAdministration(projectId, resourceIds);
1240      bool isAdmin = RoleVerifier.IsInRole(HiveRoles.Administrator);
1241      var pm = PersistenceManager;
1242      using (new PerformanceLogger("SaveProjectResourceAssignments")) {
1243        var projectDao = pm.ProjectDao;
1244        var assignedProjectResourceDao = pm.AssignedProjectResourceDao;
1245        var assignedJobResourceDao = pm.AssignedJobResourceDao;
1246        pm.UseTransaction(() => {
1247          var project = projectDao.GetById(projectId);
1248
1249          var parentProjects = projectDao.GetParentProjectsById(project.ProjectId).ToList();
1250          bool isParent = parentProjects.Select(x => x.OwnerUserId == UserManager.CurrentUserId).Any();
1251
1252          var assignedResources = project.AssignedProjectResources.Select(x => x.ResourceId).ToArray();
1253          if (!isParent && !isAdmin) resourceIds = assignedResources.ToList();
1254          var removedAssignments = assignedResources.Except(resourceIds);
1255
1256          // if user is admin or owner of parent project(s)
1257          if (isAdmin || isParent) {
1258            // remove job and project assignments
1259            if (reassign) {
1260              assignedJobResourceDao.DeleteByProjectId(project.ProjectId);
1261              project.AssignedProjectResources.Clear();
1262            } else {
1263              assignedJobResourceDao.DeleteByProjectIdAndResourceIds(projectId, removedAssignments);
1264              foreach (var item in project.AssignedProjectResources
1265                .Where(x => removedAssignments.Contains(x.ResourceId))
1266                .ToList()) {
1267                project.AssignedProjectResources.Remove(item);
1268              }
1269            }
1270            pm.SubmitChanges();
1271
1272            // add project assignments
1273            foreach (var id in resourceIds) {
1274              if (project.AssignedProjectResources.All(x => x.ResourceId != id)) {
1275                project.AssignedProjectResources.Add(new DA.AssignedProjectResource {
1276                  ResourceId = id
1277                });
1278              }
1279            }
1280            pm.SubmitChanges();
1281          }
1282
1283          // if user is admin, project owner or owner of parent projects
1284          if (cascading) {
1285            var childProjects = projectDao.GetChildProjectsById(projectId).ToList();
1286            var childProjectIds = childProjects.Select(x => x.ProjectId).ToList();
1287
1288            // remove job assignments
1289            if (reassignCascading) {
1290              assignedJobResourceDao.DeleteByProjectIds(childProjectIds);
1291            } else {
1292              assignedJobResourceDao.DeleteByProjectIdsAndResourceIds(childProjectIds, removedAssignments);
1293            }
1294            foreach (var p in childProjects) {
1295              var cpAssignedResources = p.AssignedProjectResources.Select(x => x.ResourceId).ToArray();
1296              var cpRemovedAssignments = cpAssignedResources.Except(resourceIds);
1297
1298              // remove left-over job assignments (for non-reassignments)
1299              if (!reassignCascading) {
1300                assignedJobResourceDao.DeleteByProjectIdAndResourceIds(p.ProjectId, cpRemovedAssignments);
1301              }
1302
1303              // remove project assignments
1304              if (reassignCascading) {
1305                p.AssignedProjectResources.Clear();
1306              } else {
1307                foreach (var item in p.AssignedProjectResources
1308                  .Where(x => removedAssignments.Contains(x.ResourceId) || cpRemovedAssignments.Contains(x.ResourceId))
1309                  .ToList()) {
1310                  p.AssignedProjectResources.Remove(item);
1311                }
1312              }
1313              pm.SubmitChanges();
1314
1315              // add project assignments
1316              foreach (var id in resourceIds) {
1317                if (p.AssignedProjectResources.All(x => x.ResourceId != id)) {
1318                  p.AssignedProjectResources.Add(new DA.AssignedProjectResource {
1319                    ResourceId = id
1320                  });
1321                }
1322              }
1323            }
1324          }
1325          pm.SubmitChanges();
1326        });
1327      }
1328    }
1329
1330    //private void AssignProjectResources(Guid projectId, List<Guid> resourceIds, bool cascading) {
1331    //  throw new NotImplementedException();
1332    //}
1333
1334    //private void UnassignProjectResources(Guid projectId, List<Guid> resourceIds, bool cascading) {
1335    //  RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1336    //  if (projectId == null || resourceIds == null || !resourceIds.Any()) return;
1337    //  AuthorizationManager.AuthorizeForProjectResourceAdministration(projectId, resourceIds);
1338    //  var pm = PersistenceManager;
1339    //  using (new PerformanceLogger("UnassignProjectResources")) {
1340    //    var assignedProjectResourceDao = pm.AssignedProjectResourceDao;
1341    //    var assignedJobResourceDao = pm.AssignedJobResourceDao;
1342    //    var projectDao = pm.ProjectDao;
1343    //    pm.UseTransaction(() => {
1344    //      if (cascading) {
1345    //        var childProjectIds = projectDao.GetChildProjectIdsById(projectId).ToList();
1346    //        assignedProjectResourceDao.DeleteByProjectIdsAndResourceIds(childProjectIds, resourceIds);
1347    //        assignedJobResourceDao.DeleteByProjectIdsAndResourceIds(childProjectIds, resourceIds);
1348    //      }
1349    //      assignedProjectResourceDao.DeleteByProjectIdAndResourceIds(projectId, resourceIds);
1350    //      assignedJobResourceDao.DeleteByProjectIdAndResourceIds(projectId, resourceIds);
1351    //      pm.SubmitChanges();
1352    //    });
1353    //  }
1354    //}
1355
1356    public IEnumerable<DT.AssignedProjectResource> GetAssignedResourcesForProject(Guid projectId) {
1357      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1358      AuthorizationManager.AuthorizeUserForProjectUse(UserManager.CurrentUserId, projectId);
1359      var pm = PersistenceManager;
1360      using (new PerformanceLogger("GetAssignedResourcesForProject")) {
1361        var assignedProjectResourceDao = pm.AssignedProjectResourceDao;
1362        return pm.UseTransaction(() => assignedProjectResourceDao.GetByProjectId(projectId)
1363          .Select(x => x.ToDto())
1364          .ToList()
1365        );
1366      }
1367    }
1368
1369    public IEnumerable<DT.AssignedProjectResource> GetAssignedResourcesForProjectAdministration(Guid projectId) {
1370      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1371      AuthorizationManager.AuthorizeForProjectAdministration(projectId, false);
1372      var pm = PersistenceManager;
1373      using (new PerformanceLogger("GetAssignedResourcesForProject")) {
1374        var assignedProjectResourceDao = pm.AssignedProjectResourceDao;
1375        return pm.UseTransaction(() => assignedProjectResourceDao.GetByProjectId(projectId)
1376          .Select(x => x.ToDto())
1377          .ToList()
1378        );
1379      }
1380    }
1381
1382    public IEnumerable<DT.AssignedProjectResource> GetAssignedResourcesForProjectsAdministration(IEnumerable<Guid> projectIds) {
1383      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1384      foreach (var id in projectIds)
1385        AuthorizationManager.AuthorizeForProjectAdministration(id, false);
1386
1387      var pm = PersistenceManager;
1388      using (new PerformanceLogger("GetAssignedResourcesForProject")) {
1389        var assignedProjectResourceDao = pm.AssignedProjectResourceDao;
1390        var assignments = new List<DT.AssignedProjectResource>();
1391        pm.UseTransaction(() => {
1392          foreach (var id in projectIds) {
1393            assignments.AddRange(assignedProjectResourceDao.GetByProjectId(id)
1394              .Select(x => x.ToDto()));
1395          }
1396        });
1397        return assignments.Distinct();
1398      }
1399    }
1400
1401    #endregion
1402
1403    #region Slave Methods
1404    public Guid AddSlave(DT.Slave slaveDto) {
1405      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
1406      var pm = PersistenceManager;
1407      using (new PerformanceLogger("AddSlave")) {
1408        var slaveDao = pm.SlaveDao;
1409        return pm.UseTransaction(() => {
1410          var slave = slaveDao.Save(slaveDto.ToEntity());
1411          pm.SubmitChanges();
1412          return slave.ResourceId;
1413        });
1414      }
1415    }
1416
1417    public Guid AddSlaveGroup(DT.SlaveGroup slaveGroupDto) {
1418      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
1419      var pm = PersistenceManager;
1420      using (new PerformanceLogger("AddSlaveGroup")) {
1421        var slaveGroupDao = pm.SlaveGroupDao;
1422        return pm.UseTransaction(() => {
1423          if (slaveGroupDto.Id == Guid.Empty) {
1424            slaveGroupDto.Id = Guid.NewGuid();
1425          }
1426          var slaveGroup = slaveGroupDao.Save(slaveGroupDto.ToEntity());
1427          pm.SubmitChanges();
1428          return slaveGroup.ResourceId;
1429        });
1430      }
1431    }
1432
1433    public DT.Slave GetSlave(Guid slaveId) {
1434      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
1435      var pm = PersistenceManager;
1436      using (new PerformanceLogger("GetSlave")) {
1437        var slaveDao = pm.SlaveDao;
1438        return pm.UseTransaction(() => slaveDao.GetById(slaveId).ToDto());
1439      }
1440    }
1441
1442    // query granted slaves for use (i.e. to calculate on)
1443    public IEnumerable<DT.Slave> GetSlaves() {
1444      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1445      var pm = PersistenceManager;
1446      using (new PerformanceLogger("GetSlaves")) {
1447        var slaveDao = pm.SlaveDao;
1448        var projectDao = pm.ProjectDao;
1449        var assignedProjectResourceDao = pm.AssignedProjectResourceDao;
1450
1451        // collect user information
1452        var currentUserId = UserManager.CurrentUserId;
1453        var userAndGroupIds = new List<Guid> { currentUserId };
1454        userAndGroupIds.AddRange(UserManager.GetUserGroupIdsOfUser(currentUserId));
1455
1456        return pm.UseTransaction(() => {
1457          var slaves = slaveDao.GetAll()
1458            .Select(x => x.ToDto())
1459            .ToList();
1460          var grantedProjectIds = projectDao.GetUsageGrantedProjectsForUser(userAndGroupIds)
1461            .Select(x => x.ProjectId)
1462            .ToList();
1463          var grantedResourceIds = assignedProjectResourceDao.GetAllGrantedResourcesByProjectIds(grantedProjectIds)
1464            .Select(x => x.ResourceId)
1465            .ToList();
1466
1467          return slaves
1468            .Where(x => grantedResourceIds.Contains(x.Id))
1469            .ToList();
1470        });
1471      }
1472    }
1473
1474    // query granted slave groups for use (i.e. to calculate on)
1475    public IEnumerable<DT.SlaveGroup> GetSlaveGroups() {
1476      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1477      var pm = PersistenceManager;
1478      using (new PerformanceLogger("GetSlaveGroups")) {
1479        var slaveGroupDao = pm.SlaveGroupDao;
1480        var projectDao = pm.ProjectDao;
1481        var assignedProjectResourceDao = pm.AssignedProjectResourceDao;
1482
1483        // collect user information
1484        var currentUserId = UserManager.CurrentUserId;
1485        var userAndGroupIds = new List<Guid> { currentUserId };
1486        userAndGroupIds.AddRange(UserManager.GetUserGroupIdsOfUser(currentUserId));
1487
1488        return pm.UseTransaction(() => {
1489          var slaveGroups = slaveGroupDao.GetAll()
1490            .Select(x => x.ToDto())
1491            .ToList();
1492          var grantedProjectIds = projectDao.GetUsageGrantedProjectsForUser(userAndGroupIds)
1493            .Select(x => x.ProjectId)
1494            .ToList();
1495          var grantedResourceIds = assignedProjectResourceDao.GetAllGrantedResourcesByProjectIds(grantedProjectIds)
1496            .Select(x => x.ResourceId)
1497            .ToList();
1498
1499          return slaveGroups
1500            .Where(x => grantedResourceIds.Contains(x.Id))
1501            .ToList();
1502        });
1503      }
1504    }
1505
1506    // query granted slaves for resource administration
1507    public IEnumerable<DT.Slave> GetSlavesForAdministration() {
1508      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1509      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
1510      var pm = PersistenceManager;
1511      using (new PerformanceLogger("GetSlavesForAdministration")) {
1512        var slaveDao = pm.SlaveDao;
1513        var currentUserId = UserManager.CurrentUserId;
1514
1515        if (isAdministrator) {
1516          return pm.UseTransaction(() => {
1517            return slaveDao.GetAll()
1518              .Select(x => x.ToDto())
1519              .ToList();
1520          });
1521        } else {
1522          var slaves = slaveDao.GetAll()
1523            .Select(x => x.ToDto())
1524            .ToList();
1525          var projectDao = pm.ProjectDao;
1526          var assignedProjectResourceDao = pm.AssignedProjectResourceDao;
1527          var projects = projectDao.GetAdministrationGrantedProjectsForUser(currentUserId).ToList();
1528          var resourceIds = assignedProjectResourceDao
1529            .GetAllGrantedResourcesByProjectIds(projects.Select(x => x.ProjectId).ToList())
1530            .Select(x => x.ResourceId)
1531            .ToList();
1532
1533          return slaves
1534            .Where(x => resourceIds.Contains(x.Id))
1535            .ToList();
1536        }
1537      }
1538    }
1539
1540    // query granted slave groups for resource administration
1541    public IEnumerable<DT.SlaveGroup> GetSlaveGroupsForAdministration() {
1542      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1543      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
1544      var pm = PersistenceManager;
1545      using (new PerformanceLogger("GetSlaveGroupsForAdministration")) {
1546        var slaveGroupDao = pm.SlaveGroupDao;
1547        var currentUserId = UserManager.CurrentUserId;
1548
1549        if (isAdministrator) {
1550          return pm.UseTransaction(() => {
1551            return slaveGroupDao.GetAll()
1552              .Select(x => x.ToDto())
1553              .ToList();
1554          });
1555        } else {
1556          var slaveGroups = slaveGroupDao.GetAll()
1557            .Select(x => x.ToDto())
1558            .ToList();
1559          var projectDao = pm.ProjectDao;
1560          var assignedProjectResourceDao = pm.AssignedProjectResourceDao;
1561          var projects = projectDao.GetAdministrationGrantedProjectsForUser(currentUserId).ToList();
1562          var resourceIds = assignedProjectResourceDao
1563            .GetAllGrantedResourcesByProjectIds(projects.Select(x => x.ProjectId).ToList())
1564            .Select(x => x.ResourceId)
1565            .ToList();
1566
1567          return slaveGroups
1568            .Where(x => resourceIds.Contains(x.Id))
1569            .ToList();
1570        }
1571      }
1572    }
1573
1574    public IDictionary<Guid, HashSet<Guid>> GetResourceGenealogy() {
1575      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1576      var pm = PersistenceManager;
1577      using (new PerformanceLogger("GetResourceGenealogy")) {
1578        var resourceDao = pm.ResourceDao;
1579        var resourceAncestors = new Dictionary<Guid, HashSet<Guid>>();
1580        return pm.UseTransaction(() => {
1581          var resources = resourceDao.GetAll().ToList();
1582          resources.ForEach(r => resourceAncestors.Add(r.ResourceId, new HashSet<Guid>()));
1583
1584          foreach (var r in resources) {
1585            var parentResource = r.ParentResource;
1586            while (parentResource != null) {
1587              resourceAncestors[r.ResourceId].Add(parentResource.ResourceId);
1588              parentResource = parentResource.ParentResource;
1589            }
1590          }
1591          return resourceAncestors;
1592        });
1593      }
1594    }
1595
1596    public IDictionary<Guid, string> GetResourceNames() {
1597      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1598      var pm = PersistenceManager;
1599      using (new PerformanceLogger("GetResourceNames")) {
1600        var resourceDao = pm.ResourceDao;
1601        var resourceNames = new Dictionary<Guid, string>();
1602        return pm.UseTransaction(() => {
1603          resourceDao
1604            .GetAll().ToList()
1605            .ForEach(p => resourceNames.Add(p.ResourceId, p.Name));
1606          return resourceNames;
1607        });
1608      }
1609    }
1610
1611    public void UpdateSlave(DT.Slave slaveDto) {
1612      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1613      if (slaveDto == null) return;
1614      AuthorizationManager.AuthorizeForResourceAdministration(slaveDto.Id);
1615      var pm = PersistenceManager;
1616      using (new PerformanceLogger("UpdateSlave")) {
1617        var slaveDao = pm.SlaveDao;
1618        pm.UseTransaction(() => {
1619          var slave = slaveDao.GetById(slaveDto.Id);
1620          if (slave != null) {
1621            slaveDto.CopyToEntity(slave);
1622          } else {
1623            slaveDao.Save(slaveDto.ToEntity());
1624          }
1625          pm.SubmitChanges();
1626        });
1627      }
1628    }
1629
1630    public void UpdateSlaveGroup(DT.SlaveGroup slaveGroupDto) {
1631      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1632      if (slaveGroupDto == null) return;
1633      AuthorizationManager.AuthorizeForResourceAdministration(slaveGroupDto.Id);
1634      var pm = PersistenceManager;
1635      using (new PerformanceLogger("UpdateSlaveGroup")) {
1636        var slaveGroupDao = pm.SlaveGroupDao;
1637        pm.UseTransaction(() => {
1638          var slaveGroup = slaveGroupDao.GetById(slaveGroupDto.Id);
1639          if (slaveGroup != null) {
1640            slaveGroupDto.CopyToEntity(slaveGroup);
1641          } else {
1642            slaveGroupDao.Save(slaveGroupDto.ToEntity());
1643          }
1644          pm.SubmitChanges();
1645        });
1646      }
1647    }
1648
1649    public void DeleteSlave(Guid slaveId) {
1650      if (slaveId == Guid.Empty) return;
1651      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1652      AuthorizationManager.AuthorizeForResourceAdministration(slaveId);
1653      var pm = PersistenceManager;
1654      using (new PerformanceLogger("DeleteSlave")) {
1655        var slaveDao = pm.SlaveDao;
1656        pm.UseTransaction(() => {
1657          slaveDao.Delete(slaveId);
1658          pm.SubmitChanges();
1659        });
1660      }
1661    }
1662
1663    public void DeleteSlaveGroup(Guid slaveGroupId) {
1664      if (slaveGroupId == Guid.Empty) return;
1665      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1666      AuthorizationManager.AuthorizeForResourceAdministration(slaveGroupId);
1667      var pm = PersistenceManager;
1668      using (new PerformanceLogger("DeleteSlaveGroup")) {
1669        var resourceDao = pm.ResourceDao;
1670        pm.UseTransaction(() => {
1671          var resourceIds = new HashSet<Guid> { slaveGroupId };
1672          resourceIds.Union(resourceDao.GetChildResourceIdsById(slaveGroupId));
1673          resourceDao.DeleteByIds(resourceIds);
1674          pm.SubmitChanges();
1675        });
1676      }
1677    }
1678
1679    public void AddResourceToGroup(Guid slaveGroupId, Guid resourceId) {
1680      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
1681      var pm = PersistenceManager;
1682      using (new PerformanceLogger("AddResourceToGroup")) {
1683        var resourceDao = pm.ResourceDao;
1684        pm.UseTransaction(() => {
1685          var resource = resourceDao.GetById(resourceId);
1686          resource.ParentResourceId = slaveGroupId;
1687          pm.SubmitChanges();
1688        });
1689      }
1690    }
1691
1692    public void RemoveResourceFromGroup(Guid slaveGroupId, Guid resourceId) {
1693      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
1694      var pm = PersistenceManager;
1695      using (new PerformanceLogger("RemoveResourceFromGroup")) {
1696        var resourceDao = pm.ResourceDao;
1697        pm.UseTransaction(() => {
1698          var resource = resourceDao.GetById(resourceId);
1699          resource.ParentResourceId = null;
1700          pm.SubmitChanges();
1701        });
1702      }
1703    }
1704
1705    public Guid GetResourceId(string resourceName) {
1706      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1707      var pm = PersistenceManager;
1708      using (new PerformanceLogger("GetResourceId")) {
1709        var resourceDao = pm.ResourceDao;
1710        return pm.UseTransaction(() => {
1711          var resource = resourceDao.GetByName(resourceName);
1712          return resource != null ? resource.ResourceId : Guid.Empty;
1713        });
1714      }
1715    }
1716
1717    public void TriggerEventManager(bool force) {
1718      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
1719      // use a serializable transaction here to ensure not two threads execute this simultaniously (mutex-lock would not work since IIS may use multiple AppDomains)
1720      bool cleanup;
1721      var pm = PersistenceManager;
1722      using (new PerformanceLogger("TriggerEventManager")) {
1723        cleanup = false;
1724        var lifecycleDao = pm.LifecycleDao;
1725        pm.UseTransaction(() => {
1726          var lastLifecycle = lifecycleDao.GetLastLifecycle();
1727          DateTime lastCleanup = lastLifecycle != null ? lastLifecycle.LastCleanup : DateTime.MinValue;
1728          if (force || DateTime.Now - lastCleanup > HeuristicLab.Services.Hive.Properties.Settings.Default.CleanupInterval) {
1729            lifecycleDao.UpdateLifecycle();
1730            cleanup = true;
1731            pm.SubmitChanges();
1732          }
1733        }, true);
1734      }
1735      if (cleanup) {
1736        EventManager.Cleanup();
1737      }
1738    }
1739
1740    public int GetNewHeartbeatInterval(Guid slaveId) {
1741      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
1742      var pm = PersistenceManager;
1743      using (new PerformanceLogger("GetNewHeartbeatInterval")) {
1744        var slaveDao = pm.SlaveDao;
1745        return pm.UseTransaction(() => {
1746          var slave = slaveDao.GetById(slaveId);
1747          if (slave != null) {
1748            return slave.HbInterval;
1749          }
1750          return -1;
1751        });
1752      }
1753    }
1754    #endregion
1755
1756    #region Downtime Methods
1757    public Guid AddDowntime(DT.Downtime downtimeDto) {
1758      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1759      AuthorizationManager.AuthorizeForResourceAdministration(downtimeDto.ResourceId);
1760      var pm = PersistenceManager;
1761      using (new PerformanceLogger("AddDowntime")) {
1762        var downtimeDao = pm.DowntimeDao;
1763        return pm.UseTransaction(() => {
1764          var downtime = downtimeDao.Save(downtimeDto.ToEntity());
1765          pm.SubmitChanges();
1766          return downtime.ResourceId;
1767        });
1768      }
1769    }
1770
1771    public void DeleteDowntime(Guid downtimeId) {
1772      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1773      var pm = PersistenceManager;
1774      using (new PerformanceLogger("DeleteDowntime")) {
1775        var downtimeDao = pm.DowntimeDao;
1776        pm.UseTransaction(() => {
1777          downtimeDao.Delete(downtimeId);
1778          pm.SubmitChanges();
1779        });
1780      }
1781    }
1782
1783    public void UpdateDowntime(DT.Downtime downtimeDto) {
1784      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1785      AuthorizationManager.AuthorizeForResourceAdministration(downtimeDto.ResourceId);
1786      var pm = PersistenceManager;
1787      using (new PerformanceLogger("UpdateDowntime")) {
1788        var downtimeDao = pm.DowntimeDao;
1789        pm.UseTransaction(() => {
1790          var downtime = downtimeDao.GetById(downtimeDto.Id);
1791          if (downtime != null) {
1792            downtimeDto.CopyToEntity(downtime);
1793          } else {
1794            downtimeDao.Save(downtimeDto.ToEntity());
1795          }
1796          pm.SubmitChanges();
1797        });
1798      }
1799    }
1800
1801    public IEnumerable<DT.Downtime> GetDowntimesForResource(Guid resourceId) {
1802      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1803      var pm = PersistenceManager;
1804      using (new PerformanceLogger("GetDowntimesForResource")) {
1805        var downtimeDao = pm.DowntimeDao;
1806        return pm.UseTransaction(() => downtimeDao.GetByResourceId(resourceId)
1807          .Select(x => x.ToDto())
1808          .ToList()
1809        );
1810      }
1811    }
1812    #endregion
1813
1814    #region User Methods
1815    public string GetUsernameByUserId(Guid userId) {
1816      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1817      var user = UserManager.GetUserById(userId);
1818      return user != null ? user.UserName : null;
1819    }
1820
1821    public Guid GetUserIdByUsername(string username) {
1822      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1823      var user = ServiceLocator.Instance.UserManager.GetUserByName(username);
1824      return user != null ? (Guid?)user.ProviderUserKey ?? Guid.Empty : Guid.Empty;
1825    }
1826
1827    public Dictionary<Guid, HashSet<Guid>> GetUserGroupTree() {
1828      var userGroupTree = new Dictionary<Guid, HashSet<Guid>>();
1829      var userGroupMapping = UserManager.GetUserGroupMapping();
1830
1831      foreach (var ugm in userGroupMapping) {
1832        if (ugm.Parent == null || ugm.Child == null) continue;
1833
1834        if (!userGroupTree.ContainsKey(ugm.Parent)) {
1835          userGroupTree.Add(ugm.Parent, new HashSet<Guid>());
1836        }
1837        userGroupTree[ugm.Parent].Add(ugm.Child);
1838      }
1839
1840      return userGroupTree;
1841    }
1842
1843    public bool CheckAccessToAdminAreaGranted() {
1844      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1845      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
1846      var pm = PersistenceManager;
1847      using (new PerformanceLogger("CheckAccessToAdminAreaGranted")) {
1848        if (isAdministrator) {
1849          return true;
1850        } else {
1851          var projectDao = pm.ProjectDao;
1852          var currentUserId = UserManager.CurrentUserId;
1853          return projectDao.GetAdministrationGrantedProjectsForUser(currentUserId).Any();
1854        }
1855      }
1856    }
1857    #endregion
1858
1859    #region UserPriorities Methods
1860    public IEnumerable<DT.UserPriority> GetUserPriorities() {
1861      var pm = PersistenceManager;
1862      using (new PerformanceLogger("GetUserPriorities")) {
1863        var userPriorityDao = pm.UserPriorityDao;
1864        return pm.UseTransaction(() => userPriorityDao.GetAll()
1865          .Select(x => x.ToDto())
1866          .ToList()
1867        );
1868      }
1869    }
1870    #endregion
1871
1872    #region Private Helper Methods
1873    private void UpdateTaskState(IPersistenceManager pm, DA.Task task, DT.TaskState taskState, Guid? slaveId, Guid? userId, string exception) {
1874      var stateLogDao = pm.StateLogDao;
1875      var taskStateEntity = taskState.ToEntity();
1876
1877      if (task.State == DA.TaskState.Transferring && taskStateEntity == DA.TaskState.Paused && task.Command == null) {
1878        // slave paused and uploaded the task (no user-command) -> set waiting.
1879        taskStateEntity = DA.TaskState.Waiting;
1880      }
1881
1882      stateLogDao.Save(new DA.StateLog {
1883        State = taskStateEntity,
1884        DateTime = DateTime.Now,
1885        TaskId = task.TaskId,
1886        UserId = userId,
1887        SlaveId = slaveId,
1888        Exception = exception
1889      });
1890
1891      task.State = taskStateEntity;
1892
1893      if (task.Command == DA.Command.Pause && task.State == DA.TaskState.Paused
1894          || task.Command == DA.Command.Abort && task.State == DA.TaskState.Aborted
1895          || task.Command == DA.Command.Stop && task.State == DA.TaskState.Aborted) {
1896        task.Command = null;
1897      }
1898    }
1899
1900    private void CheckProjectAvailability(IPersistenceManager pm, Guid projectId, DateTime date) {
1901      var projectDao = pm.ProjectDao;
1902      using (new PerformanceLogger("UpdateJob")) {
1903        var project = pm.UseTransaction(() => {
1904          return projectDao.GetById(projectId);
1905        });
1906        if (project != null) {
1907          if (project.StartDate > date) throw new ArgumentException("Cannot add job to specified project. The start date of the project is still in the future.");
1908          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.");
1909        } else {
1910          throw new ArgumentException("Cannot add job to specified project. The project seems not to be available anymore.");
1911        }
1912      }
1913    }
1914
1915    private void EvaluateJobs(IPersistenceManager pm, IEnumerable<DT.Job> jobs) {
1916      if (jobs == null || !jobs.Any()) return;
1917
1918      var currentUserId = UserManager.CurrentUserId;
1919      var taskDao = pm.TaskDao;
1920      var jobPermissionDao = pm.JobPermissionDao;
1921
1922      var statistics = taskDao.GetAll()
1923        .Where(x => jobs.Select(y => y.Id).Contains(x.JobId))
1924        .GroupBy(x => x.JobId)
1925        .Select(x => new {
1926          x.Key,
1927          TotalCount = x.Count(),
1928          CalculatingCount = x.Count(y => y.State == DA.TaskState.Calculating),
1929          FinishedCount = x.Count(y => CompletedStates.Contains(y.State))
1930        })
1931        .ToList();
1932
1933      foreach (var job in jobs) {
1934        var statistic = statistics.FirstOrDefault(x => x.Key == job.Id);
1935        if (statistic != null) {
1936          job.JobCount = statistic.TotalCount;
1937          job.CalculatingCount = statistic.CalculatingCount;
1938          job.FinishedCount = statistic.FinishedCount;
1939        }
1940
1941        job.OwnerUsername = UserManager.GetUserNameById(job.OwnerUserId);
1942
1943        if (currentUserId == job.OwnerUserId) {
1944          job.Permission = Permission.Full;
1945        } else {
1946          var jobPermission = jobPermissionDao.GetByJobAndUserId(job.Id, currentUserId);
1947          job.Permission = jobPermission == null ? Permission.NotAllowed : jobPermission.Permission.ToDto();
1948        }
1949      }
1950    }
1951    #endregion
1952  }
1953}
Note: See TracBrowser for help on using the repository browser.