Preventing users from opening a document in Notes

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!

Advertisements
Categories: Old Notes, Utilities | Tags: , , , , , , | 5 Comments

Post navigation

5 thoughts on “Preventing users from opening a document in Notes

  1. 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. 🙂

    • Giulio Campobassi

      @DavidLeedy. Nice that you separate data from design, but if you access the data as “getSessionAsSigner” you are committed to a purely programmatic rules approach to access. You can’t use roles or reader fields to determine permission for access. It’s one of the “free” things that i really want to avoid giving up. Or have I missed something.

      It would be easier if IBM just plugged the holes in the client model. I still live in hope. I know it’s sacrilege that it wont actually contribute to IBM’s EPS targets, but I’m just one of those rogues who just likes to finish things off and see stuff work well.

      • David Navarre

        @Giulio, you can use the roles in the design database, so that users only get views and actions that they ought to see or use filters on the view controls to limit the documents displayed. Since the user cannot make a local replica of the data database, you don’t have to worry about them navigating in unexpected ways to get at data that should be invisible to them. If you’re worried about them figuring out the URL for a page they should not access, remember that you can also use roles to limit access to individual XPages ( https://lostinxpages.com/2013/07/30/using-xpage-acls-to-limit-access/ )

      • Giulio,

        You said “You can’t use roles or reader fields to determine permission for access.”

        Remember if Readers fields are an option then you don’t need my suggestion. The original premise of the post was some security without using readers fields. So I think that’s the part you missed.

        But honestly in an XPages world I don’t know if giving up on some of this “free stuff” is that big deal. Don’t tell Marky Roden this, but you can write this yourself in Java. 🙂 Ok probably SSJS also if you’re glutton for punishment. And I don’t think it would be that hard to get something written to do this.

        Take this example. You have an inventory database. But the DB contains many customers. Maybe 1,000. who knows. Point is you want to only show a customer THEIR database but readers fields aren’t a great option because of the size of it.

        So you create Java Object(s) to handle this for you. maybe you have a setup database linking users to a companyKey. Someone tries to open an inventory item you check that company against the user list. Not the end of the world. You expand on your needs from there. No Readers fields needed.

        Now let’s say that somewhere down the line you need to actually get inventory data into an RDBMS. For Accounting purposes maybe. Sure you could use a pumping product like LEI or Notrix. But there’s a lot of moving parts there. Those solutions reach maximum suck pretty quick.

        So you change your objects to just point to the external DB like I mentioned before. But now since you’re controlling the security model anyway… there’s that much less to do. Lot of flexibility for not giving up all that much really. Especially if Readers/Authors fields don’t help you anyway.

        I don’t want to give up the free things. But if needed it’s not the end of the world I think.

    • David Navarre

      As always, insightful comments, David.

      You are correct, this does nothing to prevent a determined, knowledgeable user who is intent on getting at the data. That’s why it’s not security. It’s just some steps to ensure the user experience is likely to be the one that I want – that they use my XPages as their interface.

      I’d never tried View – Go To from the workspace with the icon selected. You’re correct, it does skip the database script in that case. I had been surprised that a view link ran the database script, as I’d thought it only worked if they opened the database as a whole. So, not surprising that View – Go To gets around the database script, but still surprising that view links don’t.

      Our pilot implementation does separate design from data in different databases (thanks to Scott Good and his folks at Teamwork Solutions for the initial design!), but since our use case involves users on laptops around the world (usually in inhospitable places) and a lot of disconnected work. That’s why it has to be XPiNC and the data has to replicate down.

      So, this implementation can’t use sessionAsSigner and user-inaccessbile data, but we might find a new use case for that down the road. So, great to hear the idea!

      Also, good to understand the design options for future presentations about our pilot project. Hopefully, we can work something up for ICON.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: