Automatic End to End Authorization (Part 2)


In my previous post, I talked about the importance of an end to end authorization system. I had an open source project here a while ago for this purpose. I describe the framework with some example here. An old saying says that a piece of code talk more than 1000 words:

Below is a sample class annotated with different authentication attributes.

<pre>
[Grant(Roles = new[] { "Everyone" }, Permission = Permission.View)]
[Grant(Roles = new[] { "QLDAdmin", "NSWAdmin" }, Permission = Permission.View | Permission.Edit | Permission.Create)]
[Grant(Roles = new[] { "Deleter" }, Permission = Permission.Delete)]
[Grant(Roles = new[] { "God" }, Permission = Permission.View | Permission.Own)]
[Deny(Roles = new[] { "NSWAdmin" }, Permission = Permission.Edit)]
[AuthorizationCustom(CustomType = typeof(TestObject), Method = "OnlyQld")]
public class TestObject
{
[Grant(Roles = new[] { "Everyone" }, Permission = Permission.View)]
[Deny(Roles = new[] { "God" }, Permission = Permission.View)]
public int YouCanSeeMe { get; set; }

[Grant(Roles = new[] { "Everyone" }, Permission = Permission.Edit)]
[Deny(Roles = new[] { "God" }, Permission = Permission.Edit | Permission.View)]
public string YouCanEditMe { get; set; }

[Deny(Roles = new[] { "Everyone" }, Permission = Permission.View)]
public string YouCanNotSeeMe { get; set; }

[Deny(Roles = new[] { "Everyone" }, Permission = Permission.Edit)]
public string YouCanSeeMeButNotEditMe { get; set; }

[Grant(Roles = new[] { "*" }, Permission = Permission.View)]
public string EverybodyCanSeeMe { get; set; }

public string[] States { get; set; }

public static Permission OnlyQld( IPrincipal pri, object instance )
{
var user = pri as TestUser;
if (user.Roles.Any(r => r.Contains("QLD"))
&&
(((TestObject)instance).States != null && ((TestObject)instance).States.Contains("QLD"))
)
return Permission.All;
return Permission.None;
}
}

</pre>

Next step is to check the permission for them in different scenarios:

<pre>[TestMethod()]
public void GetObjectLevelPremissionTest()
{
IMetadataClassProvider metadataProvider = new SelfMetadata();
var to = new TestObject();
var everyone = new TestUser() { Roles = new[] { "Everyone" } };
var god = new TestUser() { Roles = new[] { "God" } };
var adminNsw = new TestUser() { Roles = new[] { "NSWAdmin" } };
var adminQld = new TestUser() { Roles = new[] { "QLDAdmin" } };
var userWA = new TestUser() { Roles = new[] { "WAuser" } };
var userQLD = new TestUser() { Roles = new[] { "QLDuser" } };

var actual = PermissionHelper.GetObjectLevelPremission(metadataProvider, typeof(TestObject), to, everyone);
Assert.AreEqual(true, actual.Key.HasFlag(Permission.View));
Assert.AreEqual(false, actual.Key.HasFlag(Permission.Edit));
Assert.AreEqual(false, actual.Key.HasFlag(Permission.Create));

actual = PermissionHelper.GetObjectLevelPremission(metadataProvider, typeof(TestObject), to, god);
Assert.AreEqual(true, actual.Key.HasFlag(Permission.Own));

actual = PermissionHelper.GetObjectLevelPremission(metadataProvider, typeof(TestObject), to, adminNsw);
Assert.AreEqual(false, actual.Key.HasFlag(Permission.Edit));
Assert.AreEqual(true, actual.Key.HasFlag(Permission.View));

actual = PermissionHelper.GetObjectLevelPremission(metadataProvider, typeof(TestObject), to, adminQld);
Assert.AreEqual(true, actual.Key.HasFlag(Permission.Edit));
Assert.AreEqual(true, actual.Key.HasFlag(Permission.View));

to = new TestObject() { States = new[] { "QLD", "NSW" } };
actual = PermissionHelper.GetObjectLevelPremission(metadataProvider, typeof(TestObject), to, userWA);
Assert.AreEqual(false, actual.Key.HasFlag(Permission.View));

actual = PermissionHelper.GetObjectLevelPremission(metadataProvider, typeof(TestObject), to, userQLD);
Assert.AreEqual(true, actual.Key.HasFlag(Permission.View));
Assert.AreEqual(true, actual.Key.HasFlag(Permission.Create));

actual = PermissionHelper.GetObjectLevelPremission(metadataProvider, typeof(TestObject), to, adminQld);
Assert.AreEqual(true, actual.Key.HasFlag(Permission.Delete));
Assert.AreEqual(true, actual.Key.HasFlag(Permission.View));
}</pre>

Above code tests the permissions at the object level. We can get permissions at property level also in an array:

<pre>[TestMethod()]
public void GetPropertyLevelPremissionsTest()
{
IMetadataClassProvider metadataProvider = new SelfMetadata();
var to = new TestObject();
var everyone = new TestUser() { Roles = new[] { "Everyone" } };
var god = new TestUser() { Roles = new[] { "God" } };
var anon = new TestUser() { Roles = new string[0] };

var parent = PermissionHelper.GetObjectLevelPremission(metadataProvider, typeof(TestObject), to, everyone);
var actual = PermissionHelper.GetPropertyLevelPremissions(metadataProvider, parent, typeof(TestObject), to, everyone);
Assert.AreEqual(true, actual["YouCanSeeMe"].Key.HasFlag(Permission.View));
Assert.AreEqual(false, actual["YouCanSeeMe"].Key.HasFlag(Permission.Edit));
Assert.AreEqual(false, actual["YouCanSeeMe"].Key.HasFlag(Permission.Create));
Assert.AreEqual(false, actual["YouCanNotSeeMe"].Key.HasFlag(Permission.View));
Assert.AreEqual(true, actual["YouCanSeeMeButNotEditMe"].Key.HasFlag(Permission.View));
Assert.AreEqual(false, actual["YouCanSeeMeButNotEditMe"].Key.HasFlag(Permission.Edit));

parent = PermissionHelper.GetObjectLevelPremission(metadataProvider, typeof(TestObject), to, god);
actual = PermissionHelper.GetPropertyLevelPremissions(metadataProvider, parent, typeof(TestObject), to, god);
Assert.AreEqual(false, actual["YouCanSeeMe"].Key.HasFlag(Permission.View));
Assert.AreEqual(false, actual["YouCanEditMe"].Key.HasFlag(Permission.View));
Assert.AreEqual(false, actual["YouCanEditMe"].Key.HasFlag(Permission.Edit));
Assert.AreEqual(false, actual.ContainsKey("YouCanNotSeeMe"));

parent = null;
actual = PermissionHelper.GetPropertyLevelPremissions(metadataProvider, parent, typeof(TestObject), to, everyone);
Assert.AreEqual(true, actual["YouCanSeeMe"].Key.HasFlag(Permission.View));

parent = PermissionHelper.GetObjectLevelPremission(metadataProvider, typeof(TestObject), to, anon);
actual = PermissionHelper.GetPropertyLevelPremissions(metadataProvider, parent, typeof(TestObject), to, anon);
Assert.AreEqual(true, actual["EverybodyCanSeeMe"].Key.HasFlag(Permission.View));
}</pre>

Don’t get too excited. So far we haven’t seen much. The real beauty is when we get to automatically filter collections and set the client view visibility using the framework with one line of code.

To be continued…

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: