Automatic End to End Authorization (Part 3)


I promised to show you how does the SAF framework really do the magic. I changed my test model from my last post a little bit so I post it back again here:

<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)]
[Deny(Roles = new[] { "QLDMan" }, Permission = Permission.All)]
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 null;
}
}</pre>

Note that the Permission for the custom authorization method is nullable this time. It actually won’t work if the return type is not nullable.

Now the magic comes:

  1. Filter what user should not see automatically using FilterAuthorized() extension method.
  2. Send authorization tokens to client. Client can use AuthorizationToken.Visible or AuthorizationToken.Editable methods to bind view parts to data.

Below is an example case for more clarity:

<pre>[TestMethod()]
public void FilterAuthorizedTest()
{
IMetadataClassProvider sm = new SelfMetadata();
var everyone = new TestUser() { Roles = new[] { "Everyone" } };
var qldMan = new TestUser() { Roles = new[] { "QLDMan" } };

var coll = new[]
{
new TestObject() {YouCanSeeMe = 0, States = new[] {"QLD", "NSW"}},
new TestObject() {YouCanSeeMe = 1},
new TestObject() {YouCanSeeMe = 2, YouCanNotSeeMe = "a", States = new[] {"QLD"}},
new TestObject() {YouCanSeeMe = 3},
new TestObject() {YouCanSeeMe = 4, YouCanNotSeeMe = "b"}
};
var filtered = coll.FilterAuthorized(sm, everyone).ToList();
Assert.AreEqual(5, filtered.Count());

filtered = coll.FilterAuthorized(sm, qldMan).ToList();
Assert.AreEqual(2, filtered.Count());
}</pre>

The framework auto-magically cares about what user can see and what he can’t see.

In case you were not following me, here is the link to SAF Framework.

The major hole here is that the framework does not scrap properties that are not available to user at this stage. This should be a quick fix once I get some more time. Feel free, if you like to contribute. The architecture is quiet extensible and easy to understand.

Advertisement

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 )

Facebook photo

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

Connecting to %s

%d bloggers like this: