When Filemaker Privileges are not enough

Normally adjusting Filemaker privileges for user groups is enough to embed the required security into your solution. You can achieve most things through the usual granular access to script, layout, record and value list privileges. Sometimes this isn't enough though. What if you have an action that can only be performed by a user if they are a member of a given privilege set OR they conform to a rule that is based on the content of the record being viewed?

I recently had a request from a client to add a process into our Deadline solution for publishers that I just couldn't achieve with the privileges alone. Fortunately, as with most things Filemaker, the solution turned out to be pretty simple. The issue I was presented with relates to advertising sales orders. The client has a process whereby any salesperson can create an order in the software but all orders need to be passed by a sales manager before they can be issued to the client. In addition to this there is a rule that only the person who created the order or a sales manager can make alterations to any part of the order.

Initially it seems straight forward... 1. Put the sales manager in a privilege set that allows access to an edit order screen 2. Put sales people in privilege set that does not allow access to the edit screen The problem is though that this means the sales person who 'owns' the order can no longer edit it. The solution is really simple. As moving to the edit screen will always require a button press I could create an authorization script to check that the user is allowed to edit that record. The script (check_authorization) looks like this.

SetVariable[$priv;

Value:Get(PrivilegeSetName)]

SetVariable[$user;

Value:Get(AccountName)]

If

[PatternCount(Get(ScriptParameter);$priv)

or

PatternCount(Get(ScriptParameter);$user)

SetVariable [$auth;Value:"Yes"]

Else

SetVariable [$auth;Value:"No"]

Show Custom Dialog ["Access Denied";"You are not allowed to do this"]

End If

Exit Script

[Result:$auth] 

The first two lines (SetVariable) identify the current user account and the privilege set they belong to. Not strictly necessary to do this here but I like to set up variables with more sensible names to use inside a script, at the very least I find it makes the script easier to read. The next statement (the If) is where the decision is made. The button the user clicked to activate the script has a parameter attached and that parameter contains the account names and or privilege set names in a return separated list of individuals who are allowed to perform this action. In this case it contains Sales_manager ileslie i.e. the privilege set name that is allowed to perform the action and the contents of the 'sold_by' field on the current order form being viewed. The script then compares the variables I set for $priv and $user with the script parameter and if there is a match it sets the result to 'Yes'. If there is no match it sets the result to 'No' and displays a dialog. On exit the script returns the parameter $auth (either 'Yes' or 'No'). The reason for this is to allow this script to be called from within another script and return it the result before proceeding. A simple example would be:

Perform Script ["check_authorization";

Parameter:Get(ScriptParameter)

If[Get(ScriptResult) = "Yes"]

Go to Layout ["edit_order"]

End If

So I now have a simple script that can check a users authorization to run any script or action even when the authorization depends on the content of the record being viewed.