Harden item creation by checking for validity of name (#1825)

Signed-off-by: Kai Kreuzer <kai@openhab.org>
pull/1837/head
Kai Kreuzer 2020-11-18 00:18:00 +01:00 committed by GitHub
parent d5e7fe3ab3
commit 70ca7655a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 61 additions and 32 deletions

View File

@ -576,8 +576,8 @@ public class ItemResource implements RESTResource {
@SecurityRequirement(name = "oauth2", scopes = { "admin" }) }, responses = {
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = String.class))),
@ApiResponse(responseCode = "201", description = "Item created."),
@ApiResponse(responseCode = "400", description = "Item null."),
@ApiResponse(responseCode = "404", description = "Item not found."),
@ApiResponse(responseCode = "400", description = "Payload invalid."),
@ApiResponse(responseCode = "404", description = "Item not found or name in path invalid."),
@ApiResponse(responseCode = "405", description = "Item not editable.") })
public Response createOrUpdateItem(final @Context UriInfo uriInfo, final @Context HttpHeaders httpHeaders,
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @Parameter(description = "language") @Nullable String language,
@ -588,31 +588,42 @@ public class ItemResource implements RESTResource {
// If we didn't get an item bean, then return!
if (item == null) {
return Response.status(Status.BAD_REQUEST).build();
}
Item newItem = ItemDTOMapper.map(item, itemBuilderFactory);
if (newItem == null) {
logger.warn("Received HTTP PUT request at '{}' with an invalid item type '{}'.", uriInfo.getPath(),
item.type);
} else if (!itemname.equalsIgnoreCase((item.name))) {
logger.warn(
"Received HTTP PUT request at '{}' with an item name '{}' that does not match the one in the url.",
uriInfo.getPath(), item.name);
return Response.status(Status.BAD_REQUEST).build();
}
// Save the item
if (getItem(itemname) == null) {
// item does not yet exist, create it
managedItemProvider.add(newItem);
return getItemResponse(uriBuilder(uriInfo, httpHeaders), Status.CREATED, itemRegistry.get(itemname), locale,
null);
} else if (managedItemProvider.get(itemname) != null) {
// item already exists as a managed item, update it
managedItemProvider.update(newItem);
return getItemResponse(uriBuilder(uriInfo, httpHeaders), Status.OK, itemRegistry.get(itemname), locale,
null);
} else {
// Item exists but cannot be updated
logger.warn("Cannot update existing item '{}', because is not managed.", itemname);
return JSONResponse.createErrorResponse(Status.METHOD_NOT_ALLOWED,
"Cannot update non-managed Item " + itemname);
try {
Item newItem = ItemDTOMapper.map(item, itemBuilderFactory);
if (newItem == null) {
logger.warn("Received HTTP PUT request at '{}' with an invalid item type '{}'.", uriInfo.getPath(),
item.type);
return Response.status(Status.BAD_REQUEST).build();
}
// Save the item
if (getItem(itemname) == null) {
// item does not yet exist, create it
managedItemProvider.add(newItem);
return getItemResponse(uriBuilder(uriInfo, httpHeaders), Status.CREATED, itemRegistry.get(itemname),
locale, null);
} else if (managedItemProvider.get(itemname) != null) {
// item already exists as a managed item, update it
managedItemProvider.update(newItem);
return getItemResponse(uriBuilder(uriInfo, httpHeaders), Status.OK, itemRegistry.get(itemname), locale,
null);
} else {
// Item exists but cannot be updated
logger.warn("Cannot update existing item '{}', because is not managed.", itemname);
return JSONResponse.createErrorResponse(Status.METHOD_NOT_ALLOWED,
"Cannot update non-managed Item " + itemname);
}
} catch (IllegalArgumentException e) {
logger.warn("Received HTTP PUT request at '{}' with an invalid item name '{}'.", uriInfo.getPath(),
item.name);
return Response.status(Status.BAD_REQUEST).build();
}
}
@ -628,7 +639,7 @@ public class ItemResource implements RESTResource {
@Operation(summary = "Adds a list of items to the registry or updates the existing items.", security = {
@SecurityRequirement(name = "oauth2", scopes = { "admin" }) }, responses = {
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = String.class))),
@ApiResponse(responseCode = "400", description = "Item list is null.") })
@ApiResponse(responseCode = "400", description = "Payload is invalid.") })
public Response createOrUpdateItems(
@Parameter(description = "array of item data", required = true) GroupItemDTO @Nullable [] items) {
// If we didn't get an item list bean, then return!
@ -641,12 +652,17 @@ public class ItemResource implements RESTResource {
Map<String, Collection<String>> tagMap = new HashMap<>();
for (GroupItemDTO item : items) {
Item newItem = ItemDTOMapper.map(item, itemBuilderFactory);
if (newItem == null) {
wrongTypes.add(item);
tagMap.put(item.name, item.tags);
} else {
activeItems.add(newItem);
try {
Item newItem = ItemDTOMapper.map(item, itemBuilderFactory);
if (newItem == null) {
wrongTypes.add(item);
tagMap.put(item.name, item.tags);
} else {
activeItems.add(newItem);
}
} catch (IllegalArgumentException e) {
logger.warn("Received HTTP PUT request with an invalid item name '{}'.", item.name);
return Response.status(Status.BAD_REQUEST).build();
}
}

View File

@ -84,7 +84,7 @@ public class ManagedItemProvider extends AbstractManagedProvider<Item, String, P
}
/**
* Removes an item and it´s member if recursive flag is set to true.
* Removes an item and its member if recursive flag is set to true.
*
* @param itemName item name to remove
* @param recursive if set to true all members of the item will be removed, too.
@ -105,6 +105,14 @@ public class ManagedItemProvider extends AbstractManagedProvider<Item, String, P
}
}
@Override
public void add(Item element) {
if (!ItemUtil.isValidItemName(element.getName())) {
throw new IllegalArgumentException("The item name '" + element.getName() + "' is invalid.");
}
super.add(element);
}
private List<String> getMemberNamesRecursively(GroupItem groupItem, Collection<Item> allItems) {
List<String> memberNames = new ArrayList<>();
for (Item item : allItems) {

View File

@ -23,6 +23,7 @@ import org.openhab.core.items.GroupItem;
import org.openhab.core.items.Item;
import org.openhab.core.items.ItemBuilder;
import org.openhab.core.items.ItemBuilderFactory;
import org.openhab.core.items.ItemUtil;
import org.openhab.core.types.State;
/**
@ -52,6 +53,10 @@ public class ItemDTOMapper {
throw new IllegalArgumentException("The argument 'itemBuilderFactory' must no be null.");
}
if (!ItemUtil.isValidItemName(itemDTO.name)) {
throw new IllegalArgumentException("The item name '" + itemDTO.name + "' is invalid.");
}
if (itemDTO.type != null) {
ItemBuilder builder = itemBuilderFactory.newItemBuilder(itemDTO.type, itemDTO.name);