Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2817-BinPackingSpeedup/HeuristicLab.Services.Hive/3.3/HiveService.cs @ 16559

Last change on this file since 16559 was 16141, checked in by abeham, 6 years ago

#2817: updated to trunk r16140

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