Skip to content

Commit

Permalink
Merge pull request #4199 from Coduz/fix-serviceConfigHttpValueForForb…
Browse files Browse the repository at this point in the history
…iddenChange

🐛 [Service Config] Fixed returned exception when forbidden change is detected
  • Loading branch information
Coduz authored Feb 20, 2025
2 parents bcecec0 + 04bb621 commit 71d2410
Show file tree
Hide file tree
Showing 10 changed files with 320 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*******************************************************************************
* Copyright (c) 2025, 2025 Eurotech and/or its affiliates and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Eurotech - initial API and implementation
*******************************************************************************/
package org.eclipse.kapua.commons.rest.errors;

import org.eclipse.kapua.commons.configuration.exception.ServiceConfigurationForbiddenException;
import org.eclipse.kapua.commons.rest.model.errors.ServiceConfigurationUpdateForbiddenExceptionInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
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;

@Provider
public class ServiceConfigurationUpdateForbiddenExceptionMapper implements ExceptionMapper<ServiceConfigurationForbiddenException> {

private static final Logger LOG = LoggerFactory.getLogger(ServiceConfigurationUpdateForbiddenExceptionMapper.class);

private final boolean showStackTrace;

@Inject
public ServiceConfigurationUpdateForbiddenExceptionMapper(ExceptionConfigurationProvider exceptionConfigurationProvider) {
this.showStackTrace = exceptionConfigurationProvider.showStackTrace();
}

@Override
public Response toResponse(ServiceConfigurationForbiddenException serviceConfigurationForbiddenException) {
LOG.error(serviceConfigurationForbiddenException.getMessage(), serviceConfigurationForbiddenException);

return Response
.status(Status.FORBIDDEN)
.entity(new ServiceConfigurationUpdateForbiddenExceptionInfo(serviceConfigurationForbiddenException, showStackTrace))
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*******************************************************************************
* Copyright (c) 2025, 2025 Eurotech and/or its affiliates and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Eurotech - initial API and implementation
*******************************************************************************/
package org.eclipse.kapua.commons.rest.model.errors;

import org.eclipse.kapua.commons.configuration.exception.ServiceConfigurationForbiddenException;
import org.eclipse.kapua.model.config.metatype.KapuaTad;
import org.eclipse.kapua.model.id.KapuaId;
import org.eclipse.kapua.model.id.KapuaIdAdapter;
import org.eclipse.kapua.service.config.KapuaConfigurableService;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlRootElement(name = "serviceConfigurationUpdateForbiddenExceptionInfo")
@XmlAccessorType(XmlAccessType.FIELD)
public class ServiceConfigurationUpdateForbiddenExceptionInfo extends ExceptionInfo {

@XmlElement(name = "scopeId")
@XmlJavaTypeAdapter(KapuaIdAdapter.class)
private KapuaId scopeId;

@XmlElement(name = "servicePid")
private String servicePid;

@XmlElement(name = "propertyId")
private String propertyId;

@XmlElement(name = "propertyValue")
private String propertyValue;

/**
* Constructor.
*
* @since 2.1.0
*/
protected ServiceConfigurationUpdateForbiddenExceptionInfo() {
super();
}

/**
* Constructor.
*
* @param serviceConfigurationForbiddenException The original exception.
* @since 2.1.0
*/
public ServiceConfigurationUpdateForbiddenExceptionInfo(ServiceConfigurationForbiddenException serviceConfigurationForbiddenException, boolean showStackTrace) {
super(403/*Response.Status.FORBIDDEN*/, serviceConfigurationForbiddenException, showStackTrace);

this.servicePid = serviceConfigurationForbiddenException.getServicePid();
this.scopeId = serviceConfigurationForbiddenException.getScopeId();
this.propertyId = serviceConfigurationForbiddenException.getPropertyId();
this.propertyValue = serviceConfigurationForbiddenException.getPropertyValue();
}

/**
* Gets the scope {@link KapuaId} for which the update is forbidden.
*
* @return The scope {@link KapuaId} for which the update is forbidden.
* @since 2.1.0
*/
public KapuaId getScopeId() {
return scopeId;
}

/**
* Gets the {@link KapuaConfigurableService} pid.
*
* @return he {@link KapuaConfigurableService} pid.
* @since 2.1.0
*/
public String getServicePid() {
return servicePid;
}

/**
* Gets the {@link KapuaTad#getId()} for which the update is forbidden.
*
* @return The {@link KapuaTad#getId()} for which the update is forbidden.
* @since 2.1.0
*/
public String getPropertyId() {
return propertyId;
}

/**
* Gets the {@link KapuaTad} value for which the update is forbidden.
*
* @return The {@link KapuaTad} value for which the update is forbidden.
* @since 2.1.0
*/
public String getPropertyValue() {
return propertyValue;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.eclipse.kapua.KapuaException;
import org.eclipse.kapua.KapuaIllegalArgumentException;
import org.eclipse.kapua.KapuaIllegalNullArgumentException;
import org.eclipse.kapua.commons.configuration.exception.ServiceConfigurationForbiddenException;
import org.eclipse.kapua.commons.security.KapuaSecurityUtils;
import org.eclipse.kapua.commons.util.ArgumentValidator;
import org.eclipse.kapua.commons.util.StringUtil;
Expand Down Expand Up @@ -154,7 +155,7 @@ public void setConfigValues(KapuaId scopeId, Optional<KapuaId> parentId, Map<Str

if (preventChange) {
// ... prevent the change!
throw KapuaException.internalError(String.format("The configuration \"%s\" cannot be changed by this user in this account", ad.getId()));
throw new ServiceConfigurationForbiddenException(scopeId, pid, ad.getId(), String.valueOf(values.get(ad.getId())));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,10 @@ public enum KapuaConfigurationErrorCodes implements KapuaErrorCode {
* @since 2.0.0
*/
PARENT_LIMIT_EXCEEDED_BY,

/**
* @see ServiceConfigurationForbiddenException
* @since 2.1.0
*/
UPDATE_PROPERTY_FORBIDDEN,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*******************************************************************************
* Copyright (c) 2025, 2025 Eurotech and/or its affiliates and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Eurotech - initial API and implementation
*******************************************************************************/
package org.eclipse.kapua.commons.configuration.exception;

import org.eclipse.kapua.model.config.metatype.KapuaTad;
import org.eclipse.kapua.model.id.KapuaId;
import org.eclipse.kapua.service.account.Account;
import org.eclipse.kapua.service.config.KapuaConfigurableService;
import org.eclipse.kapua.service.config.ServiceComponentConfiguration;
import org.eclipse.kapua.service.user.User;

/**
* {@link KapuaConfigurationException} to {@code throw} when an update of a {@link ServiceComponentConfiguration#getProperties()} contains updates to values that cannot be updated by the curren {@link User}.
* <p>
* {@link ServiceComponentConfiguration#getProperties()} can be updated under the following conditions:
* <ul>
* <li>If the current {@link User} is root. Root {@link User} can do whatever he wants</li>
* <li>If the {@link KapuaTad} is marked to allow self-edit. For those properties a {@link User} can update the values for its {@link Account}</li>
* <li>If the {@link ServiceComponentConfiguration} belongs to a child {@link Account} of the current {@link User}</li>
* </ul>
*
* @since 2.1.0
*/
public class ServiceConfigurationForbiddenException extends KapuaConfigurationException {

private final KapuaId scopeId;
private final String servicePid;

private final String propertyId;

private final String propertyValue;

/**
* Constructor.
*
* @param servicePid The {@link KapuaConfigurableService} pid.
* @param scopeId The scope {@link KapuaId} for which limit has been exceeded.
* @param propertyId The {@link KapuaTad#getId()} for which the update is forbidden.
* @param propertyValue The {@link KapuaTad} value for which the update is forbidden.
* @since 2.0.0
*/
public ServiceConfigurationForbiddenException(KapuaId scopeId, String servicePid, String propertyId, String propertyValue) {
super(KapuaConfigurationErrorCodes.UPDATE_PROPERTY_FORBIDDEN, scopeId, servicePid, propertyId, propertyValue);

this.scopeId = scopeId;
this.servicePid = servicePid;
this.propertyId = propertyId;
this.propertyValue = propertyValue;
}

/**
* Gets the scope {@link KapuaId} for which the update is forbidden.
*
* @return The scope {@link KapuaId} for which the update is forbidden.
* @since 2.1.0
*/
public KapuaId getScopeId() {
return scopeId;
}

/**
* Gets the {@link KapuaConfigurableService} pid for which the update is forbidden.
*
* @return he {@link KapuaConfigurableService} pid for which the update is forbidden.
* @since 2.1.0
*/
public String getServicePid() {
return servicePid;
}

/**
* Gets the {@link KapuaTad#getId()} for which the update is forbidden.
*
* @return The {@link KapuaTad#getId()} for which the update is forbidden.
* @since 2.1.0
*/
public String getPropertyId() {
return propertyId;
}

/**
* Gets the {@link KapuaTad} value for which the update is forbidden.
*
* @return The {@link KapuaTad} value for which the update is forbidden.
* @since 2.1.0
*/
public String getPropertyValue() {
return propertyValue;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ LIMIT_EXCEEDED=The maximum of resources for the {0} service for the account {1}
LIMIT_EXCEEDED_BY=The maximum of resources for the {0} service for the account {1} has been exceeded. The resource limit is exceeded by {2}.
PARENT_LIMIT_EXCEEDED=The maximum of resources for the {0} service for the parent account {1} has been exceeded.
PARENT_LIMIT_EXCEEDED_BY=The maximum of resources for the {0} service for the parent account {1} has been exceeded. The resource limit is exceeded by {2}.
UPDATE_PROPERTY_FORBIDDEN=Current User cannot update property {2} of ServiceComponentConfiguration {1} of Account {0} with value {3}
2 changes: 2 additions & 0 deletions rest-api/resources/src/main/resources/openapi/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1200,6 +1200,8 @@ components:
$ref: './serviceConfiguration/serviceConfiguration.yaml#/components/schemas/option'
serviceAttributeDefinition:
$ref: './serviceConfiguration/serviceConfiguration.yaml#/components/schemas/attributeDefinition'
serviceConfigurationUpdateForbiddenExceptionInfo:
$ref: './serviceConfiguration/serviceConfiguration.yaml#/components/schemas/serviceConfigurationUpdateForbiddenExceptionInfo'
### System Info Entities ###
systemInfo:
$ref: './systemInfo/systemInfo.yaml#/components/schemas/systemInfo'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,20 @@ paths:
401:
$ref: '../openapi.yaml#/components/responses/unauthenticated'
403:
$ref: '../openapi.yaml#/components/responses/subjectUnauthorized'
description: The requested update is forbidden
content:
application/json:
schema:
oneOf:
- $ref: '../openapi.yaml#/components/schemas/subjectUnauthorizedExceptionInfo'
- $ref: './serviceConfiguration.yaml#/components/schemas/serviceConfigurationUpdateForbiddenExceptionInfo'
application/xml:
schema:
oneOf:
- $ref: '../openapi.yaml#/components/schemas/subjectUnauthorizedExceptionInfo'
- $ref: './serviceConfiguration.yaml#/components/schemas/serviceConfigurationUpdateForbiddenExceptionInfo'
xml:
name: 'serviceConfigurationUpdateForbiddenExceptionInfo'
404:
$ref: '../openapi.yaml#/components/responses/entityNotFound'
500:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,20 @@ paths:
401:
$ref: '../openapi.yaml#/components/responses/unauthenticated'
403:
$ref: '../openapi.yaml#/components/responses/subjectUnauthorized'
description: The requested update is forbidden
content:
application/json:
schema:
oneOf:
- $ref: '../openapi.yaml#/components/schemas/subjectUnauthorizedExceptionInfo'
- $ref: './serviceConfiguration.yaml#/components/schemas/serviceConfigurationUpdateForbiddenExceptionInfo'
application/xml:
schema:
oneOf:
- $ref: '../openapi.yaml#/components/schemas/subjectUnauthorizedExceptionInfo'
- $ref: './serviceConfiguration.yaml#/components/schemas/serviceConfigurationUpdateForbiddenExceptionInfo'
xml:
name: 'serviceConfigurationUpdateForbiddenExceptionInfo'
404:
$ref: '../openapi.yaml#/components/responses/entityNotFound'
500:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -378,3 +378,30 @@ components:
size:
type: integer

### Exception Info
serviceConfigurationUpdateForbiddenExceptionInfo:
description: The update of the configuration for the service contains an update to a property than cannot be updated
allOf:
- $ref: '../openapi.yaml#/components/schemas/exceptionInfo'
- properties:
scopeId:
description: The scope for which the update is forbidden
$ref: '../openapi.yaml#/components/schemas/kapuaId'
servicePid:
type: string
description: The Pid of the service
propertyId:
type: string
description: The property id for which the update is forbidden.
propertyValue:
type: string
description: The property value for which the update is forbidden.
example:
type: "serviceConfigurationUpdateForbiddenExceptionInfo"
httpErrorCode: 403
message: "Current User cannot update property maxNumberChildEntities of ServiceComponentConfiguration org.eclipse.kapua.service.account.AccountService of Account 2 with value 10"
kapuaErrorCode: "UPDATE_PROPERTY_FORBIDDEN"
scopeId: 2
servicePid: "org.eclipse.kapua.service.account.AccountService"
propertyId: "maxNumberChildEntities"
propertyValue: "10"

0 comments on commit 71d2410

Please sign in to comment.