“One step at a time is all it takes to get you there.”
— Emily Dickinson
Last time, we built out the majority of the Catalog Item that we are creating for the purpose of requesting a new Service Account. All that is left for us to do now is to create the process that will fulfill the request once it has been made. Because our intent is to create a single Catalog Item for any type of account, and each type of account will have its own unique account creation process, we will want to build a generic workflow of some kind that will look at the type requested and then launch the appropriate fulfillment process based on that type. Before we jump in and start creating things, though, we will need to come up with a strategy that will facilitate combining a generic outer process with a type-specific inner process.
Assuming that each type will have its own Subflow unique to the type, we will want to store a link to that Subflow on the type record that we created earlier. This way, the generic process can look at the type requested, read the record for that type, and then grab the link to the Subflow so that it can be launched. To make that work, we will need to devise some kind of standard for the Subflow in terms of inputs and outputs so that the generic process can consistently communicate with any given fulfillment Subflow. For input, the Requested Item record should suffice, but the outputs will depend on how much work will be delegated to the Subflow and how much will be handled by the primary process.
In addition to the creation of the account, our process should also perform a number of other tasks such as notifying the user of the account’s creation, sending them the assigned password, creating the record in the accounts table, and closing the request. Since everything except the account creation is universal, our Subflow should be limited to just the steps necessary to create the account, and all other activities should be handled by the primary request. For that to work, the Subflow will need to return sufficient data to the primary process so that it can successfully complete all of the other work. We also have to allow for the possibility that the account could not be created for whatever reason, and that information will need to be communicated back as well. This may change over time as we get into the weeds, but for now, I think that the following should be able to handle everything needed.
- Success flag
- Failure Reason
- Account ID
- Account Password
- Account Owner Instructions
Since we will need a working Subflow to test out the primary process, it might be wise to start with that first, and then circle back to the primary process once we have a working Subflow to call. Before we do that, though, we need to figure out a way to generate a password. If you search through all of the Script Includes bundled with the product for anything that has the word password in the name, you can find a lot of password generation scripts already out there. Unfortunately, these are all in the global scope, and their access is limited to the global scope, so we can’t call any of these from our Scoped Application. If you search the Internet for password generation scripts, you can find even more, but most of these are much more sophisticated that I was looking for. Ultimately, I borrowed a few things from here and there and came up with a simple Action that had no inputs, one output, and a single script execution step with the following logic.
(function execute(inputs, outputs) {
var upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var lower = 'abcdefghijklmnopqrstuvwxyz';
var number = '0123456789';
var special = '!@#$%&*()_+<>[].~';
var source = upper + lower + number + special;
outputs.password = '';
while (outputs.password.length < 32) {
outputs.password += source.charAt(Math.floor(Math.random() * (source.length + 1)));
}
})(inputs, outputs);
This does not guarantee that you will have at least one of each category of character, but with 32 positions, the chances are still pretty good that you will. I ran it a few times to see, and I didn’t think that the results looked all that bad.
- dPoxtBDUqaCtFaH2knI]XI0Ts*#1rKyT
- xnDRzngKOMy~py8xK[xV]2S2CTkh]RWv
- knUHn*0WJ4H_Ww90gq[2TqJmKKb0Xu9v
- OcWe4TKQN#0[RM1wj$p$(#_Sp.~CVTiM
- >wEE!CbrFGwYccWb#H>+6pyEpZwjcJ%A
Each one seems to have a little bit of everything, so I think it is good enough for what we are trying to do here. So now that we have that in place, we can start working on our Subflow. Unfortunately, you can build a Flow in the App Engine Studio, but not a Subflow (or at least if you can, I cannot figure out how to do that). So, to build out our Subflow, we will have to jump into the old Flow Designer. To create a new Subflow, we select New -> Subflow up in the upper right-hand corner and give it a name of ServiceNow Service Account Creation. The first thing that we will do is create all of the inputs and outputs listed above.
Once we have our inputs and outputs defined, we can jump down in the Actions section and start adding steps to the flow. The first thing that we will want to do is to grab the requested account ID from the Requested Item, so we will select Get Catalog Variables from the list of available actions and drag in the Requested Item pill from the inputs.
For the template, we select our new Service Account Catalog Item, and once we do that, all of the variables defined for that item appear in the Available list, from which we can select account_id. This will give us an account_id pill which we can use in future steps.
The next thing that we will want to do is to find out if the requested account ID is already in use. We can do that by reading the sys_user table, so for our next step we select Look Up Record from the list of actions and select the User table from the list of tables.
Our only condition for this is that the User ID is the requested account ID, which we again drag over from the inputs. Once we attempt to fetch the record, the next thing that we will want to do is to check and see if a record was returned, so for our next step we will select If from the Flow Logic options.
If a record was returned with the requested account ID, then we want to stop the process and return a failure message back to the calling Flow. To do that, we select Assign Subflow Outputs for our next step and fill in the values for the output fields.
Hopefully, the account will not already exist, so we will want to put all of our other steps under an Else condition. The first step under our Else condition will be to generate the password using the Action that we created earlier.
Once we generate the password we have enough data to create the user record, so for our next step we will select Create Record from the list of actions and populate the record with data pills from the input and preceding processes.
Once the record has been created, we need to report back to the calling Flow, so once again we will select Assign Subflow Outputs and populate the appropriate fields.
Now all we need to do is to Save and Publish our Subflow and we will have one example to use for testing. We will still need to create one more for our other example use case, but we won’t need to do that just yet. Let’s see if we can make all of this work with our first example before we run off and build another.
At this point, it would be good to test this out to make sure that it all works, but to do that we will need a valid Requested Item record to send in as input, and since we have not completed our Catalog Item, we can’t really do that just yet. Let’s build our primary Flow first, and then update the Catalog Item to point to that Flow, and then we can publish the item and do some testing. To build the Flow, we can go back into the App Engine Studio, so let’s dive into that next time out.