Просмотр исходного кода

Improved security token handling for grids

Kenric Nugteren 3 недель назад
Родитель
Сommit
994e57e97b

+ 18 - 2
inabox.wpf/DigitalForms/Designer/DynamicFormDesignWindow.xaml.cs

@@ -28,6 +28,21 @@ public partial class DynamicFormDesignWindow : Window, IDynamicFormWindow
         Preview.Mode = FormMode.Designing;
     }
 
+    private bool _readOnly;
+    public bool ReadOnly
+    {
+        get => _readOnly;
+        set
+        {
+            _readOnly = value;
+            SwitchView.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
+            if (!_readOnly)
+            {
+                Preview.Mode = FormMode.Preview;
+            }
+        }
+    }
+
     public DynamicFormDesignGrid Grid => Preview;
 
     private DFLayoutType _type;
@@ -47,10 +62,11 @@ public partial class DynamicFormDesignWindow : Window, IDynamicFormWindow
         get => Grid.Mode == FormMode.Designing;
         set
         {
-            Grid.Mode = value
+            var val = ReadOnly ? false : value;
+            Grid.Mode = val
                 ? FormMode.Designing
                 : FormMode.Preview;
-            SwitchView.Content = value ? "Preview" : "Design";
+            SwitchView.Content = val ? "Preview" : "Design";
         }
     }
 

+ 4 - 1
inabox.wpf/DigitalForms/DigitalFormGrid.cs

@@ -170,7 +170,10 @@ namespace InABox.DynamicGrid
             // TODO: Add back in
             //ActionColumns.Add(new DynamicImageColumn(ReportImage, ReportClick));
 
-            AddButton("Groups", null, EditGroupsClick);
+            if (Security.CanView<DigitalFormGroup>())
+            {
+                AddButton("Groups", null, EditGroupsClick);
+            }
 
             CopyForm = AddButton("Duplicate", InABox.Wpf.Resources.copy.AsBitmapImage(), CopyForm_Click);
             CopyForm.IsEnabled = false;

+ 9 - 5
inabox.wpf/DigitalForms/DynamicFormLayoutGrid.cs

@@ -36,12 +36,15 @@ public abstract class DynamicFormLayoutGrid : DynamicOneToManyGrid<DigitalForm,
         HiddenColumns.Add(x => x.Form.Code);
         HiddenColumns.Add(x => x.Form.Description);
 
-        ActionColumns.Add(new DynamicTickColumn<DigitalFormLayout, bool>(x => x.Active, tick, tick, null,
-            action: ActiveClick));
+        if (!ReadOnly)
+        {
+            ActionColumns.Add(new DynamicTickColumn<DigitalFormLayout, bool>(x => x.Active, tick, tick, null,
+                action: ActiveClick));
+        }
         ActionColumns.Add(new DynamicImageColumn(DesignImage, DesignClick));
 
-        AddButton("Auto Generate", null, AutoGenerate_Click);
-        AddButton("Duplicate", null, Duplicate_Click);
+        AddEditButton("Auto Generate", null, AutoGenerate_Click);
+        AddEditButton("Duplicate", null, Duplicate_Click);
     }
 
     private bool ActiveClick(CoreRow? row)
@@ -233,7 +236,8 @@ public abstract class DynamicFormLayoutGrid : DynamicOneToManyGrid<DigitalForm,
 
         var form = new DynamicFormDesignWindow
         {
-            Type = layout.Type
+            Type = layout.Type,
+            ReadOnly = ReadOnly
         };
         form.OnCreateVariable += (fieldType) =>
         {

+ 5 - 4
inabox.wpf/DigitalForms/DynamicVariableGrid.cs

@@ -26,7 +26,7 @@ namespace InABox.DynamicGrid
             base.Init();
 
             ShowHiddenButton = AddButton("Show Hidden", null, ToggleHidden_Click);
-            HideButton = AddButton("Hide Variable", null, Hide_Click);
+            HideButton = AddEditButton("Hide Variable", null, Hide_Click);
             HideButton.IsEnabled = false;
 
             HiddenColumns.Add(x => x.Hidden);
@@ -139,7 +139,7 @@ namespace InABox.DynamicGrid
                 return;
             var variable = LoadItem(SelectedRows.First());
             var properties = variable.CreateProperties();
-            if (DynamicVariableUtils.EditProperties(Item, Items, properties.GetType(), properties))
+            if (DynamicVariableUtils.EditProperties(Item, Items, properties.GetType(), properties, ReadOnly))
             {
                 variable.SaveProperties(properties);
                 SaveItem(variable);
@@ -241,7 +241,7 @@ namespace InABox.DynamicGrid
             {
                 var propertiesType = fieldBaseType.GetGenericArguments()[0];
                 var properties = (Activator.CreateInstance(propertiesType) as DFLayoutFieldProperties)!;
-                if (DynamicVariableUtils.EditProperties(form, variables, propertiesType, properties))
+                if (DynamicVariableUtils.EditProperties(form, variables, propertiesType, properties, readOnly: false))
                 {
                     variable = new DigitalFormVariable();
                     variable.SaveProperties(fieldType, properties);
@@ -252,9 +252,10 @@ namespace InABox.DynamicGrid
             return false;
         }
 
-        public static bool EditProperties(DigitalForm form, IList<DigitalFormVariable> variables, Type type, DFLayoutFieldProperties item)
+        public static bool EditProperties(DigitalForm form, IList<DigitalFormVariable> variables, Type type, DFLayoutFieldProperties item, bool readOnly)
         {
             var editor = new DynamicEditorForm(type);
+            editor.ReadOnly = readOnly;
             if (item is DFLayoutLookupFieldProperties)
             {
                 var appliesToType = DFUtils.FormEntityType(form);

+ 2 - 2
inabox.wpf/DynamicGrid/DynamicEditorForm/DynamicEditorForm.xaml.cs

@@ -140,7 +140,7 @@ public partial class DynamicEditorForm : ThemableChromelessWindow, IDynamicEdito
 
     private void Form_OnCancel()
     {
-        if (bChanged)
+        if (bChanged && !ReadOnly)
         {
             var result = MessageWindow.ShowYesNoCancel("Save Changes?", "Confirm");
             switch (result)
@@ -174,7 +174,7 @@ public partial class DynamicEditorForm : ThemableChromelessWindow, IDynamicEdito
 
     private void Window_Closing(object sender, CancelEventArgs e)
     {
-        if (bChanged && Result == null)
+        if (bChanged && !ReadOnly && Result == null)
         {
             var result = MessageWindow.ShowYesNoCancel("Save Changes?", "Confirm");
             switch (result)

+ 13 - 0
inabox.wpf/DynamicGrid/DynamicGridCommon.cs

@@ -111,6 +111,19 @@ public class DynamicGridOptions
 			}
 		}
 	}
+    private bool _viewRows;
+    public bool ViewRows
+	{
+		get => _viewRows || EditRows;
+		set
+		{
+			if(_viewRows != value)
+			{
+				_viewRows = value;
+				Changed();
+			}
+		}
+	}
     private bool _editRows;
     public bool EditRows
 	{

+ 72 - 8
inabox.wpf/DynamicGrid/Grids/BaseDynamicGrid.cs

@@ -169,7 +169,8 @@ public abstract class BaseDynamicGrid : ContentControl, IDynamicGridUIComponentP
 
     protected DynamicGridSettings Settings { get; set; }
 
-    
+    private static BitmapImage _pencil = Wpf.Resources.pencil.AsBitmapImage(Color.White);
+    private static BitmapImage _view = Wpf.Resources.view.AsBitmapImage(Color.White);
     public BaseDynamicGrid() : base()
     {
         UseWaitCursor = true;
@@ -229,7 +230,7 @@ public abstract class BaseDynamicGrid : ContentControl, IDynamicGridUIComponentP
         Add.Margin = new Thickness(0, 2, 2, 0);
         Add.Click += Add_Click;
 
-        Edit = CreateButton(Wpf.Resources.pencil.AsBitmapImage(Color.White));
+        Edit = CreateButton(_pencil);
         Edit.Margin = new Thickness(0, 2, 2, 0);
         Edit.Click += Edit_Click;
 
@@ -683,6 +684,8 @@ public abstract class BaseDynamicGrid : ContentControl, IDynamicGridUIComponentP
 
     private bool _hasLoadedOptions = false;
 
+    private event Action? _optionAction;
+
     protected virtual void OptionsChanged()
     {
         var reloadColumns = false;
@@ -693,9 +696,10 @@ public abstract class BaseDynamicGrid : ContentControl, IDynamicGridUIComponentP
         }
 
         Add.Visibility = Options.AddRows ? Visibility.Visible : Visibility.Collapsed;
-        Edit.Visibility = Options.EditRows ? Visibility.Visible : Visibility.Collapsed;
+        Edit.Visibility = Options.ViewRows ? Visibility.Visible : Visibility.Collapsed;
+        UpdateButton(Edit, Options.EditRows ? _pencil : _view, null);
 
-        EditSpacer.Visibility = Options.AddRows || Options.EditRows
+        EditSpacer.Visibility = Options.AddRows || Options.ViewRows
             ? Visibility.Visible
             : Visibility.Collapsed;
 
@@ -756,6 +760,8 @@ public abstract class BaseDynamicGrid : ContentControl, IDynamicGridUIComponentP
             reloadColumns = true;
         }
 
+        _optionAction?.Invoke();
+
         if(reloadColumns && IsReady)
         {
             Refresh(true, false);
@@ -879,7 +885,7 @@ public abstract class BaseDynamicGrid : ContentControl, IDynamicGridUIComponentP
         OnDoubleClick?.Invoke(sender, e);
         if (e.Handled)
             return;
-        if (Options.EditRows)
+        if (Options.ViewRows)
             DoEdit();
     }
 
@@ -1617,7 +1623,14 @@ public abstract class BaseDynamicGrid : ContentControl, IDynamicGridUIComponentP
     }
 
 
-    public Button AddButton(string? caption, ImageSource? image, string? tooltip, DynamicGridButtonClickEvent action, DynamicGridButtonPosition position = DynamicGridButtonPosition.Left)
+    public Button AddButton(
+        string? caption,
+        ImageSource? image,
+        string? tooltip,
+        DynamicGridButtonClickEvent action,
+        DynamicGridButtonPosition position = DynamicGridButtonPosition.Left,
+        Func<DynamicGridOptions, bool>? isVisible = null
+    )
     {
         var button = CreateButton(image, caption, tooltip);
         button.Margin = position == DynamicGridButtonPosition.Right
@@ -1628,6 +1641,14 @@ public abstract class BaseDynamicGrid : ContentControl, IDynamicGridUIComponentP
         button.Padding = !String.IsNullOrWhiteSpace(caption) ? new Thickness(5, 1, 5, 1) : new Thickness(1);
         button.Tag = action;
         button.Click += Button_Click;
+        if(isVisible is not null)
+        {
+            button.Visibility = isVisible(Options) ? Visibility.Visible : Visibility.Collapsed;
+            _optionAction += () =>
+            {
+                button.Visibility = isVisible(Options) ? Visibility.Visible : Visibility.Collapsed;
+            };
+        }
         if (position == DynamicGridButtonPosition.Right)
             RightButtonStack.Children.Add(button);
         else
@@ -1636,9 +1657,52 @@ public abstract class BaseDynamicGrid : ContentControl, IDynamicGridUIComponentP
         return button;
     }
 
-    public Button AddButton(string? caption, ImageSource? image, DynamicGridButtonClickEvent action, DynamicGridButtonPosition position = DynamicGridButtonPosition.Left)
+    public Button AddButton(
+        string? caption,
+        ImageSource? image,
+        DynamicGridButtonClickEvent action,
+        DynamicGridButtonPosition position = DynamicGridButtonPosition.Left,
+        Func<DynamicGridOptions, bool>? isVisible = null
+    )
     {
-        var result = AddButton(caption, image, null, action, position);
+        var result = AddButton(caption, image, null, action, position, isVisible: isVisible);
+        return result;
+    }
+    
+    /// <summary>
+    /// Adds a button that is only visible if this grid is editable (i.e., <c>Options.EditRows</c> is <see langword="true"/>)
+    /// </summary>
+    public Button AddEditButton(
+        string? caption,
+        ImageSource? image,
+        string? tooltip,
+        DynamicGridButtonClickEvent action,
+        DynamicGridButtonPosition position = DynamicGridButtonPosition.Left,
+        Func<DynamicGridOptions, bool>? isVisible = null
+    )
+    {
+        var result = AddButton(caption, image, tooltip, action, position,
+            isVisible: isVisible != null
+                ? (options => options.EditRows && isVisible(options))
+                : (options => options.EditRows));
+        return result;
+    }
+
+    /// <summary>
+    /// Adds a button that is only visible if this grid is editable (i.e., <c>Options.EditRows</c> is <see langword="true"/>)
+    /// </summary>
+    public Button AddEditButton(
+        string? caption,
+        ImageSource? image,
+        DynamicGridButtonClickEvent action,
+        DynamicGridButtonPosition position = DynamicGridButtonPosition.Left,
+        Func<DynamicGridOptions, bool>? isVisible = null
+    )
+    {
+        var result = AddButton(caption, image, null, action, position,
+            isVisible: isVisible != null
+                ? (options => options.EditRows && isVisible(options))
+                : (options => options.EditRows));
         return result;
     }
 

+ 1 - 0
inabox.wpf/DynamicGrid/Grids/DynamicDataGrid.cs

@@ -89,6 +89,7 @@ public class DynamicDataGrid<TEntity> : DynamicGrid<TEntity>, IDynamicDataGrid w
     {
         base.DoReconfigure(options);
 
+        options.ViewRows = true;
         if (Security.CanEdit<TEntity>())
         {
             options.AddRows = true;

+ 6 - 0
inabox.wpf/DynamicGrid/Grids/DynamicManyToManyGrid.cs

@@ -453,4 +453,10 @@ public class DynamicManyToManyGrid<TManyToMany, TThis> : DynamicGrid<TManyToMany
         }
         return true;
     }
+
+    protected override void BeforeLoad(IDynamicEditorForm form, TManyToMany[] items)
+    {
+        form.ReadOnly = form.ReadOnly || ReadOnly || !Security.CanEdit<TManyToMany>();
+        base.BeforeLoad(form, items);
+    }
 }

+ 7 - 0
inabox.wpf/DynamicGrid/Grids/DynamicOneToManyGrid.cs

@@ -61,6 +61,7 @@ public class DynamicOneToManyGrid<TOne, TMany> : DynamicGrid<TMany>,
 
         options.RecordCount = true;
         options.SelectColumns = true;
+        options.ViewRows = true;
 
         if (Security.CanEdit<TMany>() && !ReadOnly)
         {
@@ -216,6 +217,12 @@ public class DynamicOneToManyGrid<TOne, TMany> : DynamicGrid<TMany>,
 
     #region DynamicGrid
 
+    protected override void BeforeLoad(IDynamicEditorForm form, TMany[] items)
+    {
+        form.ReadOnly = form.ReadOnly || ReadOnly || !Security.CanEdit<TMany>();
+        base.BeforeLoad(form, items);
+    }
+
     protected virtual void OnDeleteItem(TMany item)
     {
         if (IsAutoEntity)

+ 2 - 2
inabox.wpf/DynamicGrid/Grids/IDynamicGrid.cs

@@ -75,9 +75,9 @@ public interface IBaseDynamicGrid
 
     void AddVisualFilter(string column, string value, FilterType filtertype = FilterType.Contains);
 
-    Button AddButton(string? caption, ImageSource? image, string? tooltip, DynamicGridButtonClickEvent action, DynamicGridButtonPosition position = DynamicGridButtonPosition.Left);
+    Button AddButton(string? caption, ImageSource? image, string? tooltip, DynamicGridButtonClickEvent action, DynamicGridButtonPosition position = DynamicGridButtonPosition.Left, Func<DynamicGridOptions, bool>? isVisible = null);
 
-    Button AddButton(string? caption, ImageSource? image, DynamicGridButtonClickEvent action, DynamicGridButtonPosition position = DynamicGridButtonPosition.Left);
+    Button AddButton(string? caption, ImageSource? image, DynamicGridButtonClickEvent action, DynamicGridButtonPosition position = DynamicGridButtonPosition.Left, Func<DynamicGridOptions, bool>? isVisible = null);
 
     void UpdateButton(Button button, ImageSource? image, string? text, string? tooltip = null);