Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HiveResourcePermissionManagement (trunk integration)/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.cs @ 7951

Last change on this file since 7951 was 7951, checked in by jkarder, 12 years ago

#1859:

  • added permission management support
  • extended administartion user interface
  • minor code improvements
File size: 21.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 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.Drawing;
25using System.Linq;
26using System.ServiceModel.Security;
27using System.Threading;
28using System.Threading.Tasks;
29using System.Windows.Forms;
30using HeuristicLab.Clients.Access;
31using HeuristicLab.Clients.Hive.Views;
32using HeuristicLab.Core;
33using HeuristicLab.Core.Views;
34using HeuristicLab.MainForm;
35using TS = System.Threading.Tasks;
36
37namespace HeuristicLab.Clients.Hive.Administrator.Views {
38  [View("Resources View")]
39  [Content(typeof(IItemList<Resource>), IsDefaultView = true)]
40  public partial class ResourcesView : ItemView, IDisposable {
41    public new IItemList<Resource> Content {
42      get { return (IItemList<Resource>)base.Content; }
43      set { base.Content = value; }
44    }
45
46    public const string UngroupedGroupName = "UNGROUPED";
47    private const int slaveImageIndex = 0;
48    private const int slaveGroupImageIndex = 1;
49    private readonly Color ownedResourceColor = Color.LightGreen;
50    private TS.Task progressTask;
51    private bool stopProgressTask;
52    private bool currentlyAuthorized;
53
54
55    public ResourcesView() {
56      InitializeComponent();
57      treeSlaveGroup.ImageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.MonitorLarge);
58      treeSlaveGroup.ImageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.NetworkCenterLarge);
59
60      HiveAdminClient.Instance.Refreshing += new EventHandler(Instance_Refreshing);
61      HiveAdminClient.Instance.Refreshed += new EventHandler(Instance_Refreshed);
62
63      Access.AccessClient.Instance.Refreshing += new EventHandler(Content_Refreshing);
64      Access.AccessClient.Instance.Refreshed += new EventHandler(Content_Refreshed);
65    }
66
67    public new void Dispose() {
68      HiveAdminClient.Instance.Refreshing -= new EventHandler(Instance_Refreshing);
69      HiveAdminClient.Instance.Refreshed -= new EventHandler(Instance_Refreshed);
70
71      Access.AccessClient.Instance.Refreshing -= new EventHandler(Content_Refreshing);
72      Access.AccessClient.Instance.Refreshed -= new EventHandler(Content_Refreshed);
73    }
74
75    private void UpdateProgress() {
76      while (!stopProgressTask) {
77        int diff = (progressBar.Maximum - progressBar.Minimum) / 10;
78
79        if (progressBar.InvokeRequired) {
80          progressBar.Invoke(new Action(delegate() { progressBar.Value = (progressBar.Value + diff) % progressBar.Maximum; }));
81        } else {
82          progressBar.Value = (progressBar.Value + diff) % progressBar.Maximum;
83        }
84
85        //ok, this is not very clever...
86        Thread.Sleep(500);
87      }
88      if (progressBar.InvokeRequired) {
89        progressBar.Invoke(new Action(delegate() { progressBar.Value = progressBar.Minimum; }));
90      } else {
91        progressBar.Value = progressBar.Minimum;
92      }
93    }
94
95    void Instance_Refreshing(object sender, EventArgs e) {
96      stopProgressTask = false;
97      progressTask = new TS.Task(UpdateProgress);
98      progressTask.Start();
99      SetEnabledStateOfControls(false);
100    }
101
102    void Instance_Refreshed(object sender, EventArgs e) {
103      stopProgressTask = true;
104      SetEnabledStateOfControls(true);
105    }
106
107    void Content_Refreshing(object sender, EventArgs e) {
108      stopProgressTask = false;
109      progressTask = new TS.Task(UpdateProgress);
110      progressTask.Start();
111      SetEnabledStateOfControls(false);
112    }
113
114    void Content_Refreshed(object sender, EventArgs e) {
115      stopProgressTask = true;
116      SetEnabledStateOfControls(true);
117    }
118
119    #region Register Content Events
120    protected override void DeregisterContentEvents() {
121      Content.ItemsAdded -= new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<Resource>>(Content_ItemsAdded);
122      Content.ItemsRemoved -= new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<Resource>>(Content_ItemsRemoved);
123      base.DeregisterContentEvents();
124    }
125    protected override void RegisterContentEvents() {
126      base.RegisterContentEvents();
127      Content.ItemsAdded += new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<Resource>>(Content_ItemsAdded);
128      Content.ItemsRemoved += new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<Resource>>(Content_ItemsRemoved);
129    }
130    #endregion
131
132    protected override void OnContentChanged() {
133      base.OnContentChanged();
134      if (Content == null) {
135        slaveView.Content = null;
136        scheduleView.Content = null;
137        permissionView.Content = null;
138        permissionView.FetchSelectedUsers = null;
139        treeSlaveGroup.Nodes.Clear();
140      } else {
141        permissionView.Content = Access.AccessClient.Instance;
142        treeSlaveGroup.Nodes.Clear();
143
144        //rebuild
145        TreeNode ungrp = new TreeNode(UngroupedGroupName);
146        ungrp.ImageIndex = slaveGroupImageIndex;
147        ungrp.SelectedImageIndex = ungrp.ImageIndex;
148        var newGroup = new SlaveGroup();
149        newGroup.Name = UngroupedGroupName;
150        newGroup.Id = Guid.NewGuid();
151        newGroup.Description = "Contains slaves which are in no group";
152        ungrp.Tag = newGroup;
153
154        foreach (Resource g in Content) {
155          if (g.GetType() == typeof(SlaveGroup)) {
156            //root node
157            if (g.ParentResourceId == null) {
158              TreeNode tn = new TreeNode();
159              tn.ImageIndex = slaveGroupImageIndex;
160              tn.SelectedImageIndex = tn.ImageIndex;
161
162              tn.Tag = g;
163              tn.Text = g.Name;
164              if (g.OwnerUserId == Access.UserInformation.Instance.User.Id) tn.BackColor = ownedResourceColor;
165
166              BuildSlaveGroupTree(g, tn);
167              treeSlaveGroup.Nodes.Add(tn);
168            }
169          } else if (g.GetType() == typeof(Slave)) {
170            if (g.ParentResourceId == null) {
171              var stn = new TreeNode(g.Name);
172              stn.ImageIndex = slaveImageIndex;
173              stn.SelectedImageIndex = stn.ImageIndex;
174              stn.Tag = g;
175              if (g.OwnerUserId == Access.UserInformation.Instance.User.Id) stn.BackColor = ownedResourceColor;
176              ungrp.Nodes.Add(stn);
177            }
178          }
179        }
180        treeSlaveGroup.Nodes.Add(ungrp);
181      }
182    }
183
184    private void BuildSlaveGroupTree(Resource g, TreeNode tn) {
185      foreach (Resource r in Content.Where(s => s.ParentResourceId != null && s.ParentResourceId == g.Id)) {
186        TreeNode stn = new TreeNode(r.Name);
187        if (r is Slave) {
188          stn.ImageIndex = slaveImageIndex;
189        } else if (r is SlaveGroup) {
190          stn.ImageIndex = slaveGroupImageIndex;
191        }
192        stn.SelectedImageIndex = stn.ImageIndex;
193        stn.Tag = r;
194        if (r.OwnerUserId == Access.UserInformation.Instance.User.Id) stn.BackColor = ownedResourceColor;
195        tn.Nodes.Add(stn);
196
197        BuildSlaveGroupTree(r, stn);
198      }
199    }
200
201    protected override void SetEnabledStateOfControls() {
202      base.SetEnabledStateOfControls();
203      if (Content == null) {
204        btnAddGroup.Enabled = false;
205        btnRemoveGroup.Enabled = false;
206        btnSave.Enabled = false;
207        btnPermissionsSave.Enabled = false;
208        permissionView.Enabled = false;
209      } else {
210        btnAddGroup.Enabled = true;
211        btnRemoveGroup.Enabled = true;
212        btnSave.Enabled = true;
213      }
214    }
215
216    public virtual void SetEnabledStateOfControls(bool state) {
217      if (InvokeRequired) {
218        Invoke(new Action(() => SetEnabledStateOfControls(state)));
219      } else {
220        if (Content == null) state = false;
221        btnAddGroup.Enabled = state;
222        btnRemoveGroup.Enabled = state;
223        btnSave.Enabled = state;
224        scheduleView.SetEnabledStateOfControls(state && IsAuthorized(slaveView.Content));
225        btnPermissionsSave.Enabled = state && permissionView.FetchSelectedUsers != null && Content != null;
226        permissionView.Enabled = state && permissionView.FetchSelectedUsers != null && Content != null;
227      }
228    }
229
230    private bool IsAuthorized(Resource resource) {
231      return resource != null
232          && resource.Name != UngroupedGroupName
233          && resource.Id != Guid.Empty
234          && HiveServiceLocator.Instance.CallHiveService<bool>(service => { return service.AuthorizesForResourceAdministration(resource.Id); });
235    }
236
237    private void treeSlaveGroup_AfterSelect(object sender, TreeViewEventArgs e) {
238      if (e.Action != TreeViewAction.Unknown) {
239        Resource selectedResource = ((Resource)e.Node.Tag);
240        currentlyAuthorized = IsAuthorized(selectedResource);
241        if (currentlyAuthorized) {
242          permissionView.FetchSelectedUsers = new Func<List<Guid>>(() => {
243            return HiveServiceLocator.Instance.CallHiveService<List<ResourcePermission>>(service => {
244              return service.GetResourcePermissions(selectedResource.Id);
245            }).Select(x => x.GrantedUserId).ToList();
246          });
247          if (!tabSlaveGroup.TabPages.Contains(tabPermissions)) tabSlaveGroup.TabPages.Add(tabPermissions);
248        } else {
249          permissionView.FetchSelectedUsers = null;
250          btnPermissionsSave.Enabled = false;
251          if (selectedResource.Id == Guid.Empty) {
252            if (!tabSlaveGroup.TabPages.Contains(tabPermissions)) tabSlaveGroup.TabPages.Add(tabPermissions);
253          } else tabSlaveGroup.TabPages.Remove(tabPermissions);
254        }
255
256        if (slaveView.Content != null && slaveView.Content is SlaveGroup) {
257          slaveView.Content.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(SlaveViewContent_PropertyChanged);
258        }
259
260        slaveView.Content = selectedResource;
261        HiveAdminClient.Instance.DowntimeForResourceId = selectedResource.Id;
262
263        if (selectedResource is SlaveGroup) {
264          slaveView.Content.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(SlaveViewContent_PropertyChanged);
265        }
266
267        if (tabSlaveGroup.SelectedIndex == 1) {
268          UpdateScheduleAsync();
269        } else if (tabSlaveGroup.SelectedIndex == 2) {
270          UpdatePermissionsAsync();
271        }
272      }
273    }
274
275    void SlaveViewContent_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) {
276      OnContentChanged();
277      if (e.PropertyName == "HbInterval") {
278        UpdateChildHbIntervall(slaveView.Content);
279      }
280    }
281
282    private void UpdateChildHbIntervall(Resource resource) {
283      foreach (Resource r in Content.Where(x => x.ParentResourceId == resource.Id)) {
284        r.HbInterval = resource.HbInterval;
285        if (r is SlaveGroup) {
286          UpdateChildHbIntervall(r);
287        }
288      }
289    }
290
291    private void btnAddGroup_Click(object sender, EventArgs e) {
292      SlaveGroup newGroup = new SlaveGroup();
293      newGroup.Name = "New Group";
294      newGroup.OwnerUserId = UserInformation.Instance.User.Id;
295      Content.Add(newGroup);
296    }
297
298    void Content_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs<Collections.IndexedItem<Resource>> e) {
299      OnContentChanged();
300    }
301
302    void Content_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs<Collections.IndexedItem<Resource>> e) {
303      OnContentChanged();
304    }
305
306    private void btnRemoveGroup_Click(object sender, EventArgs e) {
307      if (treeSlaveGroup.SelectedNode != null && treeSlaveGroup.SelectedNode.Tag != null) {
308        Resource res = (Resource)treeSlaveGroup.SelectedNode.Tag;
309
310        DialogResult diagRes = MessageBox.Show("Do you really want to delete " + res.Name + "?", "HeuristicLab Hive Administrator", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
311        if (diagRes == DialogResult.Yes) {
312          if (res is Slave) {
313            Content.Remove(res);
314            HiveAdminClient.Delete(res);
315          } else if (res is SlaveGroup) {
316            //only delete empty groups
317            if (Content.Where(s => s.ParentResourceId == res.Id).Count() < 1) {
318              Content.Remove(res);
319              HiveAdminClient.Delete(res);
320            } else {
321              MessageBox.Show("Only empty groups can be deleted.", "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
322            }
323          }
324        }
325      }
326    }
327
328    private void btnSave_Click(object sender, EventArgs e) {
329      foreach (Resource res in Content) {
330        if (res is SlaveGroup && res.Id == Guid.Empty) {
331          SlaveGroup slaveGroup = (SlaveGroup)res;
332          slaveGroup.Store();
333        } else if (res.Id != Guid.Empty && res.Modified) {
334          res.Store();
335        }
336      }
337    }
338
339    private void treeSlaveGroup_DragDrop(object sender, DragEventArgs e) {
340      if (e.Data.GetDataPresent("System.Windows.Forms.TreeNode", false)) {
341        Point pt = ((TreeView)sender).PointToClient(new Point(e.X, e.Y));
342        TreeNode destNode = ((TreeView)sender).GetNodeAt(pt);
343        TreeNode newNode = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode");
344
345        if (destNode.TreeView == newNode.TreeView) {
346          if (destNode.Text == UngroupedGroupName || (destNode.Parent != null && destNode.Parent.Text == UngroupedGroupName)) {
347            MessageBox.Show(string.Format("You can't drag items to the group \"{0}\".{1}This group only contains slaves which haven't yet been assigned to a real group.",
348              UngroupedGroupName, Environment.NewLine), "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Information);
349            return;
350          }
351
352          SlaveGroup sgrp = null;
353          TreeNode parentNode = null;
354          if (destNode.Tag != null && destNode.Tag is SlaveGroup) {
355            sgrp = (SlaveGroup)destNode.Tag;
356            parentNode = destNode;
357          } else if (destNode.Parent != null && destNode.Parent.Tag is SlaveGroup) {
358            sgrp = (SlaveGroup)destNode.Parent.Tag;
359            parentNode = destNode.Parent;
360          }
361
362          if (newNode.Tag is SlaveGroup && CheckParentsEqualsMovedNode(parentNode, newNode)) {
363            return;
364          }
365
366          SlaveGroup parent = (SlaveGroup)parentNode.Tag;
367
368          if (parent.OwnerUserId != null && !IsAuthorized(parent)) {
369            MessageBox.Show(string.Format("You don't have the permissions to drag items to the group \"{0}\".", ((Resource)parentNode.Tag).Name),
370              "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
371            return;
372          }
373
374          if (sgrp != null && newNode.Tag != null) {
375            //save parent group to get an id
376            if (sgrp.Id == Guid.Empty) {
377              sgrp.Store();
378            }
379
380            if (newNode.Tag is Slave) {
381              Slave slave = (Slave)newNode.Tag;
382              if (slave.ParentResourceId == null || (slave.ParentResourceId != null && slave.ParentResourceId != sgrp.Id)) {
383                slave.ParentResourceId = sgrp.Id;
384                newNode.Remove();
385                parentNode.Nodes.Clear();
386                BuildSlaveGroupTree(sgrp, parentNode);
387              }
388            } else if (newNode.Tag is SlaveGroup) {
389              SlaveGroup slaveGroup = (SlaveGroup)newNode.Tag;
390              if (slaveGroup.ParentResourceId == null || (slaveGroup.ParentResourceId != null && slaveGroup.ParentResourceId != sgrp.Id)) {
391                slaveGroup.ParentResourceId = sgrp.Id;
392                newNode.Remove();
393                parentNode.Nodes.Clear();
394                BuildSlaveGroupTree(sgrp, parentNode);
395              }
396            }
397          }
398        }
399      }
400    }
401
402    private bool CheckParentsEqualsMovedNode(TreeNode dest, TreeNode movedNode) {
403      TreeNode tmp = dest;
404
405      while (tmp != null) {
406        if (tmp == movedNode) {
407          return true;
408        }
409        tmp = tmp.Parent;
410      }
411      return false;
412    }
413
414    private void treeSlaveGroup_ItemDrag(object sender, ItemDragEventArgs e) {
415      TreeNode sourceNode = (TreeNode)e.Item;
416      if (IsAuthorized((Resource)sourceNode.Tag))
417        DoDragDrop(sourceNode, DragDropEffects.All);
418    }
419
420    private void treeSlaveGroup_DragEnter(object sender, DragEventArgs e) {
421      e.Effect = DragDropEffects.Move;
422    }
423
424    private void treeSlaveGroup_DragOver(object sender, DragEventArgs e) {
425      e.Effect = DragDropEffects.Move;
426    }
427
428    private void treeSlaveGroup_QueryContinueDrag(object sender, QueryContinueDragEventArgs e) {
429      e.Action = DragAction.Continue;
430    }
431
432    void ResetView() {
433      if (this.InvokeRequired) {
434        Invoke(new Action(ResetView));
435      } else {
436        treeSlaveGroup.Nodes.Clear();
437
438        if (slaveView.Content != null && slaveView.Content is SlaveGroup) {
439          slaveView.Content.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(SlaveViewContent_PropertyChanged);
440        }
441        slaveView.Content = null;
442        if (scheduleView.Content != null) {
443          scheduleView.Content.Clear();
444        }
445        HiveAdminClient.Instance.ResetDowntime();
446      }
447    }
448
449    private void UpdateResources() {
450      ResetView();
451
452      try {
453        HiveAdminClient.Instance.Refresh();
454        Content = HiveAdminClient.Instance.Resources;
455      }
456      catch (MessageSecurityException) {
457        ShowMessageSecurityException();
458      }
459      catch (AnonymousUserException) {
460        ShowHiveInformationDialog();
461      }
462    }
463
464    private void ShowMessageSecurityException() {
465      if (this.InvokeRequired) {
466        Invoke(new Action(ShowMessageSecurityException));
467      } else {
468        MessageBox.Show("A Message Security error has occured. This normally means that your user name or password is wrong.", "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
469      }
470    }
471
472    private void ShowHiveInformationDialog() {
473      if (this.InvokeRequired) {
474        Invoke(new Action(ShowHiveInformationDialog));
475      } else {
476        using (HiveInformationDialog dialog = new HiveInformationDialog()) {
477          dialog.ShowDialog(this);
478        }
479      }
480    }
481
482    private void UpdateResourcesAsync() {
483      TS.Task.Factory.StartNew(UpdateResources).ContinueWith((t) => {
484        DisplayError(t.Exception);
485      }, TaskContinuationOptions.OnlyOnFaulted);
486    }
487
488    private void UpdateSchedule() {
489      HiveAdminClient.Instance.RefreshCalendar();
490      scheduleView.Invoke(new Action(() => {
491        scheduleView.Content = HiveAdminClient.Instance.Downtimes;
492        SetEnabledStateOfControls(currentlyAuthorized);
493      }));
494    }
495
496    private void UpdateScheduleAsync() {
497      TS.Task.Factory.StartNew(UpdateSchedule).ContinueWith((t) => {
498        DisplayError(t.Exception);
499      }, TaskContinuationOptions.OnlyOnFaulted);
500    }
501
502    private void UpdatePermissions() {
503      if (permissionView.Content != null && permissionView.FetchSelectedUsers != null)
504        permissionView.Invoke(new Action(() => permissionView.ManualRefresh()));
505    }
506
507    private void UpdatePermissionsAsync() {
508      TS.Task.Factory.StartNew(UpdatePermissions).ContinueWith((t) => {
509        DisplayError(t.Exception);
510      }, TaskContinuationOptions.OnlyOnFaulted);
511    }
512
513
514    private void DisplayError(Exception ex) {
515      MessageBox.Show(string.Format("An error occured while updating: {0} {1}", Environment.NewLine, ex.Message), "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
516    }
517
518    private void tabSlaveGroup_SelectedIndexChanged(object sender, EventArgs e) {
519      if (tabSlaveGroup.SelectedIndex == 1) {
520        UpdateScheduleAsync();
521      } else if (tabSlaveGroup.SelectedIndex == 2) {
522        UpdatePermissionsAsync();
523      }
524    }
525
526    private void btnRefresh_Click(object sender, EventArgs e) {
527      UpdateResourcesAsync();
528    }
529
530    private void ResourcesView_Load(object sender, EventArgs e) {
531      UpdateResourcesAsync();
532    }
533
534    private void btnPermissionsSave_Click(object sender, EventArgs e) {
535      SetEnabledStateOfControls(false);
536      HiveServiceLocator.Instance.CallHiveService(service => {
537        service.GrantResourcePermissions(((Resource)treeSlaveGroup.SelectedNode.Tag).Id, permissionView.GetAddedUsers().Select(x => x.Id).ToList());
538        service.RevokeResourcePermissions(((Resource)treeSlaveGroup.SelectedNode.Tag).Id, permissionView.GetDeletedUsers().Select(x => x.Id).ToList());
539      });
540      SetEnabledStateOfControls(true);
541    }
542  }
543}
Note: See TracBrowser for help on using the repository browser.