One of the reasons why everyone in my company says I am a lovable chap is because I give technical support on an important HR application. In this application HR keeps track of the top-level functions in our organisation (Position), who is currently on a function (Successor) and who are marked as possible follow-ups (High Potential).
Since I am one of the few people who can read all information in the database occassionaly I receive the question if I have seen one’s name listed. Well try again next time if you see me in the pub. Maybe if you offer me a beer you might have more luck then, is my reply. Unfortunately this has not resulted (yet) in any free drinks…
The security model in this application works like this:
- people in the a higher level in the organisation may read all documents underneath their own level
- people in a lower level in the organisation may not read any documents above their own level
I must also mention how application security is distributed in our organisation:
- The Domino directory contains for each application a default set of usergroups. These groups represent the level people get in the ACL (reader, author, editor, designer)
- For server related groups their is a group for editor and manager access
- For each role a separate usergroup is listed
The naming of a usergroups is as followed:
- filename_typeofuser_accesslevel
Examples of groupnames are:
- SA01232_Users.Author
- SA01232_Users.Designer
- SA01232_Server.Manager
- SA01232_Roles.Admin
There is a routine running that creates for each role a group in the Directory and an application administrator can assign users to a group by assigning a user a role.
This works all fine BUT there is a limitation how many roles an ACL may contain (75 according to the Help).
My HR application is from a pre-standards age and has a slightly different security model that is based on individual usergroups that represent an organisational structure like in:
- filename_typeofuser_accesslevel_orglevel1_orglevel2… up till orglevel6
Therefor every position document in the application will get its unique usergroup reference and also all the usergroups of positions higher in the organisation.
For example the position document for the manager of Acme\Europe\Sales\Invoice also get the usergroups of Acme\Europe\Sales, Acme\Europe and Acme so the head of Sales, Europe can nominate and see who are in the pool of potentials for following up the head of Invoice, Sales, Europe.
Nothing to worry about except that the write access to the Domino directory is (wisely) restricted for normal users. So everytime someone thinks a usergroup needs to be updated a request has to be send to an administrator, and the updating is still then a manual task…
Well why would I worry? My worries came in the picture as soon as the application that is being used to administrate user access did not any longer display proper information about who has access to what level.
Since this an application with a one of a kind security model I could not expect any support from the administrators, they were more than happy to emphasize that it was about time that I write the security model to the model we have as standard.
Due to the limitation of userroles in an ACL I was forced to look for alternatives and one is to maintain the usergroup in the application itself and not care about having the usergroups any more in the Domino directory. This would also give me the opportunity to apply some new features like applying a mechanism to update the usergroups by the application administrator.
This all sounded nice, but a lot of work on uncovered terrain untill the sun started to shine outside when I discovered Ulriche Krause’s posting ‘Is User A Member Of A (Nested) Group ?‘.
This function allowed to copy the usergroups into my application and do the calculation from within. As a result I will get an array with usernames which I then could apply in Readers and Authors fields on each document.
I know this is data overhead (usernames stored in stead of usergroups) for something normally the Domino directory takes care of but for my application I consider it the best solution. Or am I wrong?
Note: I have added a scheduled routine that sets a flag on an updated usergroup. For each updated usergroup document the following routine runs:
Sub Initialize
Dim ses As New NotesSession
Dim luView As NotesView
Dim groupView As NotesView
Dim groupDoc As NotesDocument
Dim dc As NotesDocumentCollection
Dim doc As NotesDocument
Set db = ses.CurrentDatabase
Set groupView = db.GetView(“luGroup”)
Set luView = db.GetView(“luDocsByGroup”)
Set groupDoc = groupView.GetFirstDocument
Do Until groupDoc Is Nothing
If groupDoc.Tx_GroupUpdated(0) = “1″ Then
’Group document updated – update all position and successor documents containing the group
Set dc = luView.GetAllDocumentsByKey(groupDoc.ListName(0), True)
Set doc = dc.GetFirstDocument
Do Until doc Is Nothing
Call UpdateDocumentAccess(doc)
Set doc = dc.GetNextDocument(doc)
Loop
End If
groupDoc.Tx_GroupUpdated = “0″
Call groupDoc.save(True,False,False)
Set groupDoc = groupView.GetNextDocument(groupDoc)
Loop
End Sub
View luGroup contains all the usergroup documents, View luDocsByGroup contains all documents (Position, Successor, High Potential) that might need to be updated.
To ‘monitor’ if an usergroup is updated I use:
Sub Postopen(Source As Notesuidocument)
membersPO = Join(source.Document.Members, “##”)
End Sub
and
Sub Postsave(Source As Notesuidocument)
Dim groupChanged As String
Dim membersPS As Variant
membersPS = Join(source.Document.Members, “##”)
If membersPO <> membersPS Then
source.Document.Tx_GroupUpdated = “1″
Call source.Document.Save(True,True,True)
End If
End Sub
That’s for now, I go out cause the sun has started shining again!