Skip to content

DelfsEngineering/FM-HAM

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 

Repository files navigation

FM-HAM

Headless Authorization Module for FileMaker

FM-HAM is a flexible non opinionated model for managing account authorization. Note: Authorization is what the user can do vs authentication - who the user is.

This module is headless meaning it does not come with a user interface and often one is not needed. Technically the module is also foot / tailless as well. This means that you can store the raw authorization JSON objects any way you want but typically they are saved in a single field within your user or entity record.

Features

  • Non-opinionated
  • Ability to track numerical, value-based, or boolean privileges
  • Permissions can be stacked and overridden
  • No limit the depth of permissions
  • Easily pass a permissions object to 3rd party logic such as web interfaces like www.fmBetterForms.com etc.
  • Use it anywhere, including FileMaker record level access

Use Cases

FM-HAM can be used anywhere you need to control user activities and quantities

  • Control number of things a user is allowed to create
  • Control access a user has to an area of an application
  • Multi-tenant verticals, makes managing account attributes a snap

Simple Example

Overview

Define groups for the privileges within your application. Here is a simple example:

{
  "basicUser": {
       "addUsers": false,
       "editUsers": false,
       "editOwnDetails": true,
       "widgetsAllowed": 1
  },
  "manager": {
       "inherit": [
         "basicUser"
       ],
       "editUsers": true,
       "widgetsAllowed": 3
  },
  "admin": {
       "inherit": [
         "manager"
       ],
       "addUsers": true
  }
}

To nest privileges, use the inherit keyword. Then you'll only need to define or re-define privileges that are different than what the group is inheriting from.

  • inherit must be an array of strings that match other group names
  • Inheritance applies in order of the array; groups later in the array will take precedence.
  • Inheritance uses recursion; be careful not to cause an infinite loop!

Each user will then have their own user object with the group they belong to, and any user-specific overrides

{
	"group": "manager",
	"overrides": {
		"sessionLimit": 5
	}
}

Usage

Call the HAM_Config() function once per session to setup the privileges for the current user. If we passed in the groups and user definitions above, it would produce the following flattened session object:

{
	"addUsers": false,
	"editUsers": true,
	"editOwnDetails": true,
	"sessionLimit": 5
}

Then you can use the HAM_CheckPriv() function to lookup any of these privileges before performing certain actions.

Example:

HAM_CheckPriv( "addUsers" ; "" ) // will return FALSE

The HAM_CheckPriv function attempts to return the value of the key provided. If it encounters any errors, it will return False by default.

Best Practice

Naming permissions and privileges should be as semantic as possible. This will allow you and other developers to easily make assumptions as to what a privilege key means.

Boolean keys should be more truthy than falsy eg

Bad names

  • disabled
  • accountDisabled
  • widgets
  • preventGlobalThermoNuclearWar

Good Names

  • isActive
  • isDisabled
  • canAccessThis
  • countWidgets

Be sure to make your permissions as permissive as possible. If the CheckPriv function fails, it will return False by default.

Evaluations

If you add _eval to the end of any privilege name, the result of that privilege will be evaluated using FileMaker's Evaluate() function whenever it's checked by the HAM_CheckPriv() function. This means you can take advantage of local variables or even SQL Lookups within those calculations.

In this simple example, the editRooms privilege will only be true on Mondays.

"editRooms_eval": "Get ( DayOfWeek ) = 2",

Options & Defaults

Various options can be passed to the Setup and CheckPriv functions to modify the behavior of HAM. The options are passed as a JSON object as the last parameter of these functions.

HAM_Config Options

evaluateNow (boolean, defaults False) - Run all of the _eval privileges during setup instead of each time the privilege is checked. This is helpful if you have a lot of calculations or if they take a long time to run.

storeGlobal (boolean, defaults True) - If this is set to False, the $$HAM_Config global variable will never be stored in FileMaker's memory. This can make HAM more secure, but may also run more slowly since the Setup will be run each time HAM_CheckPriv() is called. To use it, you must have a default configuration setup in the HAM_Config function, then only call the HAM_CheckPriv function.

encryptionKey (string, no default) - If set, this will encrypt the entire $$HAM_Config global variable so that it cannot be modified by end users. You will need to pass in the encryption key each time you use the HAM_CheckPriv function.

HAM_CheckPriv Options

returnError (boolean, defaults False) - If true, the function will return a standard error object if an error occurred (instead of the default False). You can also always check the $$HAM_LastError variable to see if any errors occurred. With this enabled, if no errors occur, the value from the flat object of privileges is still returned.

encryptionKey (string, no default) - If set, it will use this key to decrypt the data stored in the $$HAM_Config global variable.

Default Configuration

You can edit the default configuration for the HAM_Config function. These settings will act like the normal parameters of the function if the function is run with blank parameters, or if the CheckPriv function runs before the Config function.

Script example psudo code

# Global script populates a `priv` object with the user’s permissions object
If [ CheckPriv ( "editReservations" ; "" ) ] #return boolean
	Set Variable [ $$BF_Actions ; BF_SetAction (show alert = $priv_error) ]
	Exit Loop If [ True ]
End If
If [ not CheckPriv ( "editReservations" ) = "all" ]
	Set Variable [ $$BF_Actions ; BF_SetAction (show alert = $priv_error) ]
	Exit Loop If [ True ]
Else If [ not CheckPriv ( "editReservations" ) = "own" ]
	CheckPrivError ( "editReservations" ; "own" )
End If
​
Exit Loop If [ CheckPriv ( "showAdminMenu" ; "" ) ]

Misc Notes to be converted into code

A user can also have custom privileges that can override these default group settings. A FileMaker Custom Function can merge the custom privileges with the group privileges into the user’s JSON object, with the custom settings taking priority ++How to verify the default setting for privileges if not set?++

++How to manage UI for granting/removing privileges so that that when changing privileges leftover custom privileges aren’t ignored?++

In FileMaker, we can easily make a series of tables to manage the groups and permission lists. This would allow easy access to add new groups or individual privileges. Scripts would normalize this data into JSON for a solution.

About

Headless Authorization Module for FileMaker

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published