Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/HiveService.cs @ 15508

Last change on this file since 15508 was 15508, checked in by jzenisek, 5 years ago

#2839 finalized permission checks in AddTask and revised implementation of ResourcePermission methods

File size: 54.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using System.Security;
26using System.ServiceModel;
27using HeuristicLab.Services.Access;
28using HeuristicLab.Services.Hive.DataAccess.Interfaces;
29using HeuristicLab.Services.Hive.DataTransfer;
30using HeuristicLab.Services.Hive.Manager;
31using HeuristicLab.Services.Hive.ServiceContracts;
32using DA = HeuristicLab.Services.Hive.DataAccess;
33using DT = HeuristicLab.Services.Hive.DataTransfer;
34
35namespace HeuristicLab.Services.Hive {
36  /// <summary>
37  /// Implementation of the Hive service (interface <see cref="IHiveService"/>).
38  /// We need 'IgnoreExtensionDataObject' Attribute for the slave to work.
39  /// </summary>
40  [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, IgnoreExtensionDataObject = true)]
41  [HiveOperationContextBehavior]
42  public class HiveService : IHiveService {
43    private const string NOT_AUTHORIZED_RESOURCE = "Current user is not authorized to access the requested resource";
44    private const string NOT_AUTHORIZED_PROJECT = "Current user is not authorized to access the requested project";
45
46    private static readonly DA.TaskState[] CompletedStates = { DA.TaskState.Finished, DA.TaskState.Aborted, DA.TaskState.Failed };
47
48    private IPersistenceManager PersistenceManager {
49      get { return ServiceLocator.Instance.PersistenceManager; }
50    }
51
52    private IUserManager UserManager {
53      get { return ServiceLocator.Instance.UserManager; }
54    }
55
56    private IRoleVerifier RoleVerifier {
57      get { return ServiceLocator.Instance.RoleVerifier; }
58    }
59
60    private IAuthorizationManager AuthorizationManager {
61      get { return ServiceLocator.Instance.AuthorizationManager; }
62    }
63    private IEventManager EventManager {
64      get { return ServiceLocator.Instance.EventManager; }
65    }
66    private HeartbeatManager HeartbeatManager {
67      get { return ServiceLocator.Instance.HeartbeatManager; }
68    }
69
70    #region Task Methods
71    public Guid AddTask(DT.Task task, DT.TaskData taskData, IEnumerable<Guid> resourceIds) {
72      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
73      var pm = PersistenceManager;
74      using (new PerformanceLogger("AddTask")) {
75        var taskDao = pm.TaskDao;
76        var stateLogDao = pm.StateLogDao;
77
78        pm.UseTransaction(() => {
79          CheckTaskPermissions(pm, task, resourceIds);
80        });
81
82        var newTask = task.ToEntity();
83        newTask.JobData = taskData.ToEntity();
84        newTask.JobData.LastUpdate = DateTime.Now;
85        newTask.AssignedTaskResources.AddRange(resourceIds.Select(
86          x => new DA.AssignedTaskResource {
87            ResourceId = x
88          }));
89        newTask.State = DA.TaskState.Waiting;
90        return pm.UseTransaction(() => {
91          taskDao.Save(newTask);
92          pm.SubmitChanges();
93          stateLogDao.Save(new DA.StateLog {
94            State = DA.TaskState.Waiting,
95            DateTime = DateTime.Now,
96            TaskId = newTask.TaskId,
97            UserId = UserManager.CurrentUserId,
98            SlaveId = null,
99            Exception = null
100          });
101          pm.SubmitChanges();
102          return newTask.TaskId;
103        }, false, true);
104      }
105    }
106
107    public Guid AddChildTask(Guid parentTaskId, DT.Task task, DT.TaskData taskData) {
108      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
109      IEnumerable<Guid> resourceIds;
110      var pm = PersistenceManager;
111      using (new PerformanceLogger("AddChildTask")) {
112        var assignedTaskResourceDao = pm.AssignedTaskResourceDao;
113        resourceIds = pm.UseTransaction(() => {
114          return assignedTaskResourceDao.GetByTaskId(parentTaskId)
115            .Select(x => x.ResourceId)
116            .ToList();
117        });
118      }
119      task.ParentTaskId = parentTaskId;
120      return AddTask(task, taskData, resourceIds);
121    }
122
123    public DT.Task GetTask(Guid taskId) {
124      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
125      AuthorizationManager.AuthorizeForTask(taskId, Permission.Read);
126      var pm = PersistenceManager;
127      using (new PerformanceLogger("GetTask")) {
128        var taskDao = pm.TaskDao;
129        return pm.UseTransaction(() => {
130          var task = taskDao.GetById(taskId);
131          return task.ToDto();
132        });
133      }
134    }
135
136    public IEnumerable<DT.LightweightTask> GetLightweightJobTasks(Guid jobId) {
137      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
138      AuthorizationManager.AuthorizeForJob(jobId, Permission.Read);
139      var pm = PersistenceManager;
140      using (new PerformanceLogger("GetLightweightJobTasks")) {
141        var taskDao = pm.TaskDao;
142        return pm.UseTransaction(() => {
143          return taskDao.GetByJobId(jobId)
144            .ToList()
145            .Select(x => new DT.LightweightTask {
146              Id = x.TaskId,
147              ExecutionTime = TimeSpan.FromMilliseconds(x.ExecutionTimeMs),
148              ParentTaskId = x.ParentTaskId,
149              StateLog = x.StateLogs.OrderBy(y => y.DateTime)
150                                    .Select(z => z.ToDto())
151                                    .ToList(),
152              State = x.State.ToDto(),
153              Command = x.Command.ToDto(),
154              LastTaskDataUpdate = x.JobData.LastUpdate
155            })
156            .ToList();
157        }, false, true);
158      }
159    }
160
161    public IEnumerable<DT.LightweightTask> GetLightweightJobTasksWithoutStateLog(Guid jobId) {
162      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
163      AuthorizationManager.AuthorizeForJob(jobId, Permission.Read);
164      var pm = PersistenceManager;
165      using (new PerformanceLogger("GetLightweightJobTasksWithoutStateLog")) {
166        var taskDao = pm.TaskDao;
167        return pm.UseTransaction(() => {
168          return taskDao.GetByJobId(jobId)
169            .ToList()
170            .Select(x => new DT.LightweightTask {
171              Id = x.TaskId,
172              ExecutionTime = TimeSpan.FromMilliseconds(x.ExecutionTimeMs),
173              ParentTaskId = x.ParentTaskId,
174              StateLog = new List<DT.StateLog>(),
175              State = x.State.ToDto(),
176              Command = x.Command.ToDto(),
177              LastTaskDataUpdate = x.JobData.LastUpdate
178            })
179            .ToList();
180        }, false, true);
181      }
182    }
183
184    public DT.TaskData GetTaskData(Guid taskId) {
185      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
186      AuthorizationManager.AuthorizeForTask(taskId, Permission.Read);
187      var pm = PersistenceManager;
188      using (new PerformanceLogger("GetTaskData")) {
189        var taskDataDao = pm.TaskDataDao;
190        return pm.UseTransaction(() => taskDataDao.GetById(taskId).ToDto());
191      }
192    }
193
194    public void UpdateTask(DT.Task taskDto) {
195      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
196      AuthorizationManager.AuthorizeForTask(taskDto.Id, Permission.Full);
197      var pm = PersistenceManager;
198      using (new PerformanceLogger("UpdateTask")) {
199        var taskDao = pm.TaskDao;
200        pm.UseTransaction(() => {
201          var task = taskDao.GetById(taskDto.Id);
202          taskDto.CopyToEntity(task);
203          pm.SubmitChanges();
204        });
205      }
206    }
207
208    public void UpdateTaskData(DT.Task taskDto, DT.TaskData taskDataDto) {
209      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
210      AuthorizationManager.AuthorizeForTask(taskDto.Id, Permission.Full);
211      var pm = PersistenceManager;
212      using (new PerformanceLogger("UpdateTaskData")) {
213        var taskDao = pm.TaskDao;
214        var taskDataDao = pm.TaskDataDao;
215        pm.UseTransaction(() => {
216          var task = taskDao.GetById(taskDto.Id);
217          var taskData = taskDataDao.GetById(taskDataDto.TaskId);
218          taskDto.CopyToEntity(task);
219          taskDataDto.CopyToEntity(taskData);
220          taskData.LastUpdate = DateTime.Now;
221          pm.SubmitChanges();
222        });
223      }
224    }
225
226    public DT.Task UpdateTaskState(Guid taskId, DT.TaskState taskState, Guid? slaveId, Guid? userId, string exception) {
227      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
228      AuthorizationManager.AuthorizeForTask(taskId, Permission.Full);
229      var pm = PersistenceManager;
230      using (new PerformanceLogger("UpdateTaskState")) {
231        var taskDao = pm.TaskDao;
232        return pm.UseTransaction(() => {
233          var task = taskDao.GetById(taskId);
234          UpdateTaskState(pm, task, taskState, slaveId, userId, exception);
235          pm.SubmitChanges();
236          return task.ToDto();
237        });
238      }
239    }
240    #endregion
241
242    #region Task Control Methods
243    public void StopTask(Guid taskId) {
244      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
245      AuthorizationManager.AuthorizeForTask(taskId, Permission.Full);
246      var pm = PersistenceManager;
247      using (new PerformanceLogger("StopTask")) {
248        var taskDao = pm.TaskDao;
249        pm.UseTransaction(() => {
250          var task = taskDao.GetById(taskId);
251          if (task.State == DA.TaskState.Calculating || task.State == DA.TaskState.Transferring) {
252            task.Command = DA.Command.Stop;
253          } else if (task.State != DA.TaskState.Aborted
254                     && task.State != DA.TaskState.Finished
255                     && task.State != DA.TaskState.Failed) {
256            UpdateTaskState(pm, task, DT.TaskState.Aborted, null, null, string.Empty);
257          }
258          pm.SubmitChanges();
259        });
260      }
261    }
262
263    public void PauseTask(Guid taskId) {
264      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
265      AuthorizationManager.AuthorizeForTask(taskId, Permission.Full);
266      var pm = PersistenceManager;
267      using (new PerformanceLogger("PauseTask")) {
268        var taskDao = pm.TaskDao;
269        pm.UseTransaction(() => {
270          var task = taskDao.GetById(taskId);
271          if (task.State == DA.TaskState.Calculating || task.State == DA.TaskState.Transferring) {
272            task.Command = DA.Command.Pause;
273          } else if (task.State != DA.TaskState.Paused
274                     && task.State != DA.TaskState.Aborted
275                     && task.State != DA.TaskState.Finished
276                     && task.State != DA.TaskState.Failed) {
277            UpdateTaskState(pm, task, DT.TaskState.Paused, null, null, string.Empty);
278          }
279          pm.SubmitChanges();
280        });
281      }
282    }
283
284    public void RestartTask(Guid taskId) {
285      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
286      AuthorizationManager.AuthorizeForTask(taskId, Permission.Full);
287      var pm = PersistenceManager;
288      using (new PerformanceLogger("RestartTask")) {
289        var taskDao = pm.TaskDao;
290        pm.UseTransaction(() => {
291          var task = taskDao.GetById(taskId);
292          task.Command = null;
293          UpdateTaskState(pm, task, DT.TaskState.Waiting, null, UserManager.CurrentUserId, string.Empty);
294          pm.SubmitChanges();
295        });
296      }
297    }
298    #endregion
299
300    #region Job Methods
301    public DT.Job GetJob(Guid id) {
302      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
303      AuthorizationManager.AuthorizeForJob(id, DT.Permission.Read);
304      var pm = PersistenceManager;
305      using (new PerformanceLogger("GetJob")) {
306        var jobDao = pm.JobDao;
307        var jobPermissionDao = pm.JobPermissionDao;
308        var taskDao = pm.TaskDao;
309        var currentUserId = UserManager.CurrentUserId;
310        return pm.UseTransaction(() => {
311          var job = jobDao.GetById(id).ToDto();
312          if (job != null) {
313            var statistics = taskDao.GetByJobId(job.Id)
314              .GroupBy(x => x.JobId)
315              .Select(x => new {
316                TotalCount = x.Count(),
317                CalculatingCount = x.Count(y => y.State == DA.TaskState.Calculating),
318                FinishedCount = x.Count(y => CompletedStates.Contains(y.State))
319              }).FirstOrDefault();
320            if (statistics != null) {
321              job.JobCount = statistics.TotalCount;
322              job.CalculatingCount = statistics.CalculatingCount;
323              job.FinishedCount = statistics.FinishedCount;
324            }
325            job.OwnerUsername = UserManager.GetUserNameById(job.OwnerUserId);
326            if (currentUserId == job.OwnerUserId) {
327              job.Permission = Permission.Full;
328            } else {
329              var jobPermission = jobPermissionDao.GetByJobAndUserId(job.Id, currentUserId);
330              job.Permission = jobPermission == null ? Permission.NotAllowed : jobPermission.Permission.ToDto();
331            }
332          }
333          return job;
334        });
335      }
336    }
337
338    public IEnumerable<DT.Job> GetJobs() {
339      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
340      var pm = PersistenceManager;
341      using (new PerformanceLogger("GetJobs")) {
342        var jobDao = pm.JobDao;
343        var jobPermissionDao = pm.JobPermissionDao;
344        var taskDao = pm.TaskDao;
345        var currentUserId = UserManager.CurrentUserId;
346        return pm.UseTransaction(() => {
347          var jobs = jobDao.GetAll()
348            .Where(x => x.OwnerUserId == currentUserId
349                     || x.JobPermissions.Count(y => y.Permission != DA.Permission.NotAllowed
350                                                 && y.GrantedUserId == currentUserId) > 0)
351            .Select(x => x.ToDto())
352            .ToList();
353          var statistics = taskDao.GetAll()
354              .GroupBy(x => x.JobId)
355              .Select(x => new {
356                x.Key,
357                TotalCount = x.Count(),
358                CalculatingCount = x.Count(y => y.State == DA.TaskState.Calculating),
359                FinishedCount = x.Count(y => CompletedStates.Contains(y.State))
360              })
361              .ToList();
362          foreach (var job in jobs) {
363            var statistic = statistics.FirstOrDefault(x => x.Key == job.Id);
364            if (statistic != null) {
365              job.JobCount = statistic.TotalCount;
366              job.CalculatingCount = statistic.CalculatingCount;
367              job.FinishedCount = statistic.FinishedCount;
368            }
369            job.OwnerUsername = UserManager.GetUserNameById(job.OwnerUserId);
370            if (currentUserId == job.OwnerUserId) {
371              job.Permission = Permission.Full;
372            } else {
373              var jobPermission = jobPermissionDao.GetByJobAndUserId(job.Id, currentUserId);
374              job.Permission = jobPermission == null ? Permission.NotAllowed : jobPermission.Permission.ToDto();
375            }
376          }
377          return jobs;
378        });
379      }
380    }
381
382    public Guid AddJob(DT.Job jobDto) {
383      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
384      var pm = PersistenceManager;
385      using (new PerformanceLogger("AddJob")) {
386        var jobDao = pm.JobDao;
387        var userPriorityDao = pm.UserPriorityDao;
388        return pm.UseTransaction(() => {
389          jobDto.OwnerUserId = UserManager.CurrentUserId;
390          jobDto.DateCreated = DateTime.Now;
391          var job = jobDao.Save(jobDto.ToEntity());
392          if (userPriorityDao.GetById(jobDto.OwnerUserId) == null) {
393            userPriorityDao.Save(new DA.UserPriority {
394              UserId = jobDto.OwnerUserId,
395              DateEnqueued = jobDto.DateCreated
396            });
397          }
398          pm.SubmitChanges();
399          return job.JobId;
400        });
401      }
402    }
403
404    public void UpdateJob(DT.Job jobDto) {
405      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
406      AuthorizationManager.AuthorizeForJob(jobDto.Id, DT.Permission.Full);
407      var pm = PersistenceManager;
408      using (new PerformanceLogger("UpdateJob")) {
409        bool exists = true;
410        var jobDao = pm.JobDao;
411        pm.UseTransaction(() => {
412          var job = jobDao.GetById(jobDto.Id);
413          if (job == null) {
414            exists = false;
415            job = new DA.Job();
416          }
417          jobDto.CopyToEntity(job);
418          if (!exists) {
419            jobDao.Save(job);
420          }
421          pm.SubmitChanges();
422        });
423      }
424    }
425
426    public void DeleteJob(Guid jobId) {
427      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
428      AuthorizationManager.AuthorizeForJob(jobId, DT.Permission.Full);
429      var pm = PersistenceManager;
430      using (new PerformanceLogger("DeleteJob")) {
431        var jobDao = pm.JobDao;
432        pm.UseTransaction(() => {
433          // child task will be deleted by db-trigger
434          jobDao.Delete(jobId);
435          pm.SubmitChanges();
436        });
437      }
438    }
439    #endregion
440
441    #region JobPermission Methods
442    public void GrantPermission(Guid jobId, Guid grantedUserId, DT.Permission permission) {
443      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
444      AuthorizationManager.AuthorizeForJob(jobId, Permission.Full);
445      var pm = PersistenceManager;
446      using (new PerformanceLogger("GrantPermission")) {
447        var jobPermissionDao = pm.JobPermissionDao;
448        var currentUserId = UserManager.CurrentUserId;
449        pm.UseTransaction(() => {
450          jobPermissionDao.SetJobPermission(jobId, currentUserId, grantedUserId, permission.ToEntity());
451          pm.SubmitChanges();
452        });
453      }
454    }
455
456    public void RevokePermission(Guid jobId, Guid grantedUserId) {
457      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
458      AuthorizationManager.AuthorizeForJob(jobId, Permission.Full);
459      var pm = PersistenceManager;
460      using (new PerformanceLogger("RevokePermission")) {
461        var jobPermissionDao = pm.JobPermissionDao;
462        var currentUserId = UserManager.CurrentUserId;
463        pm.UseTransaction(() => {
464          jobPermissionDao.SetJobPermission(jobId, currentUserId, grantedUserId, DA.Permission.NotAllowed);
465          pm.SubmitChanges();
466        });
467      }
468    }
469
470    public IEnumerable<JobPermission> GetJobPermissions(Guid jobId) {
471      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
472      AuthorizationManager.AuthorizeForJob(jobId, Permission.Full);
473      var pm = PersistenceManager;
474      using (new PerformanceLogger("GetJobPermissions")) {
475        var jobPermissionDao = pm.JobPermissionDao;
476        return pm.UseTransaction(() => jobPermissionDao.GetByJobId(jobId)
477          .Select(x => x.ToDto())
478          .ToList()
479        );
480      }
481    }
482
483    // BackwardsCompatibility3.3
484    #region Backwards compatible code, remove with 3.4
485    public bool IsAllowedPrivileged() {
486      return true;
487    }
488    #endregion
489    #endregion
490
491    #region Login Methods
492    public void Hello(DT.Slave slaveInfo) {
493      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
494      if (UserManager.CurrentUser.UserName != "hiveslave") {
495        slaveInfo.OwnerUserId = UserManager.CurrentUserId;
496      }
497      var pm = PersistenceManager;
498      using (new PerformanceLogger("Hello")) {
499        var slaveDao = pm.SlaveDao;
500        pm.UseTransaction(() => {
501          var slave = slaveDao.GetById(slaveInfo.Id);
502          if (slave == null) {
503            slaveDao.Save(slaveInfo.ToEntity());
504          } else {
505            bool oldIsAllowedToCalculate = slave.IsAllowedToCalculate;
506            Guid? oldParentResourceId = slave.ParentResourceId;
507            slaveInfo.CopyToEntity(slave);
508            slave.IsAllowedToCalculate = oldIsAllowedToCalculate;
509            slave.ParentResourceId = oldParentResourceId;
510            slave.LastHeartbeat = DateTime.Now;
511            slave.SlaveState = DA.SlaveState.Idle;
512          }
513          pm.SubmitChanges();
514        });
515      }
516    }
517
518    public void GoodBye(Guid slaveId) {
519      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
520      var pm = PersistenceManager;
521      using (new PerformanceLogger("GoodBye")) {
522        var slaveDao = pm.SlaveDao;
523        pm.UseTransaction(() => {
524          var slave = slaveDao.GetById(slaveId);
525          if (slave != null) {
526            slave.SlaveState = DA.SlaveState.Offline;
527            pm.SubmitChanges();
528          }
529        });
530      }
531    }
532    #endregion
533
534    #region Heartbeat Methods
535    public List<MessageContainer> Heartbeat(DT.Heartbeat heartbeat) {
536      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
537      List<MessageContainer> result = new List<MessageContainer>();
538      try {
539        using (new PerformanceLogger("ProcessHeartbeat")) {
540          result = HeartbeatManager.ProcessHeartbeat(heartbeat);
541        }
542      } catch (Exception ex) {
543        DA.LogFactory.GetLogger(this.GetType().Namespace).Log(string.Format("Exception processing Heartbeat: {0}", ex));
544      }
545      if (HeuristicLab.Services.Hive.Properties.Settings.Default.TriggerEventManagerInHeartbeat) {
546        TriggerEventManager(false);
547      }
548      return result;
549    }
550    #endregion
551
552    #region Plugin Methods
553    public DT.Plugin GetPlugin(Guid pluginId) {
554      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
555      var pm = PersistenceManager;
556      using (new PerformanceLogger("GetPlugin")) {
557        var pluginDao = pm.PluginDao;
558        return pm.UseTransaction(() => pluginDao.GetById(pluginId).ToDto());
559      }
560    }
561
562    public Guid AddPlugin(DT.Plugin plugin, List<DT.PluginData> pluginData) {
563      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
564      var pm = PersistenceManager;
565      using (new PerformanceLogger("AddPlugin")) {
566        var pluginDao = pm.PluginDao;
567        plugin.UserId = UserManager.CurrentUserId;
568        plugin.DateCreated = DateTime.Now;
569        return pm.UseTransaction(() => {
570          var pluginEntity = pluginDao.GetByHash(plugin.Hash).SingleOrDefault();
571          if (pluginEntity != null) {
572            throw new FaultException<PluginAlreadyExistsFault>(new PluginAlreadyExistsFault(pluginEntity.PluginId));
573          }
574          pluginEntity = plugin.ToEntity();
575          foreach (var data in pluginData) {
576            data.PluginId = default(Guid); // real id will be assigned from linq2sql
577            pluginEntity.PluginData.Add(data.ToEntity());
578          }
579          pluginDao.Save(pluginEntity);
580          pm.SubmitChanges();
581          return pluginEntity.PluginId;
582        });
583      }
584    }
585
586    public IEnumerable<DT.Plugin> GetPlugins() {
587      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
588      var pm = PersistenceManager;
589      using (new PerformanceLogger("GetPlugins")) {
590        var pluginDao = pm.PluginDao;
591        return pm.UseTransaction(() => pluginDao.GetAll()
592          .Where(x => x.Hash != null)
593          .Select(x => x.ToDto())
594          .ToList()
595        );
596      }
597    }
598
599    public IEnumerable<DT.PluginData> GetPluginDatas(List<Guid> pluginIds) {
600      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
601      var pm = PersistenceManager;
602      using (new PerformanceLogger("GetPluginDatas")) {
603        var pluginDataDao = pm.PluginDataDao;
604        return pm.UseTransaction(() => pluginDataDao.GetAll()
605            .Where(x => pluginIds.Contains(x.PluginId))
606            .Select(x => x.ToDto())
607            .ToList()
608        );
609      }
610    }
611    #endregion
612
613    #region Project Methods
614    public Guid AddProject(DT.Project projectDto) {
615      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
616      var pm = PersistenceManager;
617      using (new PerformanceLogger("AddProject")) {
618        var projectDao = pm.ProjectDao;
619        return pm.UseTransaction(() => {
620          var project = projectDao.Save(projectDto.ToEntity());
621          pm.SubmitChanges();
622          return project.ProjectId;
623        });
624      }
625    }
626
627    public void UpdateProject(DT.Project projectDto) {
628      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
629      var pm = PersistenceManager;
630      using (new PerformanceLogger("UpdateProject")) {
631        var projectDao = pm.ProjectDao;
632        pm.UseTransaction(() => {
633          var project = projectDao.GetById(projectDto.Id);
634          if (project != null) {
635            projectDto.CopyToEntity(project);
636          } else {
637            projectDao.Save(projectDto.ToEntity());
638          }
639          pm.SubmitChanges();
640        });
641      }
642    }
643
644    public void DeleteProject(Guid projectId) {
645      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
646      AuthorizationManager.AuthorizeForProjectAdministration(projectId);
647      var pm = PersistenceManager;
648      using (new PerformanceLogger("DeleteProject")) {
649        var projectDao = pm.ProjectDao;
650        pm.UseTransaction(() => {
651          projectDao.Delete(projectId);
652          pm.SubmitChanges();
653        });
654      }
655    }
656
657    public DT.Project GetProject(Guid projectId) {
658      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
659      var pm = PersistenceManager;
660      using (new PerformanceLogger("GetProject")) {
661        var projectDao = pm.ProjectDao;
662        return pm.UseTransaction(() => projectDao.GetById(projectId).ToDto());
663      }
664    }
665
666    public IEnumerable<DT.Project> GetProjects() {
667      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
668      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
669      var pm = PersistenceManager;
670      using (new PerformanceLogger("GetProjects")) {
671        var projectDao = pm.ProjectDao;
672        var projectPermissionDao = pm.ProjectPermissionDao;
673        var currentUserId = UserManager.CurrentUserId;
674        return pm.UseTransaction(() => {
675          var projectPermissions = projectPermissionDao.GetAll();
676          return projectDao.GetAll().ToList()
677            .Where(x => isAdministrator
678              || x.OwnerUserId == currentUserId
679              || UserManager.VerifyUser(currentUserId, projectPermissions
680                  .Where(y => y.ProjectId == x.ProjectId)
681                  .Select(z => z.GrantedUserId)
682                  .ToList())
683              )
684            .Select(x => x.ToDto())
685            .ToList();
686        });
687      }
688    }
689    #endregion
690
691    #region ProjectPermission Methods
692    public void GrantProjectPermissions(Guid projectId, Guid[] grantedUserIds) {
693      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
694      AuthorizationManager.AuthorizeForProjectAdministration(projectId);
695      var pm = PersistenceManager;
696      using (new PerformanceLogger("GrantProjectPermissions")) {
697        var projectDao = pm.ProjectDao;
698        pm.UseTransaction(() => {
699          var project = projectDao.GetById(projectId);
700          var projectPermissions = project.ProjectPermissions.ToList();
701          foreach (var id in grantedUserIds) {
702            if (projectPermissions.All(x => x.GrantedUserId != id)) {
703              project.ProjectPermissions.Add(new DA.ProjectPermission {
704                GrantedUserId = id,
705                GrantedByUserId = UserManager.CurrentUserId
706              });
707            }
708          }
709          pm.SubmitChanges();
710        });
711      }
712    }
713
714    public void RevokeProjectPermissions(Guid projectId, Guid[] grantedUserIds) {
715      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
716      AuthorizationManager.AuthorizeForProjectAdministration(projectId);
717      var pm = PersistenceManager;
718      using (new PerformanceLogger("RevokeProjectPermissions")) {
719        var projectPermissionDao = pm.ProjectPermissionDao;
720        pm.UseTransaction(() => {
721          projectPermissionDao.DeleteByProjectAndGrantedUserId(projectId, grantedUserIds);
722          pm.SubmitChanges();
723        });
724      }
725    }
726
727    public IEnumerable<DT.ProjectPermission> GetProjectPermissions(Guid projectId) {
728      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
729      var pm = PersistenceManager;
730      using (new PerformanceLogger("GetProjectPermissions")) {
731        var projectPermissionDao = pm.ProjectPermissionDao;
732        return pm.UseTransaction(() => projectPermissionDao.GetByProjectId(projectId)
733          .Select(x => x.ToDto())
734          .ToList()
735        );
736      }
737    }
738    #endregion
739
740    #region AssignedProjectResource Methods
741    public void AssignProjectResources(Guid projectId, Guid[] resourceIds) {
742      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
743      AuthorizationManager.AuthorizeForProjectAdministration(projectId);
744      var pm = PersistenceManager;
745      using (new PerformanceLogger("AssignProjectResources")) {
746        var projectDao = pm.ProjectDao;
747        pm.UseTransaction(() => {
748          var project = projectDao.GetById(projectId);
749          var assignedProjectResources = project.AssignedProjectResources.ToList();
750
751          if (!RoleVerifier.IsInRole(HiveRoles.Administrator))
752            AuthorizeForResources(pm, project, resourceIds);
753
754          foreach (var id in resourceIds) {
755            if (assignedProjectResources.All(x => x.ResourceId != id)) {
756              project.AssignedProjectResources.Add(new DA.AssignedProjectResource {
757                ResourceId = id
758              });
759            }
760          }
761          pm.SubmitChanges();
762        });
763      }
764    }
765
766    public void UnassignProjectResources(Guid projectId, Guid[] resourceIds) {
767      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
768      AuthorizationManager.AuthorizeForProjectAdministration(projectId);
769      var pm = PersistenceManager;
770      using (new PerformanceLogger("UnassignProjectResources")) {
771        var assignedProjectResourceDao = pm.AssignedProjectResourceDao;
772        pm.UseTransaction(() => {
773          assignedProjectResourceDao.DeleteByProjectAndGrantedUserId(projectId, resourceIds);
774          pm.SubmitChanges();
775        });
776      }
777    }
778
779    public IEnumerable<AssignedProjectResource> GetAssignedResourcesForProject(Guid projectId) {
780      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
781      var pm = PersistenceManager;
782      using (new PerformanceLogger("GetAssignedResourcesForProject")) {
783        var assignedProjectResourceDao = pm.AssignedProjectResourceDao;
784        return pm.UseTransaction(() => assignedProjectResourceDao.GetByProjectId(projectId)
785          .Select(x => x.ToDto())
786          .ToList()
787        );
788      }
789    }
790    #endregion
791
792    #region Slave Methods
793    public Guid AddSlave(DT.Slave slaveDto) {
794      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
795      var pm = PersistenceManager;
796      using (new PerformanceLogger("AddSlave")) {
797        var slaveDao = pm.SlaveDao;
798        return pm.UseTransaction(() => {
799          var slave = slaveDao.Save(slaveDto.ToEntity());
800          pm.SubmitChanges();
801          return slave.ResourceId;
802        });
803      }
804    }
805
806    public Guid AddSlaveGroup(DT.SlaveGroup slaveGroupDto) {
807      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
808      var pm = PersistenceManager;
809      using (new PerformanceLogger("AddSlaveGroup")) {
810        var slaveGroupDao = pm.SlaveGroupDao;
811        return pm.UseTransaction(() => {
812          if (slaveGroupDto.Id == Guid.Empty) {
813            slaveGroupDto.Id = Guid.NewGuid();
814          }
815          var slaveGroup = slaveGroupDao.Save(slaveGroupDto.ToEntity());
816          pm.SubmitChanges();
817          return slaveGroup.ResourceId;
818        });
819      }
820    }
821
822    public DT.Slave GetSlave(Guid slaveId) {
823      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
824      var pm = PersistenceManager;
825      using (new PerformanceLogger("GetSlave")) {
826        var slaveDao = pm.SlaveDao;
827        return pm.UseTransaction(() => slaveDao.GetById(slaveId).ToDto());
828      }
829    }
830
831    public IEnumerable<DT.Slave> GetSlaves() {
832      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
833      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
834      var pm = PersistenceManager;
835      using (new PerformanceLogger("GetSlaves")) {
836        var slaveDao = pm.SlaveDao;
837        var resourcePermissionDao = pm.ProjectPermissionDao;
838        var currentUserId = UserManager.CurrentUserId;
839        return pm.UseTransaction(() => {
840          var resourcePermissions = resourcePermissionDao.GetAll();
841          return slaveDao.GetAll().ToList()
842            .Where(x => isAdministrator
843              || x.OwnerUserId == null
844              || x.OwnerUserId == currentUserId
845              || UserManager.VerifyUser(currentUserId, resourcePermissions
846                  //.Where(y => y.ResourceId == x.ResourceId)
847                  .Select(z => z.GrantedUserId)
848                  .ToList())
849              )
850            .Select(x => x.ToDto())
851            .ToList();
852        });
853      }
854    }
855
856    public IEnumerable<DT.SlaveGroup> GetSlaveGroups() {
857      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
858      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
859      var pm = PersistenceManager;
860      using (new PerformanceLogger("GetSlaveGroups")) {
861        var slaveGroupDao = pm.SlaveGroupDao;
862        var resourcePermissionDao = pm.ProjectPermissionDao;
863        var currentUserId = UserManager.CurrentUserId;
864        return pm.UseTransaction(() => {
865          var resourcePermissions = resourcePermissionDao.GetAll();
866          return slaveGroupDao.GetAll().ToList()
867            .Where(x => isAdministrator
868              || x.OwnerUserId == null
869              || x.OwnerUserId == currentUserId
870              || UserManager.VerifyUser(currentUserId, resourcePermissions
871                  //.Where(y => y.ResourceId == x.ResourceId)
872                  .Select(z => z.GrantedUserId)
873                  .ToList())
874              )
875            .Select(x => x.ToDto())
876            .ToList();
877        });
878      }
879    }
880
881    public void UpdateSlave(DT.Slave slaveDto) {
882      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
883      var pm = PersistenceManager;
884      using (new PerformanceLogger("UpdateSlave")) {
885        var slaveDao = pm.SlaveDao;
886        pm.UseTransaction(() => {
887          var slave = slaveDao.GetById(slaveDto.Id);
888          if (slave != null) {
889            slaveDto.CopyToEntity(slave);
890          } else {
891            slaveDao.Save(slaveDto.ToEntity());
892          }
893          pm.SubmitChanges();
894        });
895      }
896    }
897
898    public void UpdateSlaveGroup(DT.SlaveGroup slaveGroupDto) {
899      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
900      var pm = PersistenceManager;
901      using (new PerformanceLogger("UpdateSlaveGroup")) {
902        var slaveGroupDao = pm.SlaveGroupDao;
903        pm.UseTransaction(() => {
904          var slaveGroup = slaveGroupDao.GetById(slaveGroupDto.Id);
905          if (slaveGroup != null) {
906            slaveGroupDto.CopyToEntity(slaveGroup);
907          } else {
908            slaveGroupDao.Save(slaveGroupDto.ToEntity());
909          }
910          pm.SubmitChanges();
911        });
912      }
913    }
914
915    public void DeleteSlave(Guid slaveId) {
916      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
917      AuthorizationManager.AuthorizeForResourceAdministration(slaveId);
918      var pm = PersistenceManager;
919      using (new PerformanceLogger("DeleteSlave")) {
920        var slaveDao = pm.SlaveDao;
921        pm.UseTransaction(() => {
922          slaveDao.Delete(slaveId);
923          pm.SubmitChanges();
924        });
925      }
926    }
927
928    public void DeleteSlaveGroup(Guid slaveGroupId) {
929      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
930      AuthorizationManager.AuthorizeForResourceAdministration(slaveGroupId);
931      var pm = PersistenceManager;
932      using (new PerformanceLogger("DeleteSlaveGroup")) {
933        var slaveGroupDao = pm.SlaveGroupDao;
934        pm.UseTransaction(() => {
935          slaveGroupDao.Delete(slaveGroupId);
936          pm.SubmitChanges();
937        });
938      }
939    }
940
941    public void AddResourceToGroup(Guid slaveGroupId, Guid resourceId) {
942      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
943      var pm = PersistenceManager;
944      using (new PerformanceLogger("AddResourceToGroup")) {
945        var resourceDao = pm.ResourceDao;
946        pm.UseTransaction(() => {
947          var resource = resourceDao.GetById(resourceId);
948          resource.ParentResourceId = slaveGroupId;
949          pm.SubmitChanges();
950        });
951      }
952    }
953
954    public void RemoveResourceFromGroup(Guid slaveGroupId, Guid resourceId) {
955      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
956      var pm = PersistenceManager;
957      using (new PerformanceLogger("RemoveResourceFromGroup")) {
958        var resourceDao = pm.ResourceDao;
959        pm.UseTransaction(() => {
960          var resource = resourceDao.GetById(resourceId);
961          resource.ParentResourceId = null;
962          pm.SubmitChanges();
963        });
964      }
965    }
966
967    public Guid GetResourceId(string resourceName) {
968      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
969      var pm = PersistenceManager;
970      using (new PerformanceLogger("GetResourceId")) {
971        var resourceDao = pm.ResourceDao;
972        return pm.UseTransaction(() => {
973          var resource = resourceDao.GetByName(resourceName);
974          return resource != null ? resource.ResourceId : Guid.Empty;
975        });
976      }
977    }
978
979    public void TriggerEventManager(bool force) {
980      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
981      // use a serializable transaction here to ensure not two threads execute this simultaniously (mutex-lock would not work since IIS may use multiple AppDomains)
982      bool cleanup;
983      var pm = PersistenceManager;
984      using (new PerformanceLogger("TriggerEventManager")) {
985        cleanup = false;
986        var lifecycleDao = pm.LifecycleDao;
987        pm.UseTransaction(() => {
988          var lastLifecycle = lifecycleDao.GetLastLifecycle();
989          DateTime lastCleanup = lastLifecycle != null ? lastLifecycle.LastCleanup : DateTime.MinValue;
990          if (force || DateTime.Now - lastCleanup > HeuristicLab.Services.Hive.Properties.Settings.Default.CleanupInterval) {
991            lifecycleDao.UpdateLifecycle();
992            cleanup = true;
993            pm.SubmitChanges();
994          }
995        }, true);
996      }
997      if (cleanup) {
998        EventManager.Cleanup();
999      }
1000    }
1001
1002    public int GetNewHeartbeatInterval(Guid slaveId) {
1003      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
1004      var pm = PersistenceManager;
1005      using (new PerformanceLogger("GetNewHeartbeatInterval")) {
1006        var slaveDao = pm.SlaveDao;
1007        return pm.UseTransaction(() => {
1008          var slave = slaveDao.GetById(slaveId);
1009          if (slave != null) {
1010            return slave.HbInterval;
1011          }
1012          return -1;
1013        });
1014      }
1015    }
1016    #endregion
1017
1018    #region ResourcePermission Methods
1019    // only for authorized Administrator/ResourceOwner
1020    public void GrantResourcePermissions(Guid resourceId, Guid[] grantedUserIds) {
1021      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1022      AuthorizationManager.AuthorizeForResourceAdministration(resourceId);
1023      var pm = PersistenceManager;
1024      using(new PerformanceLogger("GrantResourcePermissions")) {
1025        pm.UseTransaction(() => {
1026          var resourceDao = pm.ResourceDao;
1027          var resource = resourceDao.GetById(resourceId);
1028          var resourcePermissions = resource.ResourcePermissions.ToList();
1029          foreach(var id in grantedUserIds) {
1030            if(resourcePermissions.All(x => x.GrantedUserId != id)) {
1031              resource.ResourcePermissions.Add(new DA.ResourcePermission {
1032                GrantedUserId = id,
1033                GrantedByUserId = UserManager.CurrentUserId
1034              });
1035            }
1036          }
1037          pm.SubmitChanges();
1038        });
1039      }
1040    }
1041
1042
1043    // only for authorized Administrator/ResourceOwner
1044    public void RevokeResourcePermissions(Guid resourceId, Guid[] grantedUserIds) {
1045      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1046      AuthorizationManager.AuthorizeForResourceAdministration(resourceId);
1047      var pm = PersistenceManager;
1048      using(new PerformanceLogger("RevokeResourcePermission")) {
1049        pm.UseTransaction(() => {
1050          var resourcePermissionDao = pm.ResourcePermissionDao;
1051          resourcePermissionDao.DeleteByResourceIdAndGrantedUserId(resourceId, grantedUserIds);
1052          pm.SubmitChanges();
1053        });
1054      }
1055    }
1056
1057
1058    // OBSOLETE (change to public if...)
1059    // only for authorized Administrator/ResourceOwner/(Sub)ProjectOwner to which the Resource (i.e. resourceId) is assigned
1060    private void GrantResourcePermissions(Guid resourceId, Guid projectId, Guid[] grantedUserIds) {
1061      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1062      //AuthorizationManager.AuthorizeForResourceAdministration(resourceId);
1063      var pm = PersistenceManager;
1064      using (new PerformanceLogger("GrantResourcePermissions")) {
1065        pm.UseTransaction(() => {
1066          // TODO-JAN
1067          pm.SubmitChanges();
1068        });
1069      }
1070    }
1071
1072    // OBSOLETE (change to public if...)
1073    // only for authorized Administrator/ResourceOwner/(Sub)ProjectOwner to which the Resource (i.e. resourceId) is assigned
1074    private void RevokeResourcePermissions(Guid resourceId, Guid projectId, Guid[] grantedUserIds) {
1075      // TODO-JAN
1076    }
1077
1078    #endregion
1079
1080    #region Downtime Methods
1081    public Guid AddDowntime(DT.Downtime downtimeDto) {
1082      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1083      AuthorizationManager.AuthorizeForResourceAdministration(downtimeDto.ResourceId);
1084      var pm = PersistenceManager;
1085      using (new PerformanceLogger("AddDowntime")) {
1086        var downtimeDao = pm.DowntimeDao;
1087        return pm.UseTransaction(() => {
1088          var downtime = downtimeDao.Save(downtimeDto.ToEntity());
1089          pm.SubmitChanges();
1090          return downtime.ResourceId;
1091        });
1092      }
1093    }
1094
1095    public void DeleteDowntime(Guid downtimeId) {
1096      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1097      var pm = PersistenceManager;
1098      using (new PerformanceLogger("DeleteDowntime")) {
1099        var downtimeDao = pm.DowntimeDao;
1100        pm.UseTransaction(() => {
1101          downtimeDao.Delete(downtimeId);
1102          pm.SubmitChanges();
1103        });
1104      }
1105    }
1106
1107    public void UpdateDowntime(DT.Downtime downtimeDto) {
1108      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1109      AuthorizationManager.AuthorizeForResourceAdministration(downtimeDto.ResourceId);
1110      var pm = PersistenceManager;
1111      using (new PerformanceLogger("UpdateDowntime")) {
1112        var downtimeDao = pm.DowntimeDao;
1113        pm.UseTransaction(() => {
1114          var downtime = downtimeDao.GetById(downtimeDto.Id);
1115          if (downtime != null) {
1116            downtimeDto.CopyToEntity(downtime);
1117          } else {
1118            downtimeDao.Save(downtimeDto.ToEntity());
1119          }
1120          pm.SubmitChanges();
1121        });
1122      }
1123    }
1124
1125    public IEnumerable<DT.Downtime> GetDowntimesForResource(Guid resourceId) {
1126      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1127      var pm = PersistenceManager;
1128      using (new PerformanceLogger("GetDowntimesForResource")) {
1129        var downtimeDao = pm.DowntimeDao;
1130        return pm.UseTransaction(() => downtimeDao.GetByResourceId(resourceId)
1131          .Select(x => x.ToDto())
1132          .ToList()
1133        );
1134      }
1135    }
1136    #endregion
1137
1138    #region User Methods
1139    public string GetUsernameByUserId(Guid userId) {
1140      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1141      var user = UserManager.GetUserById(userId);
1142      return user != null ? user.UserName : null;
1143    }
1144
1145    public Guid GetUserIdByUsername(string username) {
1146      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
1147      var user = ServiceLocator.Instance.UserManager.GetUserByName(username);
1148      return user != null ? (Guid?)user.ProviderUserKey ?? Guid.Empty : Guid.Empty;
1149    }
1150    #endregion
1151
1152    #region UserPriorities Methods
1153    public IEnumerable<DT.UserPriority> GetUserPriorities() {
1154      var pm = PersistenceManager;
1155      using (new PerformanceLogger("GetUserPriorities")) {
1156        var userPriorityDao = pm.UserPriorityDao;
1157        return pm.UseTransaction(() => userPriorityDao.GetAll()
1158          .Select(x => x.ToDto())
1159          .ToList()
1160        );
1161      }
1162    }
1163    #endregion
1164
1165    #region Private Helper Methods
1166    private void UpdateTaskState(IPersistenceManager pm, DA.Task task, DT.TaskState taskState, Guid? slaveId, Guid? userId, string exception) {
1167      var stateLogDao = pm.StateLogDao;
1168      var taskStateEntity = taskState.ToEntity();
1169
1170      if (task.State == DA.TaskState.Transferring && taskStateEntity == DA.TaskState.Paused && task.Command == null) {
1171        // slave paused and uploaded the task (no user-command) -> set waiting.
1172        taskStateEntity = DA.TaskState.Waiting;
1173      }
1174
1175      stateLogDao.Save(new DA.StateLog {
1176        State = taskStateEntity,
1177        DateTime = DateTime.Now,
1178        TaskId = task.TaskId,
1179        UserId = userId,
1180        SlaveId = slaveId,
1181        Exception = exception
1182      });
1183
1184      task.State = taskStateEntity;
1185
1186      if (task.Command == DA.Command.Pause && task.State == DA.TaskState.Paused
1187          || task.Command == DA.Command.Abort && task.State == DA.TaskState.Aborted
1188          || task.Command == DA.Command.Stop && task.State == DA.TaskState.Aborted) {
1189        task.Command = null;
1190      }
1191    }
1192
1193    // OBSOLETE
1194    // reason: only used for double checking! AuthorizationManager.AuthorizeForProjectAdministration(..) does the same!
1195    //private DA.Project AuthorizeForProject(IPersistenceManager pm, Guid projectId) {
1196    //  var projectDao = pm.ProjectDao;
1197    //  var project = projectDao.GetById(projectId);
1198    //  if (project == null) throw new SecurityException(NOT_AUTHORIZED_PROJECT);
1199    //  if (project.OwnerUserId != UserManager.CurrentUserId
1200    //      && !RoleVerifier.IsInRole(HiveRoles.Administrator)) {
1201    //    throw new SecurityException(NOT_AUTHORIZED_PROJECT);
1202    //  }
1203    //  return project;
1204    //}
1205
1206   private void CheckTaskPermissions(IPersistenceManager pm, DT.Task task, IEnumerable<Guid> resourceIds) {
1207      var jobDao = pm.JobDao;
1208      var projectDao = pm.ProjectDao;
1209      var resourceDao = pm.ResourceDao;
1210      var resourcePermissionDao = pm.ResourcePermissionDao;
1211      var projectPermissionDao = pm.ProjectPermissionDao;
1212      var currentUserId = UserManager.CurrentUserId;
1213
1214      //// PART 1: user-resource permission check (V1)
1215      //// get granted (parent) resources
1216      //var allGrantedResourceIds = pm.UseTransaction(() => {
1217      //  return resourcePermissionDao.GetAll().ToList()
1218      //    .Where(x => x.GrantedUserId == currentUserId
1219      //      || UserManager.VerifyUser(currentUserId, new List<Guid> { x.GrantedUserId }))
1220      //    .Select(y => y.ResourceId)
1221      //    .ToList();
1222      //});
1223
1224      //// get children of granted parent resources
1225      //var userGrantedChildResourceIds = pm.UseTransaction(() => {
1226      //  return allGrantedResourceIds
1227      //  .SelectMany(x => resourceDao.GetResourcesByParentId(x))
1228      //  .Select(y => y.ResourceId);
1229      //});
1230
1231      //// join list of parent and child resources
1232      //allGrantedResourceIds.AddRange(userGrantedChildResourceIds);
1233
1234      // PART 1: user-resource permission check (V2)
1235      // collect the current currentUserId and all Ids of affiliated groups
1236      var userAndGroupIds = new List<Guid> { currentUserId };
1237      userAndGroupIds.AddRange(UserManager.GetUserGroupIdsOfUser(currentUserId));
1238
1239      // get all granted resourceIds
1240      var allGrantedResourceIds = resourcePermissionDao.GetByUserAndGroupIds(userAndGroupIds).ToList();
1241
1242      // get all owned resourceIds (including child resourceIds)
1243      var ownedResourceIds = resourceDao.GetAll()
1244        .Where(x => x.OwnerUserId == currentUserId)
1245        .Select(x => x.ResourceId).ToList();
1246      var ownedChildResourceIds = ownedResourceIds.SelectMany(x => resourceDao.GetResourceIdsByParentId(x));
1247      ownedResourceIds.AddRange(ownedChildResourceIds);
1248
1249      // join list of owned into the list with granted resourceIds
1250      allGrantedResourceIds.AddRange(ownedResourceIds);
1251
1252      // check the argument resourceIds against the list of granted (and owned) ones
1253      if (resourceIds.Except(allGrantedResourceIds).Any()) {
1254        throw new SecurityException(NOT_AUTHORIZED_RESOURCE);
1255      }
1256
1257      // PART 2: user-project permission check
1258      var job = jobDao.GetById(task.JobId);
1259      var project = projectDao.GetById(job.ProjectId);
1260      AuthorizeForProjectTask(pm, project);
1261
1262      // PART 3: project-resource permission check
1263      var assignedResourceIds = project.AssignedProjectResources.Select(x => x.ResourceId).ToList();
1264      var assignedChildResourceIds = assignedResourceIds.SelectMany(x => resourceDao.GetResourceIdsByParentId(x));
1265      assignedResourceIds.AddRange(assignedChildResourceIds);
1266      if (resourceIds.Except(assignedResourceIds).Any()) {
1267        throw new SecurityException(NOT_AUTHORIZED_PROJECT);
1268      }
1269    }
1270
1271    // Check if current user is authorized to add a task on a explicit project
1272    // case 1: user is administrator
1273    // case 2: user is owner of project or parent project
1274    // case 3: user has explicit permission on project or parent project
1275    private void AuthorizeForProjectTask(IPersistenceManager pm, DA.Project project) {
1276      if (RoleVerifier.IsInRole(HiveRoles.Administrator)) return; // case 1
1277
1278      // case 2
1279      var projectDao = pm.ProjectDao;
1280      var projectBranch = new List<DA.Project>() { project };
1281      projectBranch.AddRange(projectDao.GetProjectsByChildId(project.ProjectId));
1282      if (projectBranch
1283        .Select(x => x.OwnerUserId)
1284        .Contains(UserManager.CurrentUserId)) {
1285        return; 
1286      }
1287
1288      // case 3
1289      if(project.ProjectPermissions
1290        .Select(x => x.GrantedUserId)
1291        .Contains(UserManager.CurrentUserId)) {
1292        return;
1293      }
1294      if(projectBranch
1295        .SelectMany(x => x.ProjectPermissions)
1296        .Select(x => x.GrantedUserId)
1297        .Contains(UserManager.CurrentUserId)) {
1298        return;
1299      }
1300
1301      throw new SecurityException(NOT_AUTHORIZED_PROJECT);
1302    }
1303
1304    // Check if the current user is authorized to administer resourceIds
1305    private void AuthorizeForResources(IPersistenceManager pm, DA.Project project, Guid[] resourceIds) {
1306      var projectDao = pm.ProjectDao;
1307      var resourceDao = pm.ResourceDao;
1308
1309      var projectBranch = new List<DA.Project> { project };
1310      projectBranch.AddRange(projectDao.GetProjectsByChildId(project.ProjectId));
1311      var ownedProjects = projectBranch.Where(x => x.OwnerUserId == UserManager.CurrentUserId).ToList();
1312
1313      // get all assigned resourceIds (including children) of owned projects in this branch
1314      var assignedResourceIds = ownedProjects.SelectMany(x => x.AssignedProjectResources).Select(x => x.ResourceId).ToList();
1315      var assignedChildResourceIds = assignedResourceIds.SelectMany(x => resourceDao.GetResourceIdsByChildId(x));
1316      assignedResourceIds.AddRange(assignedChildResourceIds);
1317
1318      // look up if all resourceIds are among the assigned ones
1319      if(resourceIds.Except(assignedResourceIds).Any()) {
1320        throw new SecurityException(NOT_AUTHORIZED_RESOURCE);
1321      }
1322    }
1323
1324    // Check if the current user is authorized (i.e. is owner of the (sub)project) to set permissions
1325    // for a certain resource (resourceId) in the context of a certain project (projectId)
1326    private DA.Resource AuthorizeForResource(IPersistenceManager pm, Guid resourceId, Guid projectId) {
1327      var projectDao = pm.ProjectDao;
1328      var project = projectDao.GetById(projectId);
1329      if (project == null) throw new SecurityException(NOT_AUTHORIZED_PROJECT); // if project does not exist
1330
1331      var resourceDao = pm.ResourceDao;
1332      var resource = resourceDao.GetById(resourceId);
1333      if (resource == null) throw new SecurityException(NOT_AUTHORIZED_RESOURCE); // if resource does not exist
1334
1335
1336      // check if user is administrator, owner of the project or any parent project
1337      var projectTree = new List<DA.Project> { project };
1338      projectTree.AddRange(projectDao.GetProjectsByChildId(projectId));
1339      if(!projectTree.Select(x => x.OwnerUserId).Contains(UserManager.CurrentUserId)
1340        && !RoleVerifier.IsInRole(HiveRoles.Administrator)) {
1341        throw new SecurityException(NOT_AUTHORIZED_PROJECT);
1342      }
1343
1344      // look up if resourceId is amongst the assigned ones
1345      var assignedResources = project.AssignedProjectResources.ToList();
1346      if (assignedResources.Select(x => x.ResourceId).Contains(resourceId)) {
1347        return resource;
1348      }
1349
1350      // look up if one of the parent resourceIds is amongst the assigned ones
1351      // note: this should be faster than checking all children of the assigned
1352      // resource(-groups) for the certain resourceId
1353      var parentResourceIds = resourceDao.GetResourceIdsByChildId(resourceId);
1354      if(assignedResources.Select(x => x.ResourceId)
1355        .Intersect(parentResourceIds).Count() > 0) {
1356        return resource;
1357      }
1358
1359      throw new SecurityException(NOT_AUTHORIZED_PROJECT);
1360    }
1361    #endregion
1362  }
1363}
Note: See TracBrowser for help on using the repository browser.