This project is read-only.

Departmental Request Approval Example

Note: This example (DepartmentRequestApproval.cs) can be found in 'JetfireCoreExampleTests' project, which is part of the release download (V1.0.14 or higher).

In this example each department has a separate workspace where request workflows are stored (see Request Approval example for a discussion of Request workflow). The workspaces provide a firewall between departments not allowing members from one department to view another department's requests. Request workflows are approved when a user with the 'Approver' role, which is typically restricted to the department manager, executes the 'Approve' method of the request workflow. In the example below 'Joe' is assumed to be a manager.

workspace SALES workspace MANUFACTURING
User Access / Approver Access / Approver
Sam(sales) yes / no no / no
Joe (sales) yes / yes no / no
Carl(corporate) yes / no yes / no
Mary(manufacturing) no / no yes / no


Mary, who is in 'Manufacturing' has no access to the 'Sales' workspace; however Carl, who is in 'Coporate' has access to both both the 'Sales' and 'Manufacturing' workspaces.

The following Jetfire code shows how to create a users, roles and workspaces programmatically using Jetfire code. These workflow objects could also be created directly in C# code.
string createUserAndRoles =
  @"namespace test 
   {
      public workflow CreateUserAndRole 
      {
         Role approver = new Role(""Approver"");
         Role salesDept = new Role(""Sales"");
         Role manufacturingDept = new Role(""Manufacturing"");
         Role corporate = new Role(""Corporate"");
         User userSam = new User(""Sam"");
         User userJoe = new User(""Joe"");
         User userCarl = new User(""Carl"");
         User userMary = new User(""Mary"");
         workspace wsSales = new workspace(""Sales"");
         workspace wsManufacturing = new workspace(""Manufacturing"");
         // constructor
         public CreateUserAndRole()
         {
            userSam.AddRole(salesDept);
            userJoe.AddRole(salesDept);
            userJoe.AddRole(approver);
            userCarl.AddRole(corporate);
            userMary.AddRole(manufacturingDept);
            workflow.AddAccessRole(wsSales, salesDept);
            workflow.AddAccessRole(wsSales, corporate);
            workflow.AddAccessRole(wsManufacturing, manufacturingDept);
            workflow.AddAccessRole(wsManufacturing, corporate);
         }
      }
   }";

The Request workflow is unchanged from the Request Approval example.

The test is broken into the following sections:
  • Login in as Guest - Create the users and workflow classes
  • Login in as Sam - Make the Request
  • Login as Mary - Attempt to view the request
  • Login as Carl - Attempt to view and approve the request
  • Login as Joe - Approve the Request

