Free cookie consent management tool by TermsFeed Policy Generator

source: branches/3026_IntegrationIntoSymSpace/HeuristicLab.Services.Hive/3.3/HiveService.cs @ 17928

Last change on this file since 17928 was 17928, checked in by dpiringe, 3 years ago

#3026

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