/* * Copyright 2014-2016 CyberVision, Inc. * * 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 org.kaaproject.kaa.server.admin.controller; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; import org.kaaproject.kaa.common.dto.EndpointNotificationDto; import org.kaaproject.kaa.common.dto.NotificationDto; import org.kaaproject.kaa.common.dto.NotificationSchemaDto; import org.kaaproject.kaa.common.dto.TopicDto; import org.kaaproject.kaa.common.dto.VersionDto; import org.kaaproject.kaa.server.admin.shared.services.KaaAdminServiceException; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.multipart.MultipartFile; import java.util.List; @Api(value = "Notifications", description = "Provides function for manage notifications", basePath = "/kaaAdmin/rest") @Controller public class NotificationController extends AbstractAdminController { /** * Gets the notification schemas by application token. * * @param applicationToken the application token * @return the list notification schema dto * @throws KaaAdminServiceException the kaa admin service exception */ @ApiOperation(value = "Get notification schemas", notes = "Returns notification schemas for an application. Only users with " + "the TENANT_DEVELOPER or TENANT_USER role are allowed to request this " + "information. The Tenant ID value of the application must match the Tenant ID " + "of the request submitter.") @ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid endpointGroupId supplied"), @ApiResponse(code = 401, message = "The user is not authenticated or invalid credentials were provided"), @ApiResponse(code = 403, message = "The authenticated user does not have the required role " + "(TENANT_DEVELOPER or TENANT_USER) or the Tenant ID " + "of the application does not match the Tenant ID of the authenticated user"), @ApiResponse(code = 404, message = "An application with the specified applicationToken does not exist"), @ApiResponse(code = 500, message = "An unexpected error occurred on the server side")}) @RequestMapping(value = "notificationSchemas/{applicationToken}", method = RequestMethod.GET) @ResponseBody public List<NotificationSchemaDto> getNotificationSchemasByApplicationToken( @ApiParam(name = "applicationToken", value = "A unique auto-generated application identifier", required = true) @PathVariable String applicationToken) throws KaaAdminServiceException { return notificationService.getNotificationSchemasByApplicationToken(applicationToken); } /** * Gets the user notification schemas by application token. * * @param applicationToken the application token * @return the list schema dto * @throws KaaAdminServiceException the kaa admin service exception */ @ApiOperation(value = "Get user notification schemas", notes = "Returns user notification schemas for an application. " + "Only users with the TENANT_DEVELOPER or TENANT_USER role are allowed to request " + "this information.") @ApiResponses(value = { @ApiResponse(code = 401, message = "The user is not authenticated or invalid credentials were provided"), @ApiResponse(code = 403, message = "The authenticated user does not have the required role " + "(TENANT_DEVELOPER or TENANT_USER) or the Tenant ID " + "of the application does not match the Tenant ID of the authenticated user"), @ApiResponse(code = 404, message = "An application with the specified applicationToken does not exist"), @ApiResponse(code = 500, message = "An unexpected error occurred on the server side")}) @RequestMapping(value = "userNotificationSchemas/{applicationToken}", method = RequestMethod.GET) @ResponseBody public List<VersionDto> getUserNotificationSchemasByApplicationToken( @ApiParam(name = "applicationToken", value = "A unique auto-generated application identifier", required = true) @PathVariable String applicationToken) throws KaaAdminServiceException { return notificationService.getUserNotificationSchemasByApplicationToken(applicationToken); } /** * Gets the notification schema by her id. * * @param notificationSchemaId the notification schema id * @return the notification schema dto * @throws KaaAdminServiceException the kaa admin service exception */ @ApiOperation(value = "Get notification schema", notes = "Returns a notification schema by notification schema ID. " + "Only users with the TENANT_DEVELOPER or TENANT_USER role are allowed to " + "request this information.") @ApiResponses(value = { @ApiResponse(code = 401, message = "The user is not authenticated or invalid credentials were provided"), @ApiResponse(code = 403, message = "The authenticated user does not have the required role " + "(TENANT_DEVELOPER or TENANT_USER) or the Tenant ID " + "of the application does not match the Tenant ID of the authenticated user"), @ApiResponse(code = 404, message = "A notification schema with the specified " + "notificationSchemaId does not exist"), @ApiResponse(code = 500, message = "An unexpected error occurred on the server side")}) @RequestMapping(value = "notificationSchema/{notificationSchemaId}", method = RequestMethod.GET) @ResponseBody public NotificationSchemaDto getNotificationSchema( @ApiParam(name = "notificationSchemaId", value = "A unique notification schema identifier", required = true) @PathVariable String notificationSchemaId) throws KaaAdminServiceException { return notificationService.getNotificationSchema(notificationSchemaId); } /** * Adds notification schema to the list of all notification schemas. * * @param notificationSchema the notification schema * @return the notification schema dto * @throws KaaAdminServiceException the kaa admin service exception */ @RequestMapping(value = "createNotificationSchema", method = RequestMethod.POST) @ResponseBody public NotificationSchemaDto createNotificationSchema( @RequestBody NotificationSchemaDto notificationSchema) throws KaaAdminServiceException { return notificationService.saveNotificationSchema(notificationSchema); } /** * Edits existing notification schema. * * @param notificationSchema the notification schema * @return the notification schema dto * @throws KaaAdminServiceException the kaa admin service exception */ @ApiOperation(value = "Create/Edit notification schema", notes = "Creates or updates a notification schema. To create notification schema " + "you do not need to specify the notification schema ID, " + "createUsername field of the schema will be set to the name of the user " + "who has uploaded it, a unique version number will be generated " + "(incrementally) for this schema. To edit the notification schema " + "specify the notification schema ID. If a notification schema with the " + "specified ID exists, the configuration will be updated. Only users with " + "the TENANT_DEVELOPER or TENANT_USER role are allowed to perform " + "this operation.") @ApiResponses(value = { @ApiResponse(code = 400, message = "The specified notification schema is not a valid avro schema"), @ApiResponse(code = 401, message = "The user is not authenticated or invalid credentials were provided"), @ApiResponse(code = 403, message = "The authenticated user does not have the required role " + "(TENANT_DEVELOPER or TENANT_USER) or the Tenant ID " + "of the application does not match the Tenant ID of the authenticated user"), @ApiResponse(code = 500, message = "An unexpected error occurred on the server side")}) @RequestMapping(value = "saveNotificationSchema", method = RequestMethod.POST) @ResponseBody public NotificationSchemaDto saveNotificationSchema( @ApiParam(name = "notificationSchema", value = "NotificationSchemaDto body.", required = true) @RequestBody NotificationSchemaDto notificationSchema) throws KaaAdminServiceException { return notificationService.saveNotificationSchema(notificationSchema); } /** * Gets all topics by application token. * * @param applicationToken the application token * @return the topic dto * @throws KaaAdminServiceException the kaa admin service exception */ @ApiOperation(value = "Get topics", notes = "Returns all topics for the specified application. " + "Only users with the TENANT_DEVELOPER or TENANT_USER role are allowed to request this " + "information.") @ApiResponses(value = { @ApiResponse(code = 401, message = "The user is not authenticated or invalid credentials were provided"), @ApiResponse(code = 403, message = "The authenticated user does not have the required role " + "(TENANT_DEVELOPER or TENANT_USER) or the Tenant ID " + "of the application does not match the Tenant ID of the authenticated user"), @ApiResponse(code = 404, message = "An application with the specified applicationToken does not exist"), @ApiResponse(code = 500, message = "An unexpected error occurred on the server side")}) @RequestMapping(value = "topics/{applicationToken}", method = RequestMethod.GET) @ResponseBody public List<TopicDto> getTopicsByApplicationToken( @ApiParam(name = "applicationToken", value = "A unique auto-generated application identifier", required = true) @PathVariable String applicationToken) throws KaaAdminServiceException { return notificationService.getTopicsByApplicationToken(applicationToken); } /** * Gets all topics by endpoint group id. * * @param endpointGroupId the endpoint group id * @return the topic dto * @throws KaaAdminServiceException the kaa admin service exception */ @ApiOperation(value = "Get endpoint group topics", notes = "Returns all topics for the specified endpoint group. " + "Only users with the TENANT_DEVELOPER or TENANT_USER role are allowed to request " + "this information.") @ApiResponses(value = { @ApiResponse(code = 401, message = "The user is not authenticated or invalid credentials were provided"), @ApiResponse(code = 403, message = "The authenticated user does not have the required role " + "(TENANT_DEVELOPER or TENANT_USER) or the Tenant ID " + "of the application does not match the Tenant ID of the authenticated user"), @ApiResponse(code = 404, message = "An endpoint group to with the specified endpointGroupId does not exist"), @ApiResponse(code = 500, message = "An unexpected error occurred on the server side")}) @RequestMapping(value = "topics", method = RequestMethod.GET) @ResponseBody public List<TopicDto> getTopicsByEndpointGroupId( @ApiParam(name = "endpointGroupId", value = "A unique endpoint group identifier", required = true) @RequestParam(value = "endpointGroupId") String endpointGroupId) throws KaaAdminServiceException { return notificationService.getTopicsByEndpointGroupId(endpointGroupId); } /** * Gets all vacant topics by endpoint group id. * * @param endpointGroupId the endpoint group id * @return the topic dto * @throws KaaAdminServiceException the kaa admin service exception */ @ApiOperation(value = "Get vacant topics", notes = "Returns all vacant (not present in the endpoint group) topics for " + "the specified endpoint group. Only users with the TENANT_DEVELOPER or " + "TENANT_USER role are allowed to request this information.") @ApiResponses(value = { @ApiResponse(code = 401, message = "The user is not authenticated or invalid credentials were provided"), @ApiResponse(code = 403, message = "The authenticated user does not have the required role " + "(TENANT_DEVELOPER or TENANT_USER) or the Tenant ID " + "of the application does not match the Tenant ID of the authenticated user"), @ApiResponse(code = 404, message = "An endpoint group with the specified endpointGroupId does not exist"), @ApiResponse(code = 500, message = "An unexpected error occurred on the server side")}) @RequestMapping(value = "vacantTopics/{endpointGroupId}", method = RequestMethod.GET) @ResponseBody public List<TopicDto> getVacantTopicsByEndpointGroupId( @ApiParam(name = "endpointGroupId", value = "A unique endpoint group identifier", required = true) @PathVariable String endpointGroupId) throws KaaAdminServiceException { return notificationService.getVacantTopicsByEndpointGroupId(endpointGroupId); } /** * Gets the topic by his id. * * @param topicId the topic id * @return the topic dto * @throws KaaAdminServiceException the kaa admin service exception */ @ApiOperation(value = "Get topic", notes = "Returns a topic by topic ID. Only users with the TENANT_DEVELOPER or " + "TENANT_USER role are allowed to request this information.") @ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid topicId supplied"), @ApiResponse(code = 401, message = "The user is not authenticated or invalid credentials were provided"), @ApiResponse(code = 403, message = "The authenticated user does not have the required role " + "(TENANT_DEVELOPER or TENANT_USER) or the Tenant ID " + "of the application does not match the Tenant ID of the authenticated user"), @ApiResponse(code = 404, message = "The topic with the specified topicId does not exist"), @ApiResponse(code = 500, message = "An unexpected error occurred on the server side")}) @RequestMapping(value = "topic/{topicId}", method = RequestMethod.GET) @ResponseBody public TopicDto getTopic( @ApiParam(name = "topicId", value = "A unique topic identifier", required = true) @PathVariable String topicId) throws KaaAdminServiceException { return notificationService.getTopic(topicId); } /** * Edits topic to the list of all topics. * * @param topic the topic * @return the topic dto * @throws KaaAdminServiceException the kaa admin service exception */ @ApiOperation(value = "Create/Edit topic", notes = "Creates or edits a topic. To create topic you do not need to specify " + "the topic ID. To edit the topic specify the topic ID. If a topic " + "with the specified ID exists, it will be updated. Only users with the " + "TENANT_DEVELOPER or TENANT_USER role are allowed to perform " + "this operation.") @ApiResponses(value = { @ApiResponse(code = 401, message = "The user is not authenticated or invalid credentials were provided"), @ApiResponse(code = 403, message = "The authenticated user does not have the required role " + "(TENANT_DEVELOPER or TENANT_USER) or the Tenant ID " + "of the application does not match the Tenant ID of the authenticated user"), @ApiResponse(code = 404, message = "A topic to be edited with the specified topicId does not exist"), @ApiResponse(code = 500,message = "An unexpected error occurred on the server side")}) @RequestMapping(value = "topic", method = RequestMethod.POST) @ResponseBody public TopicDto editTopic( @ApiParam(name = "topic", value = "TopicDto body. Mandatory fields: applicationId, name, type", required = true) @RequestBody TopicDto topic) throws KaaAdminServiceException { return notificationService.editTopic(topic); } /** * Delete topic by its id. * * @param topicId the topic id * @throws KaaAdminServiceException the kaa admin service exception */ @ApiOperation(value = "Delete topic", notes = "Deletes a topic. Only users with the TENANT_DEVELOPER or " + "TENANT_USER role are allowed to perform this operation.") @ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid topicId supplied"), @ApiResponse(code = 401, message = "The user is not authenticated or invalid credentials were provided"), @ApiResponse(code = 403, message = "The authenticated user does not have the required role " + "(TENANT_DEVELOPER or TENANT_USER) or the Tenant ID " + "of the application does not match the Tenant ID of the authenticated user"), @ApiResponse(code = 404, message = "The topic with the specified topicId does not exist"), @ApiResponse(code = 500, message = "An unexpected error occurred on the server side")}) @RequestMapping(value = "delTopic", method = RequestMethod.POST) @ResponseStatus(value = HttpStatus.OK) public void deleteTopic( @ApiParam(name = "topicId", value = "A unique topic identifier", required = true) @RequestParam(value = "topicId") String topicId) throws KaaAdminServiceException { notificationService.deleteTopic(topicId); } /** * Adds the topic with specific id to endpoint group with specific id. * * @param endpointGroupId the endpoint group id * @param topicId the topic id * @throws KaaAdminServiceException the kaa admin service exception */ @ApiOperation(value = "Add topic to endpoint group", notes = "Adds the specified topic to the specified endpoint group. " + "Only users with the TENANT_DEVELOPER or TENANT_USER role are allowed to " + "perform this operation.") @ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid endpointGroupId supplied"), @ApiResponse(code = 401, message = "The user is not authenticated or invalid credentials were provided"), @ApiResponse(code = 403, message = "The authenticated user does not have the required role " + "(TENANT_DEVELOPER or TENANT_USER) or the Tenant ID " + "of the application does not match the Tenant ID of the authenticated user"), @ApiResponse(code = 404, message = "A topic with the specified topicId or an endpoint " + "group with the specified endpointGroupId does not exist"), @ApiResponse(code = 500, message = "An unexpected error occurred on the server side")}) @RequestMapping(value = "addTopicToEpGroup", method = RequestMethod.POST) @ResponseStatus(value = HttpStatus.OK) public void addTopicToEndpointGroup( @ApiParam(name = "endpointGroupId", value = "A unique endpoint group identifier", required = true) @RequestParam(value = "endpointGroupId") String endpointGroupId, @ApiParam(name = "topicId", value = "A unique topic identifier", required = true) @RequestParam(value = "topicId") String topicId) throws KaaAdminServiceException { notificationService.addTopicToEndpointGroup(endpointGroupId, topicId); } /** * Removes the topic with specific id to endpoint group with specific id. * * @param endpointGroupId the endpoint group id * @param topicId the topic id * @throws KaaAdminServiceException the kaa admin service exception */ @ApiOperation(value = "Remove topic from endpoint group", notes = "Removes the specified topic from the specified endpoint group. " + "Only users with the TENANT_DEVELOPER or TENANT_USER role are allowed " + "to perform this operation.") @ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid endpointGroupId supplied"), @ApiResponse(code = 401, message = "The user is not authenticated or invalid credentials were provided"), @ApiResponse(code = 403, message = "The authenticated user does not have the required role " + "(TENANT_DEVELOPER or TENANT_USER) or the Tenant ID " + "of the application does not match the Tenant ID of the authenticated user"), @ApiResponse(code = 404, message = "A topic with the specified topicId or " + "an endpoint group with the specified endpointGroupId does not exist"), @ApiResponse(code = 500, message = "An unexpected error occurred on the server side")}) @RequestMapping(value = "removeTopicFromEpGroup", method = RequestMethod.POST) @ResponseStatus(value = HttpStatus.OK) public void removeTopicFromEndpointGroup( @ApiParam(name = "endpointGroupId", value = "A unique endpoint group identifier", required = true) @RequestParam(value = "endpointGroupId") String endpointGroupId, @ApiParam(name = "topicId", value = "A unique topic identifier", required = true) @RequestParam(value = "topicId") String topicId) throws KaaAdminServiceException { notificationService.removeTopicFromEndpointGroup(endpointGroupId, topicId); } /** * Send notification, with information from specific file, to the client. * * @param notification the notification * @param file the file * @return the notification dto * @throws KaaAdminServiceException the kaa admin service exception */ @ApiOperation(value = "Send notification", notes = "Sends a notification with the notification body " + "from the specified file. Only users with the TENANT_DEVELOPER or TENANT_USER role are" + " allowed to perform this operation. If you want to set notification time to leave," + " you must set expiredAt field in the parameter " + "notification. If your notification schema contains one field \"message\" " + "with Union type, notification body from the specified file " + "looks like below: " + "```{" + " \"message\" : {" + " \"string\" : \"Hello world!\"" + " }" + "}```. " + "And for primitive string type of the field \"message\" " + "notification body from the specified file looks like below: " + "```{" + " \"message\" : \"Hello world!\"" + "}```") @ApiResponses(value = { @ApiResponse(code = 400, message = "The specified notification is not valid"), @ApiResponse(code = 401, message = "The user is not authenticated or invalid credentials were provided"), @ApiResponse(code = 403, message = "The authenticated user does not have the required role " + "(TENANT_DEVELOPER or TENANT_USER) or the Tenant ID " + "of the application does not match the Tenant ID of the authenticated user"), @ApiResponse(code = 404, message = "A file with the notification body " + "was not found in the form data or an application with the specified ID " + "does not exist or a topic with the specified ID does not exist"), @ApiResponse(code = 500, message = "An unexpected error occurred on the server side")}) @RequestMapping(value = "sendNotification", method = RequestMethod.POST, consumes = {"multipart/mixed", "multipart/form-data"}) @ResponseBody public NotificationDto sendNotification( @ApiParam(name = "notification", value = "NotificationDto body. Mandatory fields: applicationId, schemaId, topicId, type", required = true) @RequestPart("notification") NotificationDto notification, @ApiParam(name = "file", value = "A file with notification body according to the specified " + "notification schema represented in json format", required = true) @RequestPart("file") MultipartFile file) throws KaaAdminServiceException { byte[] data = getFileContent(file); return notificationService.sendNotification(notification, data); } /** * Send unicast notification, with information from specific file, to the * client identified by endpointKeyHash. * * @param notification the notification * @param clientKeyHash the client key hash * @param file the file * @return the endpoint notification dto * @throws KaaAdminServiceException the kaa admin service exception */ @ApiOperation(value = "Send unicast notification", notes = "Sends a unicast notification with the notification body from the specified " + "file to the client identified by endpointKeyHash. Only users " + "with the TENANT_DEVELOPER or TENANT_USER role are allowed to perform this operation." + " If you want to set notification time to leave, " + "you must set expiredAt field in the parameter notification. " + "If your notification schema contains one field \"message\" with Union type, " + "notification body from the specified file looks like below: " + "```{" + " \"message\" : {" + " \"string\" : \"Hello world!\"" + " }" + "}```. " + "And for primitive string type of the field \"message\" " + "notification body from the specified file looks like below: " + "```{" + " \"message\" : \"Hello world!\"" + "}```") @ApiResponses(value = { @ApiResponse(code = 400, message = "The specified notification is not valid"), @ApiResponse(code = 401, message = "The user is not authenticated or invalid credentials were provided"), @ApiResponse(code = 403, message = "The authenticated user does not have the required role " + "(TENANT_DEVELOPER or TENANT_USER) or the Tenant ID " + "of the application does not match the Tenant ID of the authenticated user"), @ApiResponse(code = 404, message = "A file with the notification body was not found in " + "the form data or an application with the specified ID does " + "not exist or a topic with the specified ID does not exist"), @ApiResponse(code = 500, message = "An unexpected error occurred on the server side")}) @RequestMapping(value = "sendUnicastNotification", method = RequestMethod.POST, consumes = {"multipart/mixed", "multipart/form-data"}) @ResponseBody public EndpointNotificationDto sendUnicastNotification( @ApiParam(name = "notification", value = "NotificationDto body. Mandatory fields: applicationId, schemaId, topicId, type", required = true) @RequestPart("notification") NotificationDto notification, @ApiParam(name = "endpointKeyHash", value = "The key hash of the endpoint in Base64 URL safe format", required = true) @RequestPart("endpointKeyHash") String clientKeyHash, @ApiParam(name = "file", value = "A file with notification body according to the specified " + "notification schema represented in json format", required = true) @RequestPart("file") MultipartFile file) throws KaaAdminServiceException { byte[] data = getFileContent(file); return notificationService.sendUnicastNotification(notification, clientKeyHash, data); } }