diff --git a/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java b/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java index 1f348b8c5..e606599ba 100644 --- a/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java +++ b/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java @@ -32,6 +32,7 @@ import li.strolch.agent.impl.AuditingAuditMapFacade; import li.strolch.agent.impl.AuditingOrderMap; import li.strolch.agent.impl.AuditingResourceMap; import li.strolch.agent.impl.InternalStrolchRealm; +import li.strolch.exception.StrolchAccessDeniedException; import li.strolch.exception.StrolchException; import li.strolch.model.GroupedParameterizedElement; import li.strolch.model.Locator; @@ -65,6 +66,7 @@ import li.strolch.service.api.Command; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import ch.eitchnet.privilege.base.PrivilegeException; import ch.eitchnet.privilege.model.Certificate; import ch.eitchnet.privilege.model.PrivilegeContext; import ch.eitchnet.utils.dbc.DBC; @@ -237,8 +239,12 @@ public abstract class AbstractTransaction implements StrolchTransaction { } private void assertQueryAllowed(StrolchQuery query) { - PrivilegeContext privilegeContext = this.privilegeHandler.getPrivilegeContext(this.certificate); - privilegeContext.validateAction(query); + try { + PrivilegeContext privilegeContext = this.privilegeHandler.getPrivilegeContext(this.certificate); + privilegeContext.validateAction(query); + } catch (PrivilegeException e) { + throw new StrolchAccessDeniedException(this.certificate, query, e.getMessage(), e); + } } @Override diff --git a/li.strolch.agent/src/main/java/li/strolch/service/api/DefaultServiceHandler.java b/li.strolch.agent/src/main/java/li/strolch/service/api/DefaultServiceHandler.java index 4990f1ba0..7f387254a 100644 --- a/li.strolch.agent/src/main/java/li/strolch/service/api/DefaultServiceHandler.java +++ b/li.strolch.agent/src/main/java/li/strolch/service/api/DefaultServiceHandler.java @@ -19,6 +19,7 @@ import java.text.MessageFormat; import li.strolch.agent.api.ComponentContainer; import li.strolch.agent.api.StrolchComponent; +import li.strolch.exception.StrolchAccessDeniedException; import li.strolch.exception.StrolchException; import li.strolch.runtime.configuration.ComponentConfiguration; import li.strolch.runtime.configuration.RuntimeConfiguration; @@ -33,8 +34,10 @@ import ch.eitchnet.utils.helper.StringHelper; */ public class DefaultServiceHandler extends StrolchComponent implements ServiceHandler { + private static final String PARAM_THROW_ON_PRIVILEGE_FAIL = "throwOnPrivilegeFail"; private RuntimeConfiguration runtimeConfiguration; private PrivilegeHandler privilegeHandler; + private boolean throwOnPrivilegeFail; /** * @param container @@ -48,6 +51,7 @@ public class DefaultServiceHandler extends StrolchComponent implements ServiceHa public void initialize(ComponentConfiguration configuration) { this.privilegeHandler = getContainer().getPrivilegeHandler(); this.runtimeConfiguration = configuration.getRuntimeConfiguration(); + this.throwOnPrivilegeFail = configuration.getBoolean(PARAM_THROW_ON_PRIVILEGE_FAIL, Boolean.FALSE); super.initialize(configuration); } @@ -84,7 +88,7 @@ public class DefaultServiceHandler extends StrolchComponent implements ServiceHa StringHelper.formatNanoDuration(end - start), e.getMessage()); logger.error(msg, e); - if (service instanceof AbstractService) { + if (!this.throwOnPrivilegeFail && service instanceof AbstractService) { AbstractService abstractService = (AbstractService) service; @SuppressWarnings("unchecked") U arg = (U) abstractService.getResultInstance(); @@ -93,7 +97,7 @@ public class DefaultServiceHandler extends StrolchComponent implements ServiceHa arg.setThrowable(e); return arg; } else { - throw new StrolchException(e.getMessage()); + throw new StrolchAccessDeniedException(certificate, service, e.getMessage(), e); } } @@ -113,16 +117,7 @@ public class DefaultServiceHandler extends StrolchComponent implements ServiceHa } // log the result - long end = System.nanoTime(); - String msg = "User {0}: Service {1} took {2}"; //$NON-NLS-1$ - msg = MessageFormat.format(msg, username, service.getClass().getName(), - StringHelper.formatNanoDuration(end - start)); - if (serviceResult.getState() == ServiceResultState.SUCCESS) - logger.info(msg); - else if (serviceResult.getState() == ServiceResultState.WARNING) - logger.warn(msg); - else if (serviceResult.getState() == ServiceResultState.FAILED) - logger.error(msg); + logResult(service, start, username, serviceResult); return serviceResult; @@ -135,4 +130,42 @@ public class DefaultServiceHandler extends StrolchComponent implements ServiceHa throw new StrolchException(msg, e); } } + + private void logResult(Service service, long start, String username, ServiceResult serviceResult) { + + long end = System.nanoTime(); + + String msg = "User {0}: Service {1} took {2}"; //$NON-NLS-1$ + msg = MessageFormat.format(msg, username, service.getClass().getName(), + StringHelper.formatNanoDuration(end - start)); + + if (serviceResult.getState() == ServiceResultState.SUCCESS) { + logger.info(msg); + } else if (serviceResult.getState() == ServiceResultState.WARNING) { + + msg = ServiceResultState.WARNING + " " + msg; + logger.warn(msg); + + if (StringHelper.isNotEmpty(serviceResult.getMessage()) && serviceResult.getThrowable() != null) { + logger.warn("Reason: " + serviceResult.getMessage(), serviceResult.getThrowable()); + } else if (StringHelper.isNotEmpty(serviceResult.getMessage())) { + logger.warn("Reason: " + serviceResult.getMessage()); + } else if (serviceResult.getThrowable() != null) { + logger.warn("Reason: " + serviceResult.getThrowable().getMessage(), serviceResult.getThrowable()); + } + + } else if (serviceResult.getState() == ServiceResultState.FAILED) { + + msg = ServiceResultState.FAILED + " " + msg; + logger.error(msg); + + if (StringHelper.isNotEmpty(serviceResult.getMessage()) && serviceResult.getThrowable() != null) { + logger.error("Reason: " + serviceResult.getMessage(), serviceResult.getThrowable()); + } else if (StringHelper.isNotEmpty(serviceResult.getMessage())) { + logger.error("Reason: " + serviceResult.getMessage()); + } else if (serviceResult.getThrowable() != null) { + logger.error("Reason: " + serviceResult.getThrowable().getMessage(), serviceResult.getThrowable()); + } + } + } } diff --git a/li.strolch.model/src/main/java/li/strolch/exception/StrolchAccessDeniedException.java b/li.strolch.model/src/main/java/li/strolch/exception/StrolchAccessDeniedException.java new file mode 100644 index 000000000..6f882c4c0 --- /dev/null +++ b/li.strolch.model/src/main/java/li/strolch/exception/StrolchAccessDeniedException.java @@ -0,0 +1,64 @@ +/* + * Copyright 2013 Robert von Burg + * + * 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 li.strolch.exception; + +import ch.eitchnet.privilege.model.Certificate; +import ch.eitchnet.privilege.model.Restrictable; + +/** + * @author Robert von Burg + */ +public class StrolchAccessDeniedException extends StrolchException { + + private static final long serialVersionUID = 1L; + + private Certificate certificate; + private Restrictable restrictable; + + /** + * + * @param certificate + * @param restrictable + * @param message + * @param cause + */ + public StrolchAccessDeniedException(Certificate certificate, Restrictable restrictable, String message, + Throwable cause) { + super(message, cause); + this.certificate = certificate; + this.restrictable = restrictable; + } + + /** + * + * @param certificate + * @param restrictable + * @param message + */ + public StrolchAccessDeniedException(Certificate certificate, Restrictable restrictable, String message) { + super(message); + this.certificate = certificate; + this.restrictable = restrictable; + } + + public Certificate getCertificate() { + return certificate; + } + + public Restrictable getRestrictable() { + return restrictable; + } +} diff --git a/li.strolch.model/src/main/java/li/strolch/model/parameter/AbstractParameter.java b/li.strolch.model/src/main/java/li/strolch/model/parameter/AbstractParameter.java index d749fc55f..04110f754 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/parameter/AbstractParameter.java +++ b/li.strolch.model/src/main/java/li/strolch/model/parameter/AbstractParameter.java @@ -227,8 +227,8 @@ public abstract class AbstractParameter extends AbstractStrolchElement implem */ protected void validateValue(T value) throws StrolchException { if (value == null) { - String msg = "{0} Parameter {1} may not have a null value!"; //$NON-NLS-1$ - msg = MessageFormat.format(msg, getType(), getId()); + String msg = "Can not set null value on Parameter {0}"; //$NON-NLS-1$ + msg = MessageFormat.format(msg, getLocator()); throw new StrolchException(msg); } } diff --git a/li.strolch.rest/src/main/java/li/strolch/rest/StrolchRestfulExceptionMapper.java b/li.strolch.rest/src/main/java/li/strolch/rest/StrolchRestfulExceptionMapper.java index 02c4b9e17..f4f52a07b 100644 --- a/li.strolch.rest/src/main/java/li/strolch/rest/StrolchRestfulExceptionMapper.java +++ b/li.strolch.rest/src/main/java/li/strolch/rest/StrolchRestfulExceptionMapper.java @@ -4,12 +4,16 @@ import java.text.MessageFormat; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; +import li.strolch.exception.StrolchAccessDeniedException; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import ch.eitchnet.privilege.model.Restrictable; import ch.eitchnet.utils.helper.StringHelper; @Provider @@ -19,7 +23,29 @@ public class StrolchRestfulExceptionMapper implements ExceptionMapper @Override public Response toResponse(Exception ex) { + logger.error(MessageFormat.format("Handling exception {0}", ex.getClass()), ex); //$NON-NLS-1$ - return Response.status(500).entity(StringHelper.formatExceptionMessage(ex)).type(MediaType.TEXT_PLAIN).build(); + + if (ex instanceof StrolchAccessDeniedException) { + StrolchAccessDeniedException e = (StrolchAccessDeniedException) ex; + StringBuilder sb = new StringBuilder(); + sb.append("User "); + sb.append(e.getCertificate().getUsername()); + sb.append(" does not have access to "); + Restrictable restrictable = e.getRestrictable(); + if (restrictable == null) { + sb.append(StringHelper.NULL); + } else { + sb.append(restrictable.getPrivilegeName()); + sb.append(" - "); + sb.append(restrictable.getPrivilegeValue()); + } + + return Response.status(Status.FORBIDDEN).entity(sb.toString()).type(MediaType.TEXT_PLAIN).build(); + } + + String exceptionMessage = StringHelper.formatExceptionMessage(ex); + return Response.status(Status.INTERNAL_SERVER_ERROR).entity(exceptionMessage).type(MediaType.TEXT_PLAIN) + .build(); } } \ No newline at end of file