SnTT: Using 'Run on Behalf' Agents to Access Data Where One User Doesn't Have Reader Rights10/08/2009 09:59:42 AM
Location : Cleveland, OH
Let's welcome a guest blogger for today's Show-n-Tell Thursday, Branimir Ćorluka. He will show us how a "Run on Behalf" agent can allow one user to see data to which he does not have access, so that the same user can complete a task.
There may be a situation where a user needs to compare or check some data that is located in documents on which the user does not have reader rights. This may occur fairly regularly in the course of a day, especially where one person is responsible for an administrative task.
For example, one user enters data in a time sheet document for all the employees in his department. He picks a category (vacation, trip, sick) for each working day. When an employee goes to visit a customer, that employee creates a travel document. In this document are the facts about the trip (duration, expenses ...). It makes sense that the user that fills the time sheet does not have access to the travel details. But when the user saves the time sheet he should be warned if the data that he has filled in does not match the data from the travel document (for example, the hours worked may be different, due to travel duration, or some other circumstance).
There is a handy agent option, introduced in Lotus Notes and Domino Release 6, that can resolve this issue. It is called "Run on behalf of" and it allows you to specify on whose authority this agent can run. The agent property looks like this:
It allows developers to execute the code under someone else's rights. It seems simple, right? It is as long the agent's trigger is set to scheduled or we invoke the agent via @Command([ToolsRunMacro];""). However, it gets tricky when the trigger is "On event" and we already have some LotusScript code in the event which should trigger the agent. It is natural then to use the NotesAgent class and its method Run. The trouble with that is we cannot interact with the user; no Messagebox, no Print statement.
Lotus Designer Help says:
"The user cannot interact directly with a called agent. User output goes to the Domino log."
So there is no way to display the results? Actually there is, but we need a work-around.
First we need to create a form with one field on it, in this example I will call the form "msForm" and the field "body." Place the following code in the QueryOpen event:
This LotusScript was converted to HTML using the ls2html routine,
provided by Julian Robichaux at nsftools.com.
This piece of code shows a Messagebox to the user with the content of the body field. Then it stops the form from opening.
Now, we need to create a "Run on behalf of ..." agent. The runtime properties of the agent should be set to On Event, Agent list selection and None. With the following code in the declarations section.
This LotusScript was converted to HTML using the ls2html routine,
provided by Julian Robichaux at nsftools.com.
As you can see, the simple class, ShowNoAcces, data consists of a constructor whose argument is the message we need to show to the user.
We create an instance of the document with the msForm we have created before, fill it with our data and open it in the UI. As you may recall, we won't allow this form to open. We will show the content of the form in the Messagebox and prohibit the opening of the form.
The following code comes into the Initialize section of the agent::
This LotusScript was converted to HTML using the ls2html routine,
provided by Julian Robichaux at nsftools.com.
Of course it is up to you how to find the document with the data, process the data and pass the results to the class constructor.
You also decide how to run the agent, for example you can choose to start it with a button click. Or like in this case in a QuerySave event:
This LotusScript was converted to HTML using the ls2html routine,
provided by Julian Robichaux at nsftools.com.
By following this, one user can see and act on data which he doesn't have Reader access, while maintaining the security of the data.
[UPDATE]: Craig Schumann has pointed out, in the comments to this SnTT post, that you need to be very careful with this scenario, and has given me a link to an excellent post detailing the issues. His post is entitled "Fragile UI? Don't do it on "my behalf!". Be sure to read the comments to his post, too.
Technorati tag: SnTT Show-n-Tell Thursday
There may be a situation where a user needs to compare or check some data that is located in documents on which the user does not have reader rights. This may occur fairly regularly in the course of a day, especially where one person is responsible for an administrative task.
For example, one user enters data in a time sheet document for all the employees in his department. He picks a category (vacation, trip, sick) for each working day. When an employee goes to visit a customer, that employee creates a travel document. In this document are the facts about the trip (duration, expenses ...). It makes sense that the user that fills the time sheet does not have access to the travel details. But when the user saves the time sheet he should be warned if the data that he has filled in does not match the data from the travel document (for example, the hours worked may be different, due to travel duration, or some other circumstance).
There is a handy agent option, introduced in Lotus Notes and Domino Release 6, that can resolve this issue. It is called "Run on behalf of" and it allows you to specify on whose authority this agent can run. The agent property looks like this:
It allows developers to execute the code under someone else's rights. It seems simple, right? It is as long the agent's trigger is set to scheduled or we invoke the agent via @Command([ToolsRunMacro];""). However, it gets tricky when the trigger is "On event" and we already have some LotusScript code in the event which should trigger the agent. It is natural then to use the NotesAgent class and its method Run. The trouble with that is we cannot interact with the user; no Messagebox, no Print statement.
Lotus Designer Help says:
"The user cannot interact directly with a called agent. User output goes to the Domino log."
So there is no way to display the results? Actually there is, but we need a work-around.
First we need to create a form with one field on it, in this example I will call the form "msForm" and the field "body." Place the following code in the QueryOpen event:
Sub Queryopen(Source As Notesuidocument, Mode As Integer, Isnewdoc As Variant, Continue As Variant) Messagebox source.Document.body(0) continue = False End Sub
provided by Julian Robichaux at nsftools.com.
This piece of code shows a Messagebox to the user with the content of the body field. Then it stops the form from opening.
Now, we need to create a "Run on behalf of ..." agent. The runtime properties of the agent should be set to On Event, Agent list selection and None. With the following code in the declarations section.
Class ShowNoAccesData Private msDoc As notesdocument Sub New(message As String) Dim s As New NotesSession Dim db As notesdatabase Set db = s.currentdatabase Set MsDoc = db.CreateDocument MsDoc.Form = "msForm" MsDoc.body = message Dim ws As New notesuiworkspace Call ws.EditDocument(False, msDoc) End Sub End Class
provided by Julian Robichaux at nsftools.com.
As you can see, the simple class, ShowNoAcces, data consists of a constructor whose argument is the message we need to show to the user.
We create an instance of the document with the msForm we have created before, fill it with our data and open it in the UI. As you may recall, we won't allow this form to open. We will show the content of the form in the Messagebox and prohibit the opening of the form.
The following code comes into the Initialize section of the agent::
Sub Initialize Dim s As New notessession Dim noAccessView As notesview Dim doc As NotesDocument Set noAccessView = s.CurrentDatabase.GetView("noAccessView") Set doc = noAccessView.GetFirstDocument Dim snad As New ShowNoAccesData(doc.data(0)) End Sub
provided by Julian Robichaux at nsftools.com.
Of course it is up to you how to find the document with the data, process the data and pass the results to the class constructor.
You also decide how to run the agent, for example you can choose to start it with a button click. Or like in this case in a QuerySave event:
Sub Querysave(Source As Notesuidocument, Continue As Variant) Dim s As New notessession Dim ourAgent As notesagent Set ourAgent = s.CurrentDatabase.GetAgent("(ShowNoAccessDataAgent)") If Not(ourAgent Is Nothing) Then Call ourAgent.Run Else Msgbox "Agent could not be found." End If End Sub
provided by Julian Robichaux at nsftools.com.
By following this, one user can see and act on data which he doesn't have Reader access, while maintaining the security of the data.
[UPDATE]: Craig Schumann has pointed out, in the comments to this SnTT post, that you need to be very careful with this scenario, and has given me a link to an excellent post detailing the issues. His post is entitled "Fragile UI? Don't do it on "my behalf!". Be sure to read the comments to his post, too.
Technorati tag: SnTT Show-n-Tell Thursday
Powered By : Domino
BlogSphere V1.3.1
Join The WebLog Revolution at BlogSphere.net