PIAB with databinding Windows Forms controls

Topics: Policy Injection Application Block, Security Application Block
Oct 17, 2007 at 2:15 PM
Edited Oct 17, 2007 at 2:43 PM
Hello,

I'm playing around with PIAB and Security (and actually Exception, Logging & Caching application blocks, which seem to work together well).
I'm trying to implement a windows forms app with databinding to windows forms controls (textboxes for instance).
I want to use SAB for authorization of updating business objects properties.
For Example A business object :

public class Person : IPerson, INotifyPropertyChanged
{
private string name;
private string phone;
private int age;
private EntityStateEnum entityState;

public EntityStateEnum EntityState
{
get { return entityState; }
private set { entityState = value; }
}

public string Name
{
get { return name; }
[AuthorizationCallHandler("Manager")]
set
{
if (value != name)
{
this.DataStateChanged(
EntityStateEnum.Modified,
"Name");
}

name = value;
}
}

public string Phone
{
get { return phone; }
[AuthorizationCallHandler("Manager")]
set
{
if (value != phone)
{
this.DataStateChanged(
EntityStateEnum.Modified,
"Phone");
}

phone = value;
}
}

public int Age
{
get { return age; }
[AuthorizationCallHandler("Manager")]
set
{
if (value != age)
{
this.DataStateChanged(
EntityStateEnum.Modified,
"Age");
}

age = value;
}
}

/// <summary>
/// Initializes a new instance of the Person class.
/// </summary>
public Person(string name, int age, string phone)
{
this.Phone = phone;
this.Age = age;
this.Name = name;
}

private void DataStateChanged(EntityStateEnum dataState, string propertyName)
{
// Raise the event
if (PropertyChanged != null &&
propertyName != null)
{
PropertyChanged(this, new
PropertyChangedEventArgs(propertyName));
}

// If the state is deleted, mark it as deleted
if (dataState == EntityStateEnum.Deleted)
{
this.EntityState = dataState;
}

if (this.EntityState == EntityStateEnum.Unchanged)
{
this.EntityState = dataState;
}
}

public event PropertyChangedEventHandler PropertyChanged;

}

Notice that setters are decorated with AuthorizationCallHandler for "Manager" rule.

Now I wanted to create list of these objects and make it source of a bindingdatasource in a windows form.
Each item in the list is created with policy injection.

public class PersonList : BindingList<IPerson>
{
public PersonList()
{
// just for demo, add 2 person objects

IPerson person = PolicyInjection.Create<Person, IPerson>(new object[] { "aaa", 22, "4444" });
IPerson person2 = PolicyInjection.Create<Person, IPerson>(new object[] { "bbb", 33, "5555" });

this.Add(person);
this.Add(person2);

}
}

Binding the list to form controls work ok, data is shown.

My problem is with updating as follows:

If you are in "Manager" rule, no problem.

If you are not in "Manager" rule, you can see the data (ok), but if you try to update, you get stuck in the textbox control since binding tries to validate and update underlying data, but policy injection prevents this. As far as I've seen no unauthorized exception is thrown.

Is it possible to notify binding source to cancel edit when policy injection or SAB prevents an update?

Is it possible to solve this by making TextBox control "awared" of the policy enforced and make it read only for example? Although I understand that PIAB is an extention lying "above" your code without changing your logic.

Actually it's a general question of whether PIAB can be helpfull with enabling/disabling behaviour of windows forms controls? One option it to extend those controls with methods that are "awared" of policy, for instance:

Prevent a windows form from showing if not in required "Manager" rule:

public interface IMyForm
{
void ShowForm();
}

[AuthorizationCallHandler("Manager")]
public partial class Form2 : Form, IMyForm
{
public Form2()
{
InitializeComponent();
}

public void ShowForm()
{
this.Show();
}
}

Calling this work OK, If you are not in "Manager" rule you'll get unauthorized exception:

IMyForm frm = PolicyInjection.Create<Form2, IMyForm>();
((Form2)frm).ShowForm();

Calling this does not take into account the policy (since Show() is not intercepted):

IMyForm frm = PolicyInjection.Create<Form2, IMyForm>();
((Form2)frm).Show();

Any suggestions or insights?