/*
* � Copyright IBM Corp. 2011
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.ibm.domino.das.resources;
import java.util.Vector;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import com.ibm.commons.util.StringUtil;
import com.ibm.domino.das.servlet.DasServlet;
import com.ibm.domino.das.utils.ErrorHelper;
import com.ibm.domino.osgi.core.context.ContextInfo;
import lotus.domino.Database;
import lotus.domino.Document;
import lotus.domino.NotesException;
import lotus.domino.View;
public class AbstractDasResource {
/**
* Special note id for accessing the icon note.
*/
public static final String ICON_NOTEID = "FFFF0010"; // $NON-NLS-1$
/**
* Item name in the icon note to indicate that the database api is enabled.
*/
public static final String ITEM_ALLOW_RESTDBAPI = "$AllowRESTDbAPI"; // $NON-NLS-1$
// the following 3 are access levels for the db as specified by
// ITEM_ALLOW_RESTDBAPI
public static final int DB_ACCESS_NONE = 0;
public static final int DB_ACCESS_VIEWS = 1;
public static final int DB_ACCESS_VIEWS_DOCS = 2;
// The following are for the view access check
public static final String ITEM_WEB_FLAGS = "$WebFlags"; //$NON-NLS-1$
private final static char WEBFLAG_RESTAPIALLOWED = 'A'; //$NON-NLS-1$
/**
* Get the current database object with access control check
* @return the database if allowed for access
*/
protected Database getDatabase(int minAccessNeeded){
Database database = ContextInfo.getUserDatabase();
if ( database != null ) {
//Verify current access to the database
Document doc = null;
try{
doc = database.getDocumentByID(ICON_NOTEID);
if (doc != null) {
Vector<?> values = doc.getItemValue(ITEM_ALLOW_RESTDBAPI);
int value = DB_ACCESS_NONE;
if ( values != null && values.size() > 0 ) {
Object obj = values.get(0);
if ( obj instanceof String ) {
// SPR# DDEY9N8Q62: The 8.5.2 client can incorrectly change the item
// value to a string. Tolerate that and assume the greatest level
// of access.
if ( "1".equals(obj) ) {
value = DB_ACCESS_VIEWS_DOCS;
}
}
else {
value = doc.getItemValueInteger(ITEM_ALLOW_RESTDBAPI);
}
}
if ((value > 0) && (value >= minAccessNeeded)) {
return database;
}
else if( value == DB_ACCESS_NONE) {
// This resource should never have a database context
throw new WebApplicationException(ErrorHelper.createErrorResponse("The Domino data service is not enabled for this database.", Response.Status.FORBIDDEN)); // $NLX-AbstractDasResource.DatabasenotallowedforWebAccess-1$
}
else {
if(DasServlet.DAS_LOGGER.isTraceDebugEnabled()){
DasServlet.DAS_LOGGER.traceDebug("Invalid access level value set in the icon document: {0}", value); // $NON-NLS-1$
}
throw new WebApplicationException(ErrorHelper.createErrorResponse("Cannot access resource", Response.Status.FORBIDDEN)); // $NLX-AbstractDasResource.Cannotaccessresource-1$
}
}
}catch(NotesException e){
if(DasServlet.DAS_LOGGER.isTraceDebugEnabled()){
DasServlet.DAS_LOGGER.traceDebug(e, "Error accessing the database icon document"); // $NON-NLS-1$
}
throw new WebApplicationException(ErrorHelper.createErrorResponse("", Response.Status.INTERNAL_SERVER_ERROR));
}finally {
if(doc!=null){
try {
doc.recycle();
doc = null;
} catch (NotesException e) {
DasServlet.DAS_LOGGER.warn("Error recycling the icon document", e) ; // $NLW-AbstractDasResource.errortorecycletheICONdocument-1$
}
}
}
}
return null;
}
/**
* Get the current View object by its Unid with access control check
* @return the view object for the specified Unid
*/
protected View getCurrentViewByUnid(Database db, String unid){
View expectedView = null;
Vector<?> views = null;
try {
views = db.getViews();
int size = views.size();
//if (isUNID(unid))
if (unid != null)
{
for (int i = 0; i < size; i++)
{
View view = (View) views.elementAt(i);
if (view.getUniversalID().equalsIgnoreCase(unid)){
doViewAccessCheck(view);
expectedView = view;
}
}
}
} catch (NotesException e) {
if(DasServlet.DAS_LOGGER.isTraceDebugEnabled()){
DasServlet.DAS_LOGGER.traceDebug(e, "Error accessing the view by UNID: {0}", unid); // $NON-NLS-1$
}
throw new WebApplicationException(ErrorHelper.createErrorResponse(e, Response.Status.INTERNAL_SERVER_ERROR));
}finally{
//recycle the view objects that are not matching
if(views!=null){
views.remove(expectedView);
for (int i = 0; i < views.size(); i++)
{
View view = (View) views.elementAt(i);
if(view!=null){
try {
view.recycle();
view = null;
} catch (NotesException e) {
DasServlet.DAS_LOGGER.warn("Error recycling the view", e) ; // $NLW-AbstractDasResource.errortorecycletheview-1$
}
}
}
}
}
return expectedView;
}
/**
*
* Get the current View object by its name or aliases with access control check
* @return the view object for the specified name/alias
*/
protected View getCurrentViewByName(Database db, String name){
try {
View view = db.getView(name);
if ( view == null ) {
// This resource should always have a database context
throw new WebApplicationException(ErrorHelper.createErrorResponse("The URI must refer to an existing view.", Response.Status.NOT_FOUND)); // $NLX-AbstractDasResource.TheURImustrefertoanexistingview-1$
}
doViewAccessCheck(view);
return view;
} catch (NotesException e) {
if(DasServlet.DAS_LOGGER.isTraceDebugEnabled()){
DasServlet.DAS_LOGGER.traceDebug(e, "Error accessing the view by name: {0}",name); // $NON-NLS-1$
}
throw new WebApplicationException(ErrorHelper.createErrorResponse(e, Response.Status.INTERNAL_SERVER_ERROR));
}
}
/**
* Converts a string parameter to an integer.
*
* @param paramName
* @param paramValue
* @return int
*/
protected int getParameterInt(String paramName, String paramValue) {
return getParameterInt(paramName, paramValue, false);
}
/**
* Converts a string parameter to an integer.
*
* @param paramName
* @param paramValue
* @param bHex - Set to true if the values can be hex.
* @return int
*/
protected int getParameterInt(String paramName, String paramValue, boolean bHex) {
int iParam;
try {
if(bHex && paramValue.toLowerCase().startsWith("0x")){ //$NON-NLS-1$
iParam = Integer.parseInt(paramValue.substring(2), 16);
}else{
iParam = Integer.parseInt(paramValue);
}
} catch (NumberFormatException nfe) {
String msg = StringUtil.format("Invalid parameter {0}: {1}", paramName, paramValue); // $NLX-AbstractDasResource.Invalidparameter01-1$
throw new WebApplicationException(
ErrorHelper.createErrorResponse(
new Exception(msg, nfe), Response.Status.BAD_REQUEST));
}
if (iParam < 0) {
String msg = StringUtil.format("Invalid parameter {0}: {1}", paramName, paramValue); // $NLX-AbstractDasResource.Invalidparameter01.1-1$
throw new WebApplicationException(
ErrorHelper.createErrorResponse(msg, Response.Status.BAD_REQUEST));
}
return iParam;
}
/**
* For each view, there is an new option named "Allow Domino Data Service operations" for the "Web Access"
* If the box is checked, means the access for it is allowed, otherwise, forbidden
* @param view
*/
private void doViewAccessCheck(View view) {
Document viewDoc = null;
//Just pass all requests for the current view,
try {
viewDoc = view.getParent().getDocumentByUNID(view.getUniversalID());
if (viewDoc != null) {
String flags = viewDoc.getItemValueString(ITEM_WEB_FLAGS);
if (flags.indexOf(WEBFLAG_RESTAPIALLOWED) < 0) {
if(DasServlet.DAS_LOGGER.isTraceDebugEnabled()){
DasServlet.DAS_LOGGER.traceDebug("Error accessing view: {0}",view.toString()); // $NON-NLS-1$
}
String msg = StringUtil.format("The Domino data service is not enabled for this view [{0}].", view.getName()); // $NLX-AbstractDasResource.View0notallowedforWebAccess-1$
throw new WebApplicationException(ErrorHelper.createErrorResponse(msg, Response.Status.FORBIDDEN));
}
}
} catch (NotesException e) {
if(DasServlet.DAS_LOGGER.isTraceDebugEnabled()){
DasServlet.DAS_LOGGER.traceDebug(e, "Error accessing view: {0}",view.toString()); // $NON-NLS-1$
}
throw new WebApplicationException(ErrorHelper.createErrorResponse(e, Response.Status.INTERNAL_SERVER_ERROR));
} finally {
if(viewDoc!=null){
try {
viewDoc.recycle();
viewDoc = null;
} catch (NotesException e) {
DasServlet.DAS_LOGGER.warn("Error recycling the view document", e) ; // $NLW-AbstractDasResource.errortorecycletheviewdocument-1$
}
}
}
}
}