diff --git a/smartapps/vlaminck/alfred-workflow.src/alfred-workflow.groovy b/smartapps/vlaminck/alfred-workflow.src/alfred-workflow.groovy index 3d5f955..3170ee5 100644 --- a/smartapps/vlaminck/alfred-workflow.src/alfred-workflow.groovy +++ b/smartapps/vlaminck/alfred-workflow.src/alfred-workflow.groovy @@ -92,22 +92,87 @@ void updateLock() { private void updateAll(devices) { def command = request.JSON?.command - if (command) { - devices."$command"() + def type = params.param1 + if (!devices) { + httpError(404, "Devices not found") + } + + if (command){ + devices.each { device -> + executeCommand(device, type, command) + } } } private void update(devices) { log.debug "update, request: ${request.JSON}, params: ${params}, devices: $devices.id" def command = request.JSON?.command - if (command) { - def device = devices.find { it.id == params.id } - if (!device) { - httpError(404, "Device not found") - } else { - device."$command"() - } + def type = params.param1 + def device = devices?.find { it.id == params.id } + + if (!device) { + httpError(404, "Device not found") } + + if (command) { + executeCommand(device, type, command) + } +} + +/** + * Validating the command passed by the user based on capability. + * @return boolean + */ +def validateCommand(device, deviceType, command) { + def capabilityCommands = getDeviceCapabilityCommands(device.capabilities) + def currentDeviceCapability = getCapabilityName(deviceType) + if (capabilityCommands[currentDeviceCapability]) { + return command in capabilityCommands[currentDeviceCapability] ? true : false + } else { + // Handling other device types here, which don't accept commands + httpError(400, "Bad request.") + } +} + +/** + * Need to get the attribute name to do the lookup. Only + * doing it for the device types which accept commands + * @return attribute name of the device type + */ +def getCapabilityName(type) { + switch(type) { + case "switches": + return "Switch" + case "locks": + return "Lock" + default: + return type + } +} + +/** + * Constructing the map over here of + * supported commands by device capability + * @return a map of device capability -> supported commands + */ +def getDeviceCapabilityCommands(deviceCapabilities) { + def map = [:] + deviceCapabilities.collect { + map[it.name] = it.commands.collect{ it.name.toString() } + } + return map +} + +/** + * Validates and executes the command + * on the device or devices + */ +def executeCommand(device, type, command) { + if (validateCommand(device, type, command)) { + device."$command"() + } else { + httpError(403, "Access denied. This command is not supported by current capability.") + } } private show(devices, name) {