Here is how you can solve the "Four Eyes" problem with the new events feature in the API. First, I should define the Four Eyes so we are all on the same page.
The Four Eyes Problem:
Anyone on the Engineering group can change the lifecycle state of a file from "Work In Progress" to "For Review". Any engineer can also change the lifecycle state from "For Review" to "Released". However, you don't want the same person to do both these transitions for a given file. In other words, you want "four eyes" to see the file before it gets released.
Using the default Vault features, you can't solve the problem. But with events, you can. By hooking to the UpdateFileLifecycleStateEvents event, you can check the file history and add a restriction if you detect only "two eyes" on the file.
I was going to just paste the code in-line with this post, but it turned out to be more code than I expected. This is one of those things that the human brain has no problem with, but it takes a huge amount of work to put it into computer terms. I can't complain though since that's how I stay employed.
Aside from the large amount of code, there are a few other ugly, yet unavoidable, aspects to this solution.
- Redundant API calls - It would be nice to save off the reviewState and releaseState LfCycDef objects once we look them up. We can't do that because we can't assume we are communicating with the same server or vault between events. So, we are forced to look up the LfCycDef objects each time.
- Requires consecutive versions - There is no easy way to pinpoint which version is the one with the lifecycle state change. We are forced to order all the versions and cycle through the set. We compare version N with version N-1 and see if the lifecycle state is different. If a purge creates gaps in the version history, it may be impossible to figure out who changed the state on the file.
- File.FileLfCyc.LfCycStateId and File.FileLfCyc.LfCycStateName - This one tricks me every time I run into it. The LfCycStateId has the lifecycle state ID of the latest file in the revision. The LfCycStateName has the lifecycle state name of the current file version. That's why the code compares state name instead of the ID.