source: branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectPermissionsView.cs @ 15760

Last change on this file since 15760 was 15760, checked in by jzenisek, 19 months ago

#2839

  • minor changes regarding project- & resource selection
  • adapted DeleteOnNull rules in dbml
File size: 12.3 KB
Line 
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>();
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>>();
45
46    private IEnumerable<UserGroupBase> addedPermissions;
47    private IEnumerable<UserGroupBase> removedPermissions;
48    private IEnumerable<UserGroupBase> addedIncludes;
49    private IEnumerable<UserGroupBase> removedIncludes;
50
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
55
56    public new Project Content {
57      get { return (Project)base.Content; }
58      set { base.Content = value; }
59    }
60
61    public ProjectPermissionsView() {
62      InitializeComponent();
63
64      treeView.ImageList.Images.Add(VSImageLibrary.User);
65      treeView.ImageList.Images.Add(VSImageLibrary.UserAccounts);
66    }
67
68    #region Overrides
69    protected override void OnContentChanged() {
70      base.OnContentChanged();
71      if (Content == null) {
72        assignedPermissions.Clear();
73        inheritedPermissions.Clear();
74        newAssignedPermissions.Clear();
75        newInheritedPermissions.Clear();
76        treeView.Nodes.Clear();
77        detailsViewHost.Content = null;
78      } else {
79        UpdatePermissionList();
80        detailsViewHost.ActiveView.Locked = true;
81      }
82    }
83
84    protected override void SetEnabledStateOfControls() {
85      base.SetEnabledStateOfControls();
86      bool enabled = Content != null && !Locked && !ReadOnly;
87
88      inheritButton.Enabled = enabled;
89      saveButton.Enabled = enabled;
90      treeView.Enabled = enabled;
91    }
92    #endregion
93
94    #region Event Handlers
95    private void ProjectPermissionsView_Load(object sender, EventArgs e) {
96
97    }
98
99    private void refreshButton_Click(object sender, EventArgs e) {
100      UpdatePermissionList();
101    }
102
103    private async void inheritButton_Click(object sender, EventArgs e) {
104      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
105        action: () => SetGrantedProjectPermissions(Content.Id, newAssignedPermissions.Select(x => x.Id), false, true, false));
106      UpdatePermissionList();
107    }
108
109    private async void saveButton_Click(object sender, EventArgs e) {
110      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
111        action: () => SetGrantedProjectPermissions(Content.Id, newAssignedPermissions.Select(x => x.Id), false, false, false));
112      UpdatePermissionList();
113    }
114
115    private void treeView_AfterSelect(object sender, TreeViewEventArgs e) {
116      var selectedPermission = (UserGroupBase)e.Node.Tag;
117      detailsViewHost.Content = selectedPermission;
118    }
119
120    private void treeView_BeforeCheck(object sender, TreeViewCancelEventArgs e) {
121      var checkedPermission = (UserGroupBase)e.Node.Tag;
122      if (e.Node.Parent == null || newInheritedPermissions.Contains(checkedPermission) || checkedPermission.Id == Guid.Empty) e.Cancel = true;
123    }
124
125    private void treeView_AfterCheck(object sender, TreeViewEventArgs e) {
126      var checkedPermission = (UserGroupBase)e.Node.Tag;
127      if (e.Node.Checked)
128        newAssignedPermissions.Add(checkedPermission);
129      else
130        newAssignedPermissions.Remove(checkedPermission);
131
132      UpdateNewPermissionList();
133    }
134    #endregion
135
136    #region Helpers
137    private void UpdatePermissionList() {
138      UpdateUserGroupGenealogy();
139      UpdateAssignedPermissions();
140      UpdateInheritedPermissions();
141      var top = BuildPermissionsList(AccessClient.Instance.UsersAndGroups);
142      detailsViewHost.Content = top;
143    }
144
145    private void UpdateNewPermissionList() {
146      UpdateNewAssignedPermissions();
147      UpdateNewInheritedPermissions();
148      var top = BuildPermissionsList(AccessClient.Instance.UsersAndGroups);
149      detailsViewHost.Content = top;
150    }
151
152    private void UpdateAssignedPermissions() {
153      assignedPermissions.Clear();
154      newAssignedPermissions.Clear();
155      var grantedPermissions = GetGrantedPermissionsForProject(Content.Id);
156      foreach (var r in grantedPermissions) {
157        assignedPermissions.Add(r);
158        newAssignedPermissions.Add(r);
159      }
160    }
161
162    private void UpdateNewAssignedPermissions() {
163      for(int i = newAssignedPermissions.Count-1; i >= 0; i--) {
164        if(newAssignedPermissions.Intersect(userGroupAncestors[newAssignedPermissions.ElementAt(i).Id]).Any()) {
165          newAssignedPermissions.Remove(newAssignedPermissions.ElementAt(i));
166        }
167      }
168    }
169
170    private void UpdateInheritedPermissions() {
171      inheritedPermissions.Clear();
172      newInheritedPermissions.Clear();
173      foreach(var item in assignedPermissions) {
174        if(userGroupDescendants.ContainsKey(item.Id)) {
175          foreach(var descendant in userGroupDescendants[item.Id]) {
176            inheritedPermissions.Add(descendant);
177            newInheritedPermissions.Add(descendant);
178          }
179        }
180      }
181    }
182
183    private void UpdateNewInheritedPermissions() {
184      newInheritedPermissions.Clear();
185      foreach(var item in newAssignedPermissions) {
186        if(userGroupDescendants.ContainsKey(item.Id)) {
187          foreach(var descendant in userGroupDescendants[item.Id]) {
188            newInheritedPermissions.Add(descendant);
189          }
190        }
191      }
192    }
193
194    private void UpdateUserGroupGenealogy() {
195      userGroupAncestors.Clear();
196      userGroupDescendants.Clear();
197
198      var usersAndGroups = AccessClient.Instance.UsersAndGroups;
199      foreach (var ug in usersAndGroups) {
200        userGroupAncestors.Add(ug.Id, new HashSet<UserGroupBase>());
201        userGroupDescendants.Add(ug.Id, new HashSet<UserGroupBase>());
202      }
203
204      var userGroupTree = HiveServiceLocator.Instance.CallHiveService(s => s.GetUserGroupTree());
205      foreach(var branch in userGroupTree) {
206        var parent = usersAndGroups.Where(x => x.Id == branch.Key).SingleOrDefault();
207        if(parent != null) {
208          var userGroupsToAdd = usersAndGroups.Where(x => userGroupTree[parent.Id].Contains(x.Id));
209          foreach (var node in userGroupsToAdd) {
210            userGroupDescendants[parent.Id].Add(node);
211            userGroupAncestors[node.Id].Add(parent);
212          }
213        }
214      }
215    }
216
217    private static IEnumerable<UserGroupBase> GetGrantedPermissionsForProject(Guid projectId) {
218      var projectPermissions = HiveServiceLocator.Instance.CallHiveService(s => s.GetProjectPermissions(projectId));
219      var userIds = new HashSet<Guid>(projectPermissions.Select(x => x.GrantedUserId));
220      return AccessClient.Instance.UsersAndGroups.Where(x => userIds.Contains(x.Id));
221    }
222
223    private static void SetGrantedProjectPermissions(Guid projectId, IEnumerable<Guid> userIds, bool reassign, bool cascading, bool reassignCascading) {
224      if (projectId == null || userIds == null) return;
225      HiveServiceLocator.Instance.CallHiveService(s => {
226        s.SaveProjectPermissions(projectId, userIds.ToList(), reassign, cascading, reassignCascading);
227      });
228    }
229
230    private UserGroupBase BuildPermissionsList(IEnumerable<UserGroupBase> usersAndGroups) {
231      addedPermissions = newAssignedPermissions.Except(assignedPermissions);
232      removedPermissions = assignedPermissions.Except(newAssignedPermissions);
233      addedIncludes = newInheritedPermissions.Except(inheritedPermissions);
234      removedIncludes = inheritedPermissions.Except(newInheritedPermissions);
235
236      treeView.Nodes.Clear();
237      if (!usersAndGroups.Any()) return null;
238
239      treeView.BeforeCheck -= treeView_BeforeCheck;
240      treeView.AfterCheck -= treeView_AfterCheck;
241
242      var userGroups = new HashSet<UserGroup>(usersAndGroups.OfType<UserGroup>());
243      var users = new HashSet<LightweightUser>(usersAndGroups.OfType<LightweightUser>());
244      UserGroupBase first = null;
245
246      var groupsNode = new TreeNode("Groups") { ForeColor = SystemColors.GrayText };
247      groupsNode.ImageIndex = groupsNode.SelectedImageIndex = userGroupImageIndex;
248
249      foreach (var group in userGroups.OrderBy(x => x.Name)) {
250        var node = new TreeNode(group.Name) { Tag = group };
251        node.ImageIndex = userGroupImageIndex;
252        node.SelectedImageIndex = node.ImageIndex;
253        BuildNode(group, node);
254        groupsNode.Nodes.Add(node);
255        if (first == null) first = group;
256      }
257
258      var usersNode = new TreeNode("Users") { ForeColor = SystemColors.GrayText };
259      usersNode.ImageIndex = usersNode.SelectedImageIndex = userImageIndex;
260
261      foreach (var user in users.OrderBy(x => x.ToString())) {
262        var node = new TreeNode(user.ToString()) { Tag = user };
263        node.ImageIndex = userImageIndex;
264        node.SelectedImageIndex = node.ImageIndex;
265        BuildNode(user, node);
266        usersNode.Nodes.Add(node);
267        if (first == null) first = user;
268      }
269
270      treeView.Nodes.Add(groupsNode);
271      treeView.Nodes.Add(usersNode);
272      treeView.BeforeCheck += treeView_BeforeCheck;
273      treeView.AfterCheck += treeView_AfterCheck;
274      treeView.ExpandAll();
275
276      return first;
277    }
278
279    private void BuildNode(UserGroupBase ug, TreeNode node) {
280
281      if (newAssignedPermissions.Contains(ug)) {
282        node.Checked = true;
283      } else if (newInheritedPermissions.Contains(ug)) {
284        node.Checked = true;
285        node.ForeColor = SystemColors.GrayText;
286      }
287
288      if (inheritedPermissions.Contains(ug) && newInheritedPermissions.Contains(ug)) {
289        node.Text += " [included]";
290      } else if (addedIncludes.Contains(ug)) {
291        node.BackColor = addedIncludeColor;
292        node.ForeColor = SystemColors.GrayText;
293        node.Text += " [added include]";
294      } else if (removedIncludes.Contains(ug)) {
295        node.BackColor = removedIncludeColor;
296        node.ForeColor = SystemColors.GrayText;
297        node.Text += " [removed include]";
298      }
299
300      if (addedPermissions.Contains(ug)) {
301        node.BackColor = addedAssignmentColor;
302        node.ForeColor = SystemColors.ControlText;
303        node.Text += " [added assignment]";
304      } else if (removedPermissions.Contains(ug)) {
305        node.BackColor = removedAssignmentColor;
306        node.ForeColor = SystemColors.ControlText;
307        node.Text += " [removed assignment]";
308      }
309
310    }
311
312    #endregion
313  }
314}
Note: See TracBrowser for help on using the repository browser.