This project is read-only.

Request Approval Example

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

In Jetfire methods are equivalent to commands and properties to information. It is desirable to control when commands are allowed to execute and when information can be viewed or changed. To accomplish this Jetfire can use the 'states' construct or the 'access' construct or a combination of the two (see Dynamic Access Modifiers. This example focuses on the 'access' programming construct using roles.

With 'access' construct access modifiers can be dynamic. That is a method's or property's access modifier (whether it is private or public) can be changed programmatically). The 'access' construct can use roles (this example) or the value of a boolean property (basket example).

In this example a 'Request' workflow is created. The 'Approve'
method(command) can only be executed by a user with the role of "Approver".

User Guest Joe
Approve() private public


This test is very simple having only a single command to "Approve" the request. In the advanced version of this test the example is extended further to introduce states and a "Decline" command.

The following Jetfire code shows how to create a user programatically.
string createUserAndRoles =
  @"namespace test 
   {
      public workflow CreateUserAndRole 
      {
         Role role;
         User user;
         // constructor
         public CreateUserAndRole()
         {
            role = new Role(""Approver"");
            user = new User(""Joe"");
            user.AddRole(role);
         }
      }
   }";


The following is a very simple Request workflow class. Requests are created, which in turn can be approved. This example does not demonstrate how to 'Decline' requests. Each 'Request' is an instance of the Request workflow class.
Note: Once a "Request" workflow object is created it will remain in the system until is explicitly deleted or the database is deleted.
string requestWorkflow =
    @"
    namespace test
    {
        // This workflow can only approve requests.
        // The next example shows a more complete solution.
       public workflow Request
       {
          // Constructor
          public Request(string requestName, string requestDetails)
          {
             // use the built in description properties to store extra information.
            this.Subject = requestName;
            this.ToolTip = requestDetails;
          }
          string status = ""pending"";
          public void Approve()
            : access(""Approver"")
          {
             status = ""approved"";
          }
          public string Status
          {
             get{ return status;}
          }                  
       }
    }
    ";

The method "Approve" is 'public' like any other method, provided that the logged in user has a role named 'Approver'.
If the user does not have this role then the method will be private.
Note: A Role and User are just workflow objects in Jetfire. They have some first class attributes; however they can be treated like any other workflow.
 public void Approve()
          : access(""Approver"")
 {
       status = ""approved"";
 }


The following C# test code demonstrates how to execute the Jetfire create user and 'Request' workflow class.
[TestMethod]
public void Access_ApprovalMethod()
{
    //
    //  Login in as 'Guest'.
    //
    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 createUserAndRole = createClass.NewWorkflow(); 
    //
    // Create the 'Request' workflow class
    //
    nexus.ParseServer(requestWorkflow);
    TjWorkflowClass requestClass = nexus.FindClass<TjWorkflowClass>("test", "Request");
    TjParameter[] parameters = TjParameter.ConvertToArray(
        nexus, 
        "Day Off", 
        "Boss, I'd like to take next Tuesday off.  Hope it is okay with you?");
    TjWorkflow dayOffRequest = requestClass.NewWorkflow(parameters);
    string guid = dayOffRequest.JetfireGuid.GuidValue;
    //
    // Check to see if the workflow was created properly.
    //
    Assert.AreEqual("Day Off", dayOffRequest.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, 
        dayOffRequest.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);
    start.Transport.Dispose();
    //
    // Logon as Joe who has the "Approve" role.
    //
    LinqStartObjects start2 = JetfireTest.NewNexusServer(
       "MyStorage",     // A handle for the memory based object storage
       TjServerStorageType.MemoryLinq,
       TjStorageCommand.ReUseExisingStorage,      
       "Joe");
    TjNexus nexus2 = start2.ClientNexus;
    Assert.AreEqual("Joe", nexus2.UserLogin.Name);
    //
    // Get the request - It will be in the cache.
    //
    TjWorkflow request = nexus2.Cache.GetUnit<TjWorkflow>(new TjGuid(guid));
    //
    //  Get the method Approve and check its access modifier.
    //
    Assert.AreEqual(TjAccessModifierType.Public, request.DynamicAccessModifier("Approve"));
    //
    //   Approve the request.
    //
    request.Execute("Approve");
    Assert.AreEqual("approved", request.Get<string>("Status"));
    
    JetfireTest.AssertNoIncidents(nexus2);
    start2.Transport.Dispose();
}

Last edited Feb 24, 2009 at 1:33 PM by JohnHansen, version 16

Comments

No comments yet.