public void DepartmentRequestApprovalTest()
{
    #region Login in as Guest - Create the users and workflow classes
    //
    //  Login in as 'Guest'.
    //
    TjGuid guidCreationWF;
    using (LinqStartObjects start = JetfireTest.NewNexusServer(
        "MyStorage",     // A handle for the memory based object storage
        TjServerStorageType.MemoryLinq,
        TjStorageCommand.ClearStorage  // deletes any existing objects
        ))
    {
        TjNexus nexus = start.ClientNexus;
        //
        //  Create the user 'Joe'.
        //  Parse source code and create the Jetfire executable code expressions, 
        //  get the workflow class 'CreateUserAndRole',
        //  then instantiate a new workflow object.
        //
        nexus.ParseServer(createUserAndRoles);
        TjWorkflowClass createClass = nexus.FindClass<TjWorkflowClass>(
            "test",
            "CreateUserAndRole");
        // the constructor automatically executes
        TjWorkflow creationWF = createClass.NewWorkflow();
        guidCreationWF = creationWF.JetfireGuid;
        //
        // Create the 'Request' workflow class
        //
        nexus.ParseServer(requestWorkflow);
        JetfireTest.AssertNoIncidents(nexus);
    }
    #endregion 
    #region Login in as Sam - Make the Request
    //
    // Login as Sam.   Make the Request
    //
    TjGuid guidDayOffRequest;
    using (LinqStartObjects start = JetfireTest.NewNexusServer(
       "MyStorage",     // A handle for the memory based object storage
       TjServerStorageType.MemoryLinq,
       TjStorageCommand.ReUseExisingStorage,
       "Sam"))
    {
        TjNexus nexus = start.ClientNexus;
        TjWorkflow creationWF = nexus.Cache.GetUnit<TjWorkflow>(guidCreationWF);

        TjWorkspace wsSales = creationWF.Get<TjWorkspace>("wsSales");
        TjWorkflowClass requestClass = nexus.FindClass<TjWorkflowClass>("test", "Request");
        //
        // Create the Request workflow
        //
        TjWorkflow dayOffRequestWF = requestClass.New<TjWorkflow>(
            wsSales, 
            "Day Off", 
            "Boss, I'd like to take next Tuesday off.  Hope it is okay with you?");
        guidDayOffRequest = dayOffRequestWF.JetfireGuid;
        //
        // Check to see if the workflow was created properly.
        //
        Assert.AreEqual("Day Off", dayOffRequestWF.Get<string>("Subject"));
        //
        //  Get the method Approve and check its access modifier.
        //  Can't self approve becuse the access modifier is private.
        //
        Assert.AreEqual(
            TjAccessModifierType.Private,
            dayOffRequestWF.DynamicAccessModifier("Approve"));
        //
        // Now the 'Approve' method is private 
        // (because the Guest user doesn't have the role "Approver").  
        // The human interface can prevent
        // the 'Approve' method from being executed.   If the method is executed
        // then an exception will occur.
        //
        JetfireTest.AssertNoIncidents(nexus);
    }
    #endregion
    #region Login as Mary - Attempt to view the request
    //
    // Login as Mary.   
    // It should not be possible to view the request.
    //
    using (LinqStartObjects start = JetfireTest.NewNexusServer(
       "MyStorage",     // A handle for the memory based object storage
       TjServerStorageType.MemoryLinq,
       TjStorageCommand.ReUseExisingStorage,
       "Mary"))
    {
        TjNexus nexus = start.ClientNexus;
        Assert.AreEqual("Mary", nexus.UserLogin.Name);

        TjWorkflow dayOffRequestWF;
        //
        // Mary can't get the request because
        // she doesn't have access to "Sales" workspace.
        // Mary has only a single role giving access
        // to the 'Manufacturing' workspace.
        //
        bool isFound = nexus.Cache.TryGetStorageUnit<TjWorkflow>(guidDayOffRequest, out dayOffRequestWF);
        Assert.IsFalse(isFound);

        JetfireTest.AssertNoIncidents(nexus);
    }
    #endregion
    #region Login as Carl - Attempt to view and approve the request.
    //
    // Login as Carl who is in corporate.     
    // It should be possible to view the request.
    // Carl does not have the 'Approver' role so although
    // he can view the request he can 'Approve' it.
    //
    using (LinqStartObjects start = JetfireTest.NewNexusServer(
       "MyStorage",     // A handle for the memory based object storage
       TjServerStorageType.MemoryLinq,
       TjStorageCommand.ReUseExisingStorage,
       "Carl"))
    {
        TjNexus nexus = start.ClientNexus;
        Assert.AreEqual("Carl", nexus.UserLogin.Name);

        TjWorkflow dayOffRequestWF;
        //
        // Get the request - It will be in the cache.
        //
        bool isFoundReqest = nexus.Cache.TryGetStorageUnit<TjWorkflow>(guidDayOffRequest, out dayOffRequestWF);
        Assert.IsTrue(isFoundReqest);
        //
        // Carl can't approve the request because he does not have the 'Approver' role.
        //
        Assert.AreEqual(
            TjAccessModifierType.Private,
            dayOffRequestWF.DynamicAccessModifier("Approve"));

        JetfireTest.AssertNoIncidents(nexus);
    }
    #endregion
    #region Login as Joe - Approve the Request
    //
    // Logon as Joe who has the "Approve" role.
    //
    using (LinqStartObjects start = JetfireTest.NewNexusServer(
       "MyStorage",     // A handle for the memory based object storage
       TjServerStorageType.MemoryLinq,
       TjStorageCommand.ReUseExisingStorage,
       "Joe"))
    {
        TjNexus nexus = start.ClientNexus;
        Assert.AreEqual("Joe", nexus.UserLogin.Name);
        //
        // Get the request - It will be in the cache.
        //
        TjWorkflow dayOffRequestWF = nexus.Cache.GetUnit<TjWorkflow>(guidDayOffRequest);
        //
        //  Get the method Approve and check its access modifier.
        //
        Assert.AreEqual(TjAccessModifierType.Public, dayOffRequestWF.DynamicAccessModifier("Approve"));
        //
        //   Approve the request.
        //
        dayOffRequestWF.Execute("Approve");
        Assert.AreEqual("approved", dayOffRequestWF.Get<string>("Status"));

        JetfireTest.AssertNoIncidents(nexus);
    }
    #endregion
}
#endregion

Last edited Apr 3, 2009 at 10:10 PM by JohnHansen, version 30

Comments

No comments yet.