As we prepare our pilot of our XPage application, I was reminded that sometimes users might find a way to open a document in the Notes client when we don’t really want them to. While the odds are against them getting to a view or to a Notes document, no system is idiot-proof (idiots are absolutely genius sometimes!) So, I dug out an old script that I’d written back during my time at FAA to prevent users from accidentally opening a Notes database when they should be opening it only via the browser.
So, the users in question need to be able to update the documents, but I want them to do it in XPiNC or in the browser. That means, I can’t go using readernames fields to hide the documents from them and I know that hiding views (either via not including them in an outline or by naming convention) isn’t necessarily going to prevent them from opening my views.
Basically, all we do is check for their roles and if they have the right one, we let them in. Otherwise, they get warned off. I could add some script to this to open the document in the proper XPage, but this is a bare-bones version to help you get started if you have this kind of need.
Sub Queryopen(Source As Notesuidocument, Mode As Integer, Isnewdoc As Variant, Continue As Variant) Dim session As New NotesSession Dim db As NotesDatabase Dim doc As NotesDocument Dim formName As Variant Dim OKtoOpen As Boolean Dim roles As Variant Set db = session.CurrentDatabase roles = db.QueryAccessRoles(session.UserName) Set doc = Source.Document formName = doc.GetItemValue ( "Form" ) OKtoOpen = False Forall URoles In roles If Ucase(URoles) = "[ADMIN]" Then OKtoOpen = True End If End Forall If OKtoOpen = False Then Continue = False Messagebox "You are not authorized to access " & formName(0) & " documents via the Notes Client!",48, "Access Error" End If End Sub
While I was at it, I also wrote another version to be used to keep users out if they accidentally opened it on the backup or development servers. (Yes, I know production databases don’t belong on development servers, but it has happened here and, I am sure, other places).
Sub Queryopen(Source As Notesuidocument, Mode As Integer, Isnewdoc As Variant, Continue As Variant) Dim ws As New NotesUIWorkspace Dim session As New NotesSession Dim db As NotesDatabase Dim appsdb As NotesDatabase Dim doc As NotesDocument Dim appsdoc As NotesDocument Dim serverName As New NotesName ( "" ) Dim dontOpenServers (1) As String dontOpenServers (0) = "DominoDev" dontOpenServers (1) = "Backup" Set db = session.CurrentDatabase Set serverName = New NotesName ( db.Server ) Forall badServer In dontOpenServers If serverName.Common = badServer Then Continue = False Messagebox "You are attempting to open this document on " & serverName.Common & Chr$(10) & "Trying to open the document on MAIN",48, "Wrong Server" Set doc = Source.Document Set appsdb = New NotesDatabase ( "MAIN/COMPANY", db.FilePath ) ' if that didn't open it, try again If Not ( appsdb.IsOpen ) Then Call appsdb.Open ( "MAIN/COMPANY", db.FilePath ) End If ' if that didn't open it, try by replicaID If Not ( appsdb.IsOpen ) Then Call appsdb.OpenByReplicaID ( "MAIN/COMPANY", db.ReplicaID ) End If If Not ( appsdb.IsOpen ) Then Messagebox "Could not open the MAIN/COMPANY replica of the database, trying local replica",48, "Failed" Call appsdb.OpenByReplicaID ( "", db.ReplicaID ) End If If ( apps1db.IsOpen ) Then Set appsdoc = apps1db.GetDocumentByUNID ( doc.UniversalID ) If Not ( appsdoc Is Nothing ) Then Call ws.EditDocument ( False, appsdoc ) Else Messagebox "Opened the database, but could not open the document",48, "Failed" End If Else Messagebox "Could not open the local replica of the database either",48, "Failed" End If End If End Forall End Sub
These QueryOpens could be placed on individual forms or on subforms that are on those forms. You could put a version in the PostOpen event of the database script, though you have to keep in mind that the PostOpen doesn’t run if the user opens a document via a document link instead of opening a view or the database itself. Come to think of it, I will be putting a version in the PostOpen to prevent unauthorized users from opening the database, but have it quietly open the XPiNC page I want them to open.
I thought about putting this in my Security category, but it’s not really about security. It’s mostly about making sure the user gets the proper experience, by using production replicas or the correct client.
Hope you found something interesting here!
I’m sure you know there’s a couple problems with the LotusScript solution for a determined user. The first is, in theory they could turn on the debugger and avoid the code. Probably a long shot I admit but possible.
The database postOpen is a bigger problem I think. If I remember right, the postOpen code does NOT run if the user tries to open a specific VIEW in the database. for example he clicks on the icon once in the workspace to select it. Then does View – Go To. If he picks a view there I believe the postOpen doesn’t work. So that’s easier for a user to actually hit.
In the XPages world though we have a MUCH better option I think. I just started early work on this and have deployed a rough implemention on this. This might not work for all situations, I don’t know.
Have your XPages Code be in one database and your Data in another. Don’t give the users any ACL access in the Data database. (Sounds weird doesn’t it.) The user comes into your xpages .nsf and any data call that’s needed is run via code as “getSessionAsSigner”. This Signer does have access to the data .nsf.
Now you need to take care of any security stuff yourself in your code, but you’re doing that anyway really since you’re not using readers fields.
This works very well for me as I’ve been moving to Java Beans for all my stuff. So I haven’t been touching Notes Documents or Views directly. The Java Object does first. So when last week when I had the need for this type of security it was really very easy to implement.
Now I’ve only done this so far in a Read only situation, but I don’t anticipate any problems with editing.
I’ve not idea how this applies to XPiNC. I would assume that offline XPiNC is not an option since they can’t replicate the data down.
An added advantage of this…. Since you are now seperating your business objects from your data source… so the day comes when you want to move from storing data in the .nsf and want to put it in a relational db or whatever… you just need to change how your objects access the data. Everything else stays the same..
This topic will likely be coming to NotesIn9 at some point. 🙂