Access control
Domino REST API follows Domino's access control with no exceptions. However, you can further tighten the security to be very specific on individual access requirements.
Access annotations
You can decorate each request class with a series of Java annotations to both document and early enforce access requirements:
@MinimumAcl(AclLevel)
- Specifies the required ACL access. While Editor access suffices for updating a document, you can specify that this function requires Designer access.@AclAttributes(AclAccessFlags)
- Requires specific flags likeCreateDocuments
orCreateSharedFoldersViews
, all the checkboxes in the ACL.@AclRoles(String[])
- User must have one of the roles to perform the operation.@ServerAclSecurity(ServerAclType)
- Requires Server ACL entries likeSERVER_ADMIN
,FULL_ADMIN
,DATABASE_ADMIN
, and more.@ServerEclSecurity(ServerEclType)
- Requires execution permissions likeRUN_UNRESTRICTED_CODE
,RUN_RESTRICTED_CODE
andRUN_FORMULA
.
So your class could look like this:
@MinimumAcl(AclLevel.AUTHOR)
@AclAttributes({AclAccessFlags.CreateDocuments})
@AclRoles({"Approver"})
public class SubmitDecision extends AsyncDominoJNXJson {
public void process(final DbRequestParameters<JsonObject> request) throws Exception {
request.validate();
// Your code goes here
}
}
Helper methods
There are a number of helper methods available to perform common checks. Most of them can be found in the KeepJnxSession
, or as static methods in DocumentFunctions
. Check the JavaDoc for details:
Optional<Document> session.getDocumentByUNID(request.db, unid, DocumentScope.VALID_DOCUMENTS_ONLY)
Document validateDocumentAccessRequest(final Database db, final String unid, final DocumentAccess docAccess, final Optional<KeepRequestId> requestId)
Document createDocFromJson(final Database db, final JsonObject body)
void updateDocumentFromJson(final JsonObject jsonSource, final Document doc)
JsonObject DocumentFunctions.document2Json(doc, includeMeta)
Typical code pattern would look like this:
// Get a specific document
final Optional<Document> optionalNote = request.session.getDocumentByUNID(request.db, unid, DocumentScope.VALID_DOCUMENTS_ONLY);
// Throw an error
final Document note = optionalNote.orElseThrow(() -> new KeepExceptionNotFound(KeepExceptionStrings.NO_DOCUMENT_ACCESS, unid));
// Create a new doc
final Document note = optionalNote.orElse(() -> db.createDocument());
Privileged operations
A typical requirement in web applications is the need for operation specific elevated privileges. An example is if you want the default access for "ApprovalLog.nsf" to be Reader so nobody can manually create or alter documents, but the code in SubmitDecision
needs to be able to create. For this scenario, the KeepJnxSession
allows to execute
operations as the server, using server privileges.
The modified code from Business Logic would look like this:
try (KeepClient kc = request.session.getClientAsIDUser(); // Session as server
Database approvalLog = kc.openDatabase("ApprovalLog.nsf")) {
// Write to log
Document logEntry = approvalLog.createDocument();
logEntry.replaceItemValue("Form", "logentry");
// like before
logEntry.save();
// Update document
// like before
doc.save();
} catch (Exception e) {
logger.error(e.getMessage());
throw e;
}
Important
While this allows to have tight access control, it can backfire when not implemented carefully.
Next
Proceed to deployment.