Free cookie consent management tool by TermsFeed Policy Generator

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

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

#2839: fixed handling of project related updates for project owners, who are no admins and do not own parent projects

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