mirror of
https://github.com/xcp-ng/xenadmin.git
synced 2024-12-23 08:56:02 +01:00
245 lines
9.6 KiB
C#
245 lines
9.6 KiB
C#
|
/* Copyright (c) Citrix Systems Inc.
|
||
|
* All rights reserved.
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms,
|
||
|
* with or without modification, are permitted provided
|
||
|
* that the following conditions are met:
|
||
|
*
|
||
|
* * Redistributions of source code must retain the above
|
||
|
* copyright notice, this list of conditions and the
|
||
|
* following disclaimer.
|
||
|
* * Redistributions in binary form must reproduce the above
|
||
|
* copyright notice, this list of conditions and the
|
||
|
* following disclaimer in the documentation and/or other
|
||
|
* materials provided with the distribution.
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||
|
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||
|
* SUCH DAMAGE.
|
||
|
*/
|
||
|
|
||
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.ComponentModel;
|
||
|
using System.Data;
|
||
|
using System.Drawing;
|
||
|
using System.Text;
|
||
|
using System.Windows.Forms;
|
||
|
using XenAPI;
|
||
|
using XenAdmin.Core;
|
||
|
|
||
|
|
||
|
namespace XenAdmin.Dialogs
|
||
|
{
|
||
|
public partial class RoleSelectionDialog : XenDialogBase
|
||
|
{
|
||
|
private Subject[] subjects;
|
||
|
private Pool pool;
|
||
|
private Dictionary<Role, List<Subject>> roleAssignment;
|
||
|
// Used to stop 'changes made' checks during a batch select
|
||
|
bool batchChange = false;
|
||
|
|
||
|
public RoleSelectionDialog()
|
||
|
{
|
||
|
InitializeComponent();
|
||
|
}
|
||
|
|
||
|
public RoleSelectionDialog(Subject[] subjects, Pool pool) : this()
|
||
|
{
|
||
|
this.subjects = subjects;
|
||
|
this.pool = pool;
|
||
|
roleAssignment = new Dictionary<Role,List<Subject>>();
|
||
|
if (subjects.Length == 1)
|
||
|
{
|
||
|
Subject subject = subjects[0];
|
||
|
string sName = (subject.DisplayName ?? subject.SubjectName ?? Messages.UNKNOWN_AD_USER).Ellipsise(30);
|
||
|
if (subject.IsGroup)
|
||
|
{
|
||
|
labelBlurb.Text = String.Format(Messages.AD_SELECT_ROLE_GROUP, sName);
|
||
|
pictureBoxSubjectType.Image = XenAdmin.Properties.Resources._000_UserAndGroup_h32bit_32;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
labelBlurb.Text = String.Format(Messages.AD_SELECT_ROLE_USER, sName);
|
||
|
pictureBoxSubjectType.Image = XenAdmin.Properties.Resources._000_User_h32bit_16;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
labelBlurb.Text = Messages.AD_SELECT_ROLE_MIXED;
|
||
|
pictureBoxSubjectType.Image = XenAdmin.Properties.Resources._000_User_h32bit_16;
|
||
|
}
|
||
|
|
||
|
// Get the list of roles off the server and arrange them into rank
|
||
|
List<Role> serverRoles = new List<Role>(pool.Connection.Cache.Roles);
|
||
|
//hide basic permissions, we only want the roles.
|
||
|
serverRoles.RemoveAll(delegate(Role r){return r.subroles.Count < 1;});
|
||
|
serverRoles.Sort();
|
||
|
serverRoles.Reverse();
|
||
|
foreach (Role r in serverRoles)
|
||
|
{
|
||
|
roleAssignment.Add(r, new List<Subject>());
|
||
|
}
|
||
|
foreach (Subject s in subjects)
|
||
|
{
|
||
|
List<Role> subjectRoles = (List<Role>)pool.Connection.ResolveAll<Role>(s.roles);
|
||
|
foreach (Role r in subjectRoles)
|
||
|
{
|
||
|
roleAssignment[r].Add(s);
|
||
|
}
|
||
|
}
|
||
|
foreach (Role role in serverRoles)
|
||
|
{
|
||
|
DataGridViewRow r = new DataGridViewRow();
|
||
|
DataGridViewCheckBoxCellEx c1 = new DataGridViewCheckBoxCellEx();
|
||
|
c1.ThreeState = true;
|
||
|
if (roleAssignment[role].Count == subjects.Length)
|
||
|
{
|
||
|
c1.Value = CheckState.Checked;
|
||
|
c1.CheckState = CheckState.Checked;
|
||
|
}
|
||
|
else if (roleAssignment[role].Count == 0)
|
||
|
{
|
||
|
c1.Value = CheckState.Unchecked;
|
||
|
c1.CheckState = CheckState.Unchecked;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
c1.Value = CheckState.Indeterminate;
|
||
|
c1.CheckState = CheckState.Indeterminate;
|
||
|
}
|
||
|
DataGridViewTextBoxCell c2 = new DataGridViewTextBoxCell();
|
||
|
c2.Value = role.FriendlyName;
|
||
|
r.Cells.Add(c1);
|
||
|
r.Cells.Add(c2);
|
||
|
r.Tag = role;
|
||
|
gridRoles.Rows.Add(r);
|
||
|
}
|
||
|
setRoleDescription();
|
||
|
}
|
||
|
|
||
|
private void setRoleDescription()
|
||
|
{
|
||
|
if (gridRoles.SelectedRows.Count < 1)
|
||
|
return;
|
||
|
Role r = gridRoles.SelectedRows[0].Tag as Role;
|
||
|
if (r == null)
|
||
|
return;
|
||
|
|
||
|
labelDescription.Text = r.FriendlyDescription;
|
||
|
}
|
||
|
|
||
|
private void buttonSave_Click(object sender, EventArgs e)
|
||
|
{
|
||
|
foreach (Subject s in subjects)
|
||
|
{
|
||
|
List<Role> rolesToAdd = new List<Role>();
|
||
|
List<Role> rolesToRemove = new List<Role>();
|
||
|
foreach (DataGridViewRow r in gridRoles.Rows)
|
||
|
{
|
||
|
bool check = (bool)r.Cells[0].Value;
|
||
|
Role role = r.Tag as Role;
|
||
|
if (check && !(roleAssignment[role].Contains(s)))
|
||
|
rolesToAdd.Add(role);
|
||
|
else if (!check && (roleAssignment[role].Contains(s)))
|
||
|
rolesToRemove.Add(role);
|
||
|
}
|
||
|
|
||
|
XenAdmin.Actions.AddRemoveRolesAction a = new XenAdmin.Actions.AddRemoveRolesAction(pool, s, rolesToAdd, rolesToRemove);
|
||
|
a.RunAsync();
|
||
|
}
|
||
|
Close();
|
||
|
}
|
||
|
|
||
|
private bool changesMade()
|
||
|
{
|
||
|
foreach (DataGridViewRow r in gridRoles.Rows)
|
||
|
{
|
||
|
Role role = r.Tag as Role;
|
||
|
DataGridViewCheckBoxCellEx c = r.Cells[0] as DataGridViewCheckBoxCellEx;
|
||
|
if (c.CheckState == CheckState.Checked && roleAssignment[role].Count < subjects.Length)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
else if (c.CheckState == CheckState.Unchecked && roleAssignment[role].Count > 0)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
// Don't care about intermediate values, it's not possible to set them in the dialog
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
private void buttonCancel_Click(object sender, EventArgs e)
|
||
|
{
|
||
|
Close();
|
||
|
}
|
||
|
|
||
|
private void gridRoles_SelectionChanged(object sender, EventArgs e)
|
||
|
{
|
||
|
setRoleDescription();
|
||
|
}
|
||
|
|
||
|
|
||
|
// We want to allow the user to select rows without changing the check boxes so they can browse the descriptions
|
||
|
// so handle mouseclicks only on the check box column
|
||
|
// Only allow them to select a single role, which also means all that tri state rubbish dissapears as soon as they make a selection
|
||
|
private void gridRoles_CellContentClick(object sender, DataGridViewCellEventArgs e)
|
||
|
{
|
||
|
if (e.ColumnIndex != 0 || e.RowIndex < 0 || batchChange)
|
||
|
return;
|
||
|
|
||
|
selectIndex(e.RowIndex);
|
||
|
buttonSave.Enabled = changesMade();
|
||
|
}
|
||
|
|
||
|
// We want to allow the user to select rows without changing the check boxes so they can browse the descriptions
|
||
|
// but we want it to be keyboard accessible. Capture the select keypress and toggle the checkbox
|
||
|
private void gridRoles_KeyPress(object sender, KeyPressEventArgs e)
|
||
|
{
|
||
|
// makes assumption about multiselect
|
||
|
System.Diagnostics.Trace.Assert(!gridRoles.MultiSelect);
|
||
|
|
||
|
if (batchChange || e.KeyChar != ' ')
|
||
|
return;
|
||
|
|
||
|
selectIndex(gridRoles.SelectedRows[0].Index);
|
||
|
buttonSave.Enabled = changesMade();
|
||
|
}
|
||
|
|
||
|
private void selectIndex(int i)
|
||
|
{
|
||
|
batchChange = true;
|
||
|
foreach (DataGridViewRow r in gridRoles.Rows)
|
||
|
{
|
||
|
if (i == r.Index)
|
||
|
{
|
||
|
r.Cells[0].Value = true;
|
||
|
((DataGridViewCheckBoxCellEx)(r.Cells[0])).CheckState = CheckState.Checked;
|
||
|
continue;
|
||
|
}
|
||
|
r.Cells[0].Value = false;
|
||
|
((DataGridViewCheckBoxCellEx)(r.Cells[0])).CheckState = CheckState.Unchecked;
|
||
|
}
|
||
|
batchChange = false;
|
||
|
}
|
||
|
|
||
|
// Data grid view check box cells dont commit their value immeadiately, though the UI updates (edit mode).
|
||
|
// To prevent messing around we handle the check state value ourselves.
|
||
|
class DataGridViewCheckBoxCellEx : DataGridViewCheckBoxCell
|
||
|
{
|
||
|
public CheckState CheckState = CheckState.Unchecked;
|
||
|
}
|
||
|
}
|
||
|
}
|