Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectPermissionsView.cs @ 16187

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

#2839

  • fixed enabled state of controls bug for initial project selection regarding permission detail views
  • fixed problem at resource assignment for root projects
File size: 13.2 KB
RevLine 
[15422]1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2017 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.Windows.Forms;
27using HeuristicLab.Clients.Access;
28using HeuristicLab.Common.Resources;
29using HeuristicLab.Core.Views;
30using HeuristicLab.MainForm;
31
32namespace HeuristicLab.Clients.Hive.Administrator.Views {
33  [View("ProjectView")]
34  [Content(typeof(Project), IsDefaultView = false)]
35  public partial class ProjectPermissionsView : ItemView {
36    private const int userImageIndex = 0;
37    private const int userGroupImageIndex = 1;
38
39    private readonly HashSet<UserGroupBase> assignedPermissions = new HashSet<UserGroupBase>();
40    private readonly HashSet<UserGroupBase> inheritedPermissions = new HashSet<UserGroupBase>();
[15576]41    private readonly HashSet<UserGroupBase> newAssignedPermissions = new HashSet<UserGroupBase>();
42    private readonly HashSet<UserGroupBase> newInheritedPermissions = new HashSet<UserGroupBase>();
43    private readonly Dictionary<Guid, HashSet<UserGroupBase>> userGroupAncestors = new Dictionary<Guid, HashSet<UserGroupBase>>();
44    private readonly Dictionary<Guid, HashSet<UserGroupBase>> userGroupDescendants = new Dictionary<Guid, HashSet<UserGroupBase>>();
[15422]45
[15580]46    private IEnumerable<UserGroupBase> addedPermissions;
47    private IEnumerable<UserGroupBase> removedPermissions;
48    private IEnumerable<UserGroupBase> addedIncludes;
49    private IEnumerable<UserGroupBase> removedIncludes;
50
[15576]51    private readonly Color addedAssignmentColor = Color.FromArgb(255, 87, 191, 193); // #57bfc1
52    private readonly Color removedAssignmentColor = Color.FromArgb(255, 236, 159, 72); // #ec9f48
53    private readonly Color addedIncludeColor = Color.FromArgb(25, 169, 221, 221); // #a9dddd
54    private readonly Color removedIncludeColor = Color.FromArgb(25, 249, 210, 145); // #f9d291
[16117]55    private readonly Color projectOwnerColor = Color.DarkRed;
[15576]56
[15422]57    public new Project Content {
58      get { return (Project)base.Content; }
59      set { base.Content = value; }
60    }
61
62    public ProjectPermissionsView() {
63      InitializeComponent();
64
65      treeView.ImageList.Images.Add(VSImageLibrary.User);
66      treeView.ImageList.Images.Add(VSImageLibrary.UserAccounts);
67    }
68
69    #region Overrides
70    protected override void OnContentChanged() {
71      base.OnContentChanged();
72      if (Content == null) {
73        assignedPermissions.Clear();
74        inheritedPermissions.Clear();
[15576]75        newAssignedPermissions.Clear();
76        newInheritedPermissions.Clear();
[15422]77        treeView.Nodes.Clear();
78        detailsViewHost.Content = null;
79      } else {
[16187]80        UpdatePermissionList();       
[15422]81      }
[16187]82      SetEnabledStateOfControls();
[15422]83    }
[15760]84
85    protected override void SetEnabledStateOfControls() {
86      base.SetEnabledStateOfControls();
87      bool enabled = Content != null && !Locked && !ReadOnly;
88
89      inheritButton.Enabled = enabled;
90      saveButton.Enabled = enabled;
91      treeView.Enabled = enabled;
[16187]92
93      if (detailsViewHost != null) {
94        detailsViewHost.Locked = true;
95      }
96
[15760]97    }
[15422]98    #endregion
99
100    #region Event Handlers
101    private void ProjectPermissionsView_Load(object sender, EventArgs e) {
102
103    }
104
105    private void refreshButton_Click(object sender, EventArgs e) {
[15576]106      UpdatePermissionList();
[15422]107    }
108
[15576]109    private async void inheritButton_Click(object sender, EventArgs e) {
110      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
[15642]111        action: () => SetGrantedProjectPermissions(Content.Id, newAssignedPermissions.Select(x => x.Id), false, true, false));
[15576]112      UpdatePermissionList();
[15422]113    }
114
115    private async void saveButton_Click(object sender, EventArgs e) {
116      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
[15576]117        action: () => SetGrantedProjectPermissions(Content.Id, newAssignedPermissions.Select(x => x.Id), false, false, false));
118      UpdatePermissionList();
[15422]119    }
120
121    private void treeView_AfterSelect(object sender, TreeViewEventArgs e) {
122      var selectedPermission = (UserGroupBase)e.Node.Tag;
123      detailsViewHost.Content = selectedPermission;
[16186]124      if (selectedPermission is LightweightUser)
125        detailsViewHost.ViewType = typeof(Access.Views.RefreshableLightweightUserInformationView);
[15422]126    }
127
128    private void treeView_BeforeCheck(object sender, TreeViewCancelEventArgs e) {
129      var checkedPermission = (UserGroupBase)e.Node.Tag;
[16117]130      if (e.Node.Parent == null
131        || newInheritedPermissions.Contains(checkedPermission)
132        || checkedPermission.Id == Guid.Empty
133        || Content.OwnerUserId == checkedPermission.Id)
134          e.Cancel = true;
[15422]135    }
136
137    private void treeView_AfterCheck(object sender, TreeViewEventArgs e) {
138      var checkedPermission = (UserGroupBase)e.Node.Tag;
139      if (e.Node.Checked)
[15576]140        newAssignedPermissions.Add(checkedPermission);
[15422]141      else
[15576]142        newAssignedPermissions.Remove(checkedPermission);
143
144      UpdateNewPermissionList();
[15422]145    }
146    #endregion
147
148    #region Helpers
[15576]149    private void UpdatePermissionList() {
[16117]150      AccessClient.Instance.Refresh();
151
[15576]152      UpdateUserGroupGenealogy();
153      UpdateAssignedPermissions();
154      UpdateInheritedPermissions();
155      var top = BuildPermissionsList(AccessClient.Instance.UsersAndGroups);
156      detailsViewHost.Content = top;
[15422]157    }
158
[15576]159    private void UpdateNewPermissionList() {
160      UpdateNewAssignedPermissions();
161      UpdateNewInheritedPermissions();
162      var top = BuildPermissionsList(AccessClient.Instance.UsersAndGroups);
163      detailsViewHost.Content = top;
[15422]164    }
165
166    private void UpdateAssignedPermissions() {
167      assignedPermissions.Clear();
[15576]168      newAssignedPermissions.Clear();
169      var grantedPermissions = GetGrantedPermissionsForProject(Content.Id);
170      foreach (var r in grantedPermissions) {
[15422]171        assignedPermissions.Add(r);
[15576]172        newAssignedPermissions.Add(r);
173      }
[15422]174    }
175
[15576]176    private void UpdateNewAssignedPermissions() {
177      for(int i = newAssignedPermissions.Count-1; i >= 0; i--) {
[16117]178        if(newAssignedPermissions.Intersect(userGroupAncestors[newAssignedPermissions.ElementAt(i).Id]).Any()
179          && newAssignedPermissions.ElementAt(i).Id != Content.OwnerUserId) {
[15576]180          newAssignedPermissions.Remove(newAssignedPermissions.ElementAt(i));
181        }
182      }
183    }
184
[15422]185    private void UpdateInheritedPermissions() {
186      inheritedPermissions.Clear();
[15576]187      newInheritedPermissions.Clear();
188      foreach(var item in assignedPermissions) {
189        if(userGroupDescendants.ContainsKey(item.Id)) {
190          foreach(var descendant in userGroupDescendants[item.Id]) {
[16117]191            if(!assignedPermissions.Contains(descendant)) {
192              inheritedPermissions.Add(descendant);
193              newInheritedPermissions.Add(descendant);
194            }
[15576]195          }
196        }
[15422]197      }
198    }
199
[15576]200    private void UpdateNewInheritedPermissions() {
201      newInheritedPermissions.Clear();
202      foreach(var item in newAssignedPermissions) {
203        if(userGroupDescendants.ContainsKey(item.Id)) {
204          foreach(var descendant in userGroupDescendants[item.Id]) {
[16117]205            if(!newAssignedPermissions.Contains(descendant))
206              newInheritedPermissions.Add(descendant);
[15576]207          }
208        }
209      }
210    }
211
212    private void UpdateUserGroupGenealogy() {
213      userGroupAncestors.Clear();
214      userGroupDescendants.Clear();
215
216      var usersAndGroups = AccessClient.Instance.UsersAndGroups;
217      foreach (var ug in usersAndGroups) {
218        userGroupAncestors.Add(ug.Id, new HashSet<UserGroupBase>());
219        userGroupDescendants.Add(ug.Id, new HashSet<UserGroupBase>());
220      }
221
222      var userGroupTree = HiveServiceLocator.Instance.CallHiveService(s => s.GetUserGroupTree());
223      foreach(var branch in userGroupTree) {
224        var parent = usersAndGroups.Where(x => x.Id == branch.Key).SingleOrDefault();
225        if(parent != null) {
226          var userGroupsToAdd = usersAndGroups.Where(x => userGroupTree[parent.Id].Contains(x.Id));
227          foreach (var node in userGroupsToAdd) {
228            userGroupDescendants[parent.Id].Add(node);
229            userGroupAncestors[node.Id].Add(parent);
230          }
231        }
232      }
233    }
234
235    private static IEnumerable<UserGroupBase> GetGrantedPermissionsForProject(Guid projectId) {
[16117]236      if (projectId == Guid.Empty) return Enumerable.Empty<UserGroupBase>();
[15576]237      var projectPermissions = HiveServiceLocator.Instance.CallHiveService(s => s.GetProjectPermissions(projectId));
238      var userIds = new HashSet<Guid>(projectPermissions.Select(x => x.GrantedUserId));
239      return AccessClient.Instance.UsersAndGroups.Where(x => userIds.Contains(x.Id));
240    }
241
242    private static void SetGrantedProjectPermissions(Guid projectId, IEnumerable<Guid> userIds, bool reassign, bool cascading, bool reassignCascading) {
243      if (projectId == null || userIds == null) return;
244      HiveServiceLocator.Instance.CallHiveService(s => {
245        s.SaveProjectPermissions(projectId, userIds.ToList(), reassign, cascading, reassignCascading);
246      });
247    }
248
[15422]249    private UserGroupBase BuildPermissionsList(IEnumerable<UserGroupBase> usersAndGroups) {
[15580]250      addedPermissions = newAssignedPermissions.Except(assignedPermissions);
251      removedPermissions = assignedPermissions.Except(newAssignedPermissions);
252      addedIncludes = newInheritedPermissions.Except(inheritedPermissions);
253      removedIncludes = inheritedPermissions.Except(newInheritedPermissions);
254
[15422]255      treeView.Nodes.Clear();
256      if (!usersAndGroups.Any()) return null;
257
258      treeView.BeforeCheck -= treeView_BeforeCheck;
259      treeView.AfterCheck -= treeView_AfterCheck;
260
261      var userGroups = new HashSet<UserGroup>(usersAndGroups.OfType<UserGroup>());
262      var users = new HashSet<LightweightUser>(usersAndGroups.OfType<LightweightUser>());
263      UserGroupBase first = null;
264
265      var groupsNode = new TreeNode("Groups") { ForeColor = SystemColors.GrayText };
266      groupsNode.ImageIndex = groupsNode.SelectedImageIndex = userGroupImageIndex;
267
268      foreach (var group in userGroups.OrderBy(x => x.Name)) {
269        var node = new TreeNode(group.Name) { Tag = group };
270        node.ImageIndex = userGroupImageIndex;
271        node.SelectedImageIndex = node.ImageIndex;
[15576]272        BuildNode(group, node);
[15422]273        groupsNode.Nodes.Add(node);
274        if (first == null) first = group;
275      }
276
277      var usersNode = new TreeNode("Users") { ForeColor = SystemColors.GrayText };
278      usersNode.ImageIndex = usersNode.SelectedImageIndex = userImageIndex;
279
280      foreach (var user in users.OrderBy(x => x.ToString())) {
281        var node = new TreeNode(user.ToString()) { Tag = user };
282        node.ImageIndex = userImageIndex;
283        node.SelectedImageIndex = node.ImageIndex;
[15576]284        BuildNode(user, node);
[15422]285        usersNode.Nodes.Add(node);
286        if (first == null) first = user;
287      }
288
289      treeView.Nodes.Add(groupsNode);
290      treeView.Nodes.Add(usersNode);
291      treeView.BeforeCheck += treeView_BeforeCheck;
292      treeView.AfterCheck += treeView_AfterCheck;
293      treeView.ExpandAll();
294
295      return first;
296    }
[15576]297
298    private void BuildNode(UserGroupBase ug, TreeNode node) {
299
300      if (newAssignedPermissions.Contains(ug)) {
301        node.Checked = true;
302      } else if (newInheritedPermissions.Contains(ug)) {
303        node.Checked = true;
304        node.ForeColor = SystemColors.GrayText;
305      }
306
307      if (inheritedPermissions.Contains(ug) && newInheritedPermissions.Contains(ug)) {
308        node.Text += " [included]";
309      } else if (addedIncludes.Contains(ug)) {
310        node.BackColor = addedIncludeColor;
311        node.ForeColor = SystemColors.GrayText;
312        node.Text += " [added include]";
313      } else if (removedIncludes.Contains(ug)) {
314        node.BackColor = removedIncludeColor;
315        node.ForeColor = SystemColors.GrayText;
316        node.Text += " [removed include]";
317      }
318
319      if (addedPermissions.Contains(ug)) {
320        node.BackColor = addedAssignmentColor;
321        node.ForeColor = SystemColors.ControlText;
322        node.Text += " [added assignment]";
323      } else if (removedPermissions.Contains(ug)) {
324        node.BackColor = removedAssignmentColor;
325        node.ForeColor = SystemColors.ControlText;
326        node.Text += " [removed assignment]";
327      }
328
[16117]329      if(Content != null && ug != null && ug.Id != Guid.Empty
330        && Content.OwnerUserId == ug.Id) {
331        node.ForeColor = projectOwnerColor;
332      }
333
[15576]334    }
335
[15422]336    #endregion
337  }
338}
Note: See TracBrowser for help on using the repository browser.