At ACP we've implemented a user management service used by all our custom-built apps to assign permissions to users. This was one of our first agile developments and I thought I'd share the thought processes behind its design.
The problem
Applications have functions (e.g. 'create a new blog'). Applications have users (e.g. 'Me'). Not all users are created equal. Some can perform many functions, some only a few. Some functions are used by many users, some only a few. Clearly we need a way to manage who can do what - ideally this should be provided with the minimal effort to develop and maintain.
Observation 1: A single application to manage assignment of users to functions for all applications would be useful. The problem described above is a generic one unrelated to a specific application. Result: Decide we need a User Management Application (UMA)
Observation 2: Functions and users have a many-to-many relationship. We could build an application which takes a list of users (e.g. from AD) and a list of functions for each application and provides a tool to map the two lists. Plus a service interface which allows an application to request the functions available for a particular user. Result: This will be OK for small apps with few users / functions, but will be a nightmare for anything larger.
Observation 3: Many functions are grouped for particular users - e.g. a 'Super User' may have access to everything, a 'Warehouse Manager' may have access to functions relating to managing warehouses. Result: These sound like Roles - we could extend the tool to map users to roles and roles to functions.
Observation 4: Some users have the same functions but they shouldn't have the same access to the same data. E.g. we may have a Sydney warehouse and a Melbourne warehouse - with a warehouse manager in each one. Result: UMA needs to support application dimensions (warehouses in the example above) but could be any 'filter' on data - e.g. publications, sales groups, departments. We can map users to dimensions.
Obversation 5: Sometimes an application needs to know who can do something rather than what someone can do. E.g. the application wants to show a list of people who can approve a photograpy purchase. Result: Allow the service interface to query by function (returning a list of users) as well as by user.
Obversation 6: If UMA goes down (so to speak) so will all our apps. Result: Firstly, only retrieve permissions on starting a session (a short outage would be less of a problem). Secondly, allow applications to store and revert to the last known permission set for the user if UMA is otherwise engaged.
Observation 7: When a new employee starts, HelpDesk will be asked 'can you give them the same access as Jervis Bean?'. Result: UMA needs to support profiles. We can map a profile to roles and dimensions and users to profiles (though we can still add explicit mappings for the user). Oh and we'll change the name to Profile and User Management Application (PUMA) since it's easier to rip off a logo...
Observation 8: Some dimensions should have one and only one user associated with a particular function. For example, there should be only one person who is the editor of Ralph. Result: PUMA should manage the multiplicity of the dimension / function relationship.