Stumbling Through

Join me as I stumble, bumble and fumble my way through some new developer technologies. We'll laugh, we'll cry, there may be a mouse tossed through a monitor, but in the end we will all hopefully learn something.
in

Stumbling Through: K2 Blackpearl Programmability

Technorati Tags: ,,

While doing a little requirements gathering for a workflow project that will be leveraging the K2 Blackpearl product, I came across a few requirements that were not features we'd get 'out of the box' in Blackpearl.  Specifically, the project required a stand-alone user role manager outside of the one provided within the K2 workspace and an enhanced task list containing features that do not exist in the default task list web part. 

I am going to start out by discussing how to leverage Blackpearl's management API to accomplish at least part of a custom user role manager.  The goal here is to provide a site where authorized users can see all of the workflow roles defined for workflows, and add users from Active Directory to those roles.  We'll need to be able to add new roles, rename roles, and remove users from roles as well.  These roles can be used by workflow processes to assign tasks to groups of users, so they appear on the task list for every user belonging to the group until one of the users opens the task.  The reason for using these roles instead of Active Directory groups is that, ostensibly, you can open up the role management to end users instead of relying on network administrators to maintain your Active Directory groups.  While Blackpearl provides an interface for maintaining these roles out of the box, it currently resides within their 'Workspace' which has a ton of other functionality that we'd like to insulate our end users from.

So, where do we start?  Let's create a basic C# ASP.NET application in Visual Studio, and make a reference to the following .NET assemblies:

SourceCode.Security.UserRoleManager.Management

SourceCode.Workflow.Management

These assemblies are inter-related, and together provide the API for maintaining workflow roles.  The core class in this solution will be the 'UserRoleManager', which is used to query and manipulate the blackpearl environment.  In order for it to work, though, we need to connect it to our workflow server.  This will require a connection string to your workflow server, which is easily obtained via the object browser (Select the 'Change Server' option from the 'Environment' sub menu and you'll get your current connection string).  By the way, all of this code is going to be going into the 'Page_Load' event of our default page - I've added only a grid view (named GridView1) to the page which we'll use to see our output from our API calls.  Here is the logic for instantiating the user role manager API:

UserRoleManager managerAPI = new UserRoleManager();

// Connect to environment

managerAPI.Connection = managerAPI.CreateConnection();

managerAPI.Connection.Open("[host server connection string here, can get it from object browser]");

// END connect to environment

Now we are connected to our environment, and yes, in a real-world scenario you'd want to wrap this in a try-catch with a finally block to close the connection, just like you would with any data connection.  I'm just a lazy blogger and I'm not gonna write all that too.  Now the API becomes very straight-forward to use.  I want to first put all of the existing roles into our grid view, so I will simply write this:

// List all roles

Role[] roles = managerAPI.GetRoles();

this.GridView1.DataSource = roles;

this.GridView1.DataBind();

// END List all roles

Executing this, you should see all of the roles you have previously defined appear in your grid view.  Doesn't get any more straight forward than that... updating roles is just as intuitive as well.  To update the description of one of the roles we've just retrieved (we'll use the first role retrieved for simplicity sake), simply follow this logic:

// Append a '7' to the first role's description (update test)

Role updateRole = roles[0];

updateRole.Description += "7";

managerAPI.UpdateRole(updateRole);

// END Append a '7' to the first role's description (update test)

Now not everything is all pretty and nice with the user role manager API, there is a bit of complexity to maintaining the users of each role that feels quite over the top.  I was expecting users to be a child collection of each role, but that was not the case.  Users are made available from the Role object via the 'GetData' method, which returns some simple XML containing role information, users, groups and smart objects belonging to this role.  This same XML schema needs to be followed whenever you want to add/update role users vial the 'LoadData' method.  Here is a quick example of the code required to add myself to a new role named 'Test':

// Add a new role

Role newRole = new Role("Test");

newRole.LoadData("<role name=\"" + newRole.Name + "" guid=\"" + newRole.Guid + "\" description=\"\" isdynamic=\"false\"><include><users><user name=\"K2:Domain\\user\" /></users><groups /><smartobjects /></include><exclude><users /><groups /><smartobjects /></exclude></role>");

managerAPI.CreateRole(newRole);

// END add new role

Pretty weird, huh?  Though it does allow for a bit of flexibility, particularly in using smart objects to populate roles (a topic for another day), I prefer making children as properties of the parent class for the sake of readability.  Ah well, it may just be a coding style conflict.  Never the less, it all works as advertised and in learning this it makes the visual elements of a custom user role manager the most complicated part of development; the logic to process the user's requests will be a snap.

Comments

Assissotom said:

Very good site! I like it! Thanks!
# January 17, 2008 5:09 AM
Leave a Comment

(required) 

(required) 

(optional)

(required)