Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2925_AutoDiffForDynamicalModels/HeuristicLab.Services.Hive/3.3/HiveService.cs @ 16662

Last change on this file since 16662 was 16662, checked in by gkronber, 6 years ago

#2925: merged all changes from trunk to branch (up to r16659)

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