AndrewG10i
AndrewG10i

Reputation: 681

SessionAsSigner & restoreWrappedDocument()

Faced with the following issue: I am actively use DominoDocument class (wrapped Document) in my projects, particularly as basis for my business model objects.

Very often I have a need to access / iterate my business model objects as Anonymous user thus underlying lotus.domino.Document retrieved based on SessionAsSigner session object (for example in case of some REST Services, or in case of xAgent, etc).

The behavior of restoreWrappedDocument() method in such cases really breaks all flexibility of using such architecture: this method tries to restore wrapped document based on current execution environment access rights, and of course that causes errors with ACL.

Let’s consider the following code snippet as example:

public void test3() {
    try {

        System.out.println(">>>>>");
        System.out.println(">>>>> START");

        lotus.domino.Database db = AppBean.getSessionAsSigner().getDatabase(AppBean.getInstance().getContactsDBserverName(), AppBean.getInstance().getContactsDBname(), false);

        Document notesDoc = db.getAllDocuments().getFirstDocument();
        String dbName = notesDoc.getParentDatabase().getServer() + "!!" + notesDoc.getParentDatabase().getFilePath();
        DominoDocument ds = DominoDocument.wrap(dbName, notesDoc, null, "exception", false, "UseWeb", null);

        System.out.println(">> 1 >> " + ds.getValue("form"));

        ds.getDocument().recycle();

        try {
            ds.restoreWrappedDocument();
        }catch(Throwable e2){
            System.out.println(">> 2 - exception - >> " + e2.toString());
            e2.printStackTrace();
        }

        try {
            System.out.println(">> 3 >> " + ds.getValue("form"));
        }catch(Throwable e3){
            System.out.println(">> 3 - exception - >> " + e3.toString());
        }

        System.out.println(">>>>> END");
        System.out.println(">>>>>");

    }catch(Exception e){
        e.printStackTrace();
    }
}

1) Scenario 1: executing this code by authenticated user that has access to target DB gives the following result:

enter image description here

So method works as expected and everything perfect.

2) Scenario 2: executing this code by Anonymous user causes Exception (generally, what is expected):

enter image description here

You can clearly see that restoreWrappedDocument() executes some helper methods in order to get DB, and of course that is done with current user access level (Anonymous).

Possible solutions:

  1. The obvious solution is to add custom logic to my business object model, which will perform custom restore (basically based on Server&DB names and document UNID or NoteID).
  2. What I am very curious whether there is any more smart or built-in method exist for restoring wrapped documents with SessionAsSigner rights?

Thanks!

Upvotes: 0

Views: 367

Answers (2)

Sven Hasselbach
Sven Hasselbach

Reputation: 10485

A solution with a Helper class using Java Reflection: (Incomplete, missing some parts)

package ch.hasselba.xpages;

import java.lang.reflect.Field;

import lotus.domino.Database;
import lotus.domino.Document;
import lotus.domino.NotesException;

import com.ibm.xsp.FacesExceptionEx;
import com.ibm.xsp.model.domino.DominoUtils;
import com.ibm.xsp.model.domino.wrapped.DominoDocument;

public class DominoDocumentUtil {

    private static final long serialVersionUID = 1L;
    private transient final Field wrappedObj;
    private transient final DominoDocument dominoDoc;

    public DominoDocumentUtil(DominoDocument doc) throws SecurityException,
            NoSuchFieldException {
        dominoDoc = doc;
        wrappedObj= doc.getClass().getDeclaredField("_wrappedObject");
        wrappedObj.setAccessible(true);
    }

    public void restoreWrappedDocument(Database db)
            throws IllegalArgumentException, IllegalAccessException {
        try {
            Document doc = DominoUtils.getDocumentById(db, dominoDoc
                .getDocumentId(), dominoDoc.isAllowDeletedDocs());
            this.wrappedObj.set(dominoDoc, doc);
        } catch (NotesException ne) {
            throw new FacesExceptionEx(ne.getMessage());
        }
    }
}

To use the class you can call the restoreWrappedDocument method with a database opened with sessionAsSigner:

DominoDocumentUtil util = new DominoDocumentUtil(ds);
util.restoreWrappedDocument(db);

Upvotes: 1

Jesse Gallagher
Jesse Gallagher

Reputation: 4471

I don't think there's a proper way to do this, other than your option 1, for better or for worse.

However, and I'm not saying this is a good idea, it seems like DominoDocument likely gets to its session through the current request map. If you want to be tricky, you could try temporarily swapping session out for sessionAsSigner in the request scope, calling restoreWrappedDocument, and then swapping it back.

Upvotes: 1

Related Questions