diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/beans/TagInfo.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/beans/TagInfo.java new file mode 100644 index 0000000000..33075f39d2 --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/beans/TagInfo.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you 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 io.entgra.device.mgt.core.device.mgt.api.jaxrs.beans; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel(value = "TagInfo", description = "Tag details including parameters associated with tags " + + "wrapped here.") +public class TagInfo { + + @ApiModelProperty(name = "name", value = "The name of the tag.", required = true) + private String name; + + @ApiModelProperty(name = "description", value = "Describes the behavior of the tag.", + required = false) + private String description; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/beans/TagInfoList.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/beans/TagInfoList.java new file mode 100644 index 0000000000..4960c35f82 --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/beans/TagInfoList.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you 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 io.entgra.device.mgt.core.device.mgt.api.jaxrs.beans; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.util.List; + +@ApiModel(value = "TagInfoList") +public class TagInfoList extends BasePaginatedResult { + + private List tags; + + @ApiModelProperty(value = "Returns the list of tags that match the offset and limit parameter values " + + "that were specified.") + @JsonProperty("tags") + public List getList() { + return tags; + } + + public void setList(List tags) { + this.tags = tags; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("{\n"); + sb.append(" count: ").append(getCount()).append(",\n"); + sb.append(" tags: [").append(tags).append("\n"); + sb.append("]}\n"); + return sb.toString(); + } + + +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/beans/TagMappingInfo.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/beans/TagMappingInfo.java new file mode 100644 index 0000000000..ae5debb2e4 --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/beans/TagMappingInfo.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you 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 io.entgra.device.mgt.core.device.mgt.api.jaxrs.beans; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.util.List; + +@ApiModel(value = "TagMappingInfo", description = "Tag mapping details including parameters associated with " + + "device mapping wrapped here.") +public class TagMappingInfo { + + @ApiModelProperty(name = "deviceIdentifiers", value = "Defines the device identifiers.", required = true) + private List deviceIdentifiers; + + @ApiModelProperty(name = "deviceType", value = "Defines the device type.", required = true) + private String deviceType; + + @ApiModelProperty(name = "tags", value = "Defines the tags.", required = true) + private List tags; + + public List getDeviceIdentifiers() { + return deviceIdentifiers; + } + + public void setDeviceIdentifiers(List deviceIdentifiers) { + this.deviceIdentifiers = deviceIdentifiers; + } + + public String getDeviceType() { + return deviceType; + } + + public void setDeviceType(String deviceType) { + this.deviceType = deviceType; + } + + public List getTags() { + return tags; + } + + public void setTags(List tags) { + this.tags = tags; + } +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/beans/TagMappingInfoList.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/beans/TagMappingInfoList.java new file mode 100644 index 0000000000..8ae856748e --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/beans/TagMappingInfoList.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you 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 io.entgra.device.mgt.core.device.mgt.api.jaxrs.beans; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.util.List; + +@ApiModel(value = "TagMappingInfoList") +public class TagMappingInfoList extends BasePaginatedResult { + + private List tagMappings; + + @ApiModelProperty(value = "Returns the list of tag mappings that match the offset and " + + "limit parameter values that were specified.") + @JsonProperty("tagMappings") + public List getList() { + return tagMappings; + } + + public void setList(List tagMappings) { + this.tagMappings = tagMappings; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("{\n"); + sb.append(" count: ").append(getCount()).append(",\n"); + sb.append(" tagMappings: [").append(tagMappings).append("\n"); + sb.append("]}\n"); + return sb.toString(); + } + + +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/api/DeviceManagementService.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/api/DeviceManagementService.java index 5c41168bcb..e201133681 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/api/DeviceManagementService.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/api/DeviceManagementService.java @@ -64,9 +64,7 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import java.sql.Timestamp; import java.util.List; -import java.util.Map; /** * Device related REST-API. This can be used to manipulated device related details. @@ -339,6 +337,12 @@ public interface DeviceManagementService { required = false) @QueryParam("requireDeviceInfo") boolean requireDeviceInfo, + @ApiParam( + name = "tags", + value = "Describes the tags associated with the enrolment", + required = false) + @QueryParam("tags") + List tags, @ApiParam( name = "offset", value = "The starting pagination index for the complete list of qualified items.", diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/api/TagManagementService.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/api/TagManagementService.java new file mode 100644 index 0000000000..a9e90d87fe --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/api/TagManagementService.java @@ -0,0 +1,401 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you 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 io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.api; + +import io.entgra.device.mgt.core.device.mgt.api.jaxrs.beans.*; +import io.swagger.annotations.*; +import io.entgra.device.mgt.core.apimgt.annotations.Scope; +import io.entgra.device.mgt.core.apimgt.annotations.Scopes; +import io.entgra.device.mgt.core.device.mgt.api.jaxrs.util.Constants; + +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.List; + +@SwaggerDefinition( + info = @Info( + version = "1.0.0", + title = "", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = "name", value = "TagManagement"), + @ExtensionProperty(name = "context", value = "/api/device-mgt/v1.0/tags"), + }) + } + ), + tags = { + @Tag(name = "device_management") + } +) +@Scopes( + scopes = { + @Scope( + name = "Getting the List of Tags", + description = "Getting the List of Tags", + key = "tm:tags:view", + roles = {"Internal/devicemgt-user"}, + permissions = {"/device-mgt/tags/view"} + ), + @Scope( + name = "Adding a new tag", + description = "Adding a new tag", + key = "tm:tags:create", + roles = {"Internal/devicemgt-user"}, + permissions = {"/device-mgt/tags/create"} + ), + @Scope( + name = "Updating a tag", + description = "Updating a tag", + key = "tm:tags:update", + roles = {"Internal/devicemgt-user"}, + permissions = {"/device-mgt/tags/update"} + ), + @Scope( + name = "Delete a tag", + description = "Delete a tag", + key = "tm:tags:delete", + roles = {"Internal/devicemgt-user"}, + permissions = {"/device-mgt/tags/delete"} + ), + @Scope( + name = "Adding a device tag mapping", + description = "Adding a device-tag mapping", + key = "tm:tags:mapping:create", + roles = {"Internal/devicemgt-user"}, + permissions = {"/device-mgt/tags/mapping/create"} + ), + @Scope( + name = "Deleting a device tag mapping", + description = "Deleting a device-tag mapping", + key = "tm:tags:mapping:delete", + roles = {"Internal/devicemgt-user"}, + permissions = {"/device-mgt/tags/mapping/delete"} + ), + @Scope( + name = "Getting the list of device tag mappings", + description = "Getting the list of device-tag mappings", + key = "tm:tags:mapping:view", + roles = {"Internal/devicemgt-user"}, + permissions = {"/device-mgt/tags/mapping/view"} + ) + } +) +@Path("/tags") +@Api(value = "Tag Management", description = "Tag management related operations can be found here.") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public interface TagManagementService { + + @GET + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Getting the List of Tags", + notes = "", + tags = "Tag Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "tm:tags:view") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully fetched the list of tags.", + response = TagInfoList.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource has been modified the last time.\n" + + "Used by caches, or in conditional requests."), + }), + @ApiResponse( + code = 304, + message = "Not Modified. \n Empty body because the client already has the latest version of the requested resource."), + @ApiResponse( + code = 406, + message = "Not Acceptable.\n The requested media type is not supported"), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while fetching list of roles.", + response = ErrorResponse.class) + }) + Response getTags(); + + @POST + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Adding a Tag", + notes = "", + tags = "Tag Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "tm:tags:create") + }) + } + ) + @ApiResponses(value = { + @ApiResponse( + code = 201, + message = "Created. \n Successfully created the tag.", + responseHeaders = { + @ResponseHeader( + name = "Content-Location", + description = "The URL to the newly added tag."), + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource has been modified the last time.\n" + + "Used by caches, or in conditional requests.")}), + @ApiResponse( + code = 303, + message = "See Other. \n The source can be retrieved from the URL specified in the location header.", + responseHeaders = { + @ResponseHeader( + name = "Content-Location", + description = "The Source URL of the document.")}), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 415, + message = "Unsupported media type. \n The format of the requested entity was not supported.", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while adding a new tag.", + response = ErrorResponse.class) + }) + Response addTag( + @ApiParam( + name = "tag", + value = "The properties required to add a new tag.", + required = true) List tags); + + @PUT + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "PUT", + value = "Updating a Tag", + notes = "", + tags = "Tag Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "tm:tags:update") + }) + } + ) + @ApiResponses(value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully updated the tag.", + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body")}), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 404, + message = "Not Found. \n The specified tag does not exist.", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while updating the tag.", + response = ErrorResponse.class) + }) + Response updateTag( + @ApiParam( + name = "tagId", + value = "The ID of the tag to be updated.", + required = false) @QueryParam("tagId") Integer tagId, + @ApiParam( + name = "tagName", + value = "The name of the tag to be updated.", + required = false) @QueryParam("tagName") String tagName, + @ApiParam( + name = "tagInfo", + value = "The properties required to update the tag.", + required = true) TagInfo tagInfo); + + @DELETE + @Path("/{tagId}") + @ApiOperation( + httpMethod = "DELETE", + value = "Deleting a Tag", + notes = "", + tags = "Tag Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "tm:tags:delete") + }) + } + ) + @ApiResponses(value = { + @ApiResponse( + code = 204, + message = "No Content. \n Successfully deleted the tag."), + @ApiResponse( + code = 404, + message = "Not Found. \n The specified tag does not exist.", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while deleting the tag.", + response = ErrorResponse.class) + }) + Response deleteTag( + @ApiParam( + name = "tagId", + value = "The ID of the tag to be deleted.", + required = true) @PathParam("tagId") int tagId); + + @GET + @Path("/{tagId}") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Getting a Tag by ID", + notes = "", + tags = "Tag Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "tm:tags:view") + }) + } + ) + @ApiResponses(value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully fetched the tag.", + response = Tag.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body")}), + @ApiResponse( + code = 404, + message = "Not Found. \n The specified tag does not exist.", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while fetching the tag.", + response = ErrorResponse.class) + }) + Response getTagById( + @ApiParam( + name = "tagId", + value = "The ID of the tag to be fetched.", + required = true) @PathParam("tagId") int tagId); + + @POST + @Path("/mapping") + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Adding a Device-Tag Mapping", + notes = "", + tags = "Device-Tag Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "tm:tags:mapping:create") + }) + } + ) + @ApiResponses(value = { + @ApiResponse( + code = 201, + message = "Created. \n Successfully created the device-tag mapping.", + responseHeaders = { + @ResponseHeader( + name = "Content-Location", + description = "The URL to the newly added device-tag mapping."), + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body")}), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while adding the device-tag mapping.", + response = ErrorResponse.class) + }) + Response addDeviceTagMapping( + @ApiParam( + name = "deviceTagInfo", + value = "The properties required to add a new device-tag mapping.", + required = true) TagMappingInfo tagMappingInfo); + + @DELETE + @Path("/mapping") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "DELETE", + value = "Deleting a Device-Tag Mapping", + notes = "", + tags = "Device-Tag Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "tm:tags:mapping:delete") + }) + } + ) + @ApiResponses(value = { + @ApiResponse( + code = 204, + message = "No Content. \n Successfully deleted the device-tag mapping."), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while deleting the device-tag mapping.", + response = ErrorResponse.class) + }) + Response deleteDeviceTagMapping( + @ApiParam( + name = "deviceTagInfo", + value = "The properties required to add a new device-tag mapping.", + required = true) TagMappingInfo tagMappingInfo); +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceManagementServiceImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceManagementServiceImpl.java index 88cfe125ca..5c7d235b88 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceManagementServiceImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceManagementServiceImpl.java @@ -151,6 +151,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { @QueryParam("since") String since, @HeaderParam("If-Modified-Since") String ifModifiedSince, @QueryParam("requireDeviceInfo") boolean requireDeviceInfo, + @QueryParam("tags") List tags, @QueryParam("offset") int offset, @QueryParam("limit") int limit) { try { @@ -226,6 +227,19 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { return Response.status(Response.Status.OK).entity(devices).build(); } + if (tags != null && !tags.isEmpty()) { + boolean isTagsEmpty = true; + for (String tagString : tags) { + if (StringUtils.isNotBlank(tagString)) { + isTagsEmpty = false; + break; + } + } + if (!isTagsEmpty) { + request.setTags(tags); + } + } + // this is the user who initiates the request String authorizedUser = CarbonContext.getThreadLocalCarbonContext().getUsername(); if (groupId != 0) { diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/TagManagementServiceImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/TagManagementServiceImpl.java new file mode 100644 index 0000000000..b1643472d8 --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/TagManagementServiceImpl.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you 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 io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.impl; + +import io.entgra.device.mgt.core.device.mgt.api.jaxrs.beans.TagInfo; +import io.entgra.device.mgt.core.device.mgt.api.jaxrs.beans.TagMappingInfo; +import io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.api.TagManagementService; +import io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.impl.util.RequestValidationUtil; +import io.entgra.device.mgt.core.device.mgt.api.jaxrs.util.DeviceMgtAPIUtils; +import io.entgra.device.mgt.core.device.mgt.common.exceptions.BadRequestException; +import io.entgra.device.mgt.core.device.mgt.common.tag.mgt.*; +import io.entgra.device.mgt.core.device.mgt.extensions.logger.spi.EntgraLogger; +import io.entgra.device.mgt.core.notification.logger.impl.EntgraRoleMgtLoggerImpl; + +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.ArrayList; +import java.util.List; + +@Path("/tags") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public class TagManagementServiceImpl implements TagManagementService { + + private static final EntgraLogger log = new EntgraRoleMgtLoggerImpl(TagManagementServiceImpl.class); + + @GET + @Override + public Response getTags() { + try { + List tags = DeviceMgtAPIUtils.getTagManagementService().getAllTags(); + return Response.status(Response.Status.OK).entity(tags).build(); + } catch (TagManagementException e) { + String msg = "Error occurred while getting tags."; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + } + + @POST + @Override + public Response addTag(List tagInfoList) { + RequestValidationUtil.validateTagListDetails(tagInfoList); + try { + List tags = new ArrayList<>(); + for (TagInfo tagInfo : tagInfoList) { + Tag tag = new Tag(tagInfo.getName(), tagInfo.getDescription()); + tags.add(tag); + } + DeviceMgtAPIUtils.getTagManagementService().addTags(tags); + return Response.status(Response.Status.CREATED).entity(tagInfoList).build(); + } catch (TagManagementException e) { + String msg = "Error occurred while adding tags." ; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } catch (BadRequestException e) { + String msg = "Error occurred while adding tags. Please check the request" ; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build(); + } + } + + @PUT + @Override + public Response updateTag(@QueryParam("tagId") Integer tagId, @QueryParam("tagName") String tagName, TagInfo tagInfo) { + RequestValidationUtil.validateTagDetails(tagId, tagName, tagInfo); + try { + Tag tag; + if (tagId != null) { + tag = DeviceMgtAPIUtils.getTagManagementService().getTagById(tagId); + } else { + tag = DeviceMgtAPIUtils.getTagManagementService().getTagByName(tagName); + } + if (tag == null) { + String msg = "Tag not found."; + log.error(msg); + return Response.status(Response.Status.NOT_FOUND).entity(msg).build(); + } + tag.setName(tagInfo.getName()); + tag.setDescription(tagInfo.getDescription()); + DeviceMgtAPIUtils.getTagManagementService().updateTag(tag); + return Response.status(Response.Status.OK).entity(tag).build(); + } catch (TagManagementException e) { + String msg = (tagId != null) ? "Error occurred while updating tag with ID " + tagId + "." + : "Error occurred while updating tag with name " + tagName + "."; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } catch (TagNotFoundException e) { + String msg = (tagId != null) ? "Tag with ID " + tagId + " is not found." + : "Tag with name " + tagName + " is not found."; + log.error(msg, e); + return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build(); + } catch (BadRequestException e) { + String msg = (tagId != null) ? "Error occurred while updating tag with ID " + tagId + : "Error occurred while updating tag with name " + tagName; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build(); + } + } + + @DELETE + @Path("/{tagId}") + @Override + public Response deleteTag(@PathParam("tagId") int tagId) { + try { + DeviceMgtAPIUtils.getTagManagementService().deleteTag(tagId); + return Response.status(Response.Status.NO_CONTENT).build(); + } catch (TagManagementException e) { + String msg = "Error occurred while deleting tag with ID " + tagId + "."; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } catch (TagNotFoundException e) { + String msg = "Tag with ID " + tagId + " is not found."; + log.error(msg, e); + return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build(); + } + } + + @GET + @Path("/{tagId}") + @Override + public Response getTagById(@PathParam("tagId") int tagId) { + try { + Tag tag = DeviceMgtAPIUtils.getTagManagementService().getTagById(tagId); + return Response.status(Response.Status.OK).entity(tag).build(); + } catch (TagManagementException e) { + String msg = "Error occurred while getting tag with ID " + tagId + "."; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } catch (TagNotFoundException e) { + String msg = "Tag with ID " + tagId + " is not found."; + log.error(msg, e); + return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build(); + } + } + + @POST + @Path("/mapping") + public Response addDeviceTagMapping(TagMappingInfo tagMappingInfo) { + RequestValidationUtil.validateTagMappingDetails(tagMappingInfo); + try { + TagMappingDTO tagMappingDTO = new TagMappingDTO(tagMappingInfo.getDeviceIdentifiers(), + tagMappingInfo.getDeviceType(), tagMappingInfo.getTags()); + DeviceMgtAPIUtils.getTagManagementService().addDeviceTagMapping(tagMappingDTO); + return Response.status(Response.Status.CREATED).entity(tagMappingDTO).build(); + } catch (TagManagementException e) { + String msg = "Error occurred while adding device-tag mapping."; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } catch (BadRequestException e) { + String msg = "Error occurred while adding tag mappings."; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build(); + } + } + + @DELETE + @Path("/mapping") + public Response deleteDeviceTagMapping(TagMappingInfo tagMappingInfo) { + RequestValidationUtil.validateTagMappingDetails(tagMappingInfo); + try { + TagMappingDTO tagMappingDTO = new TagMappingDTO(tagMappingInfo.getDeviceIdentifiers(), + tagMappingInfo.getDeviceType(), tagMappingInfo.getTags()); + DeviceMgtAPIUtils.getTagManagementService().deleteDeviceTagMapping(tagMappingDTO); + return Response.status(Response.Status.NO_CONTENT).build(); + } catch (TagManagementException e) { + String msg = "Error occurred while deleting tag mappings."; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } catch (BadRequestException e) { + String msg = "Error occurred while deleting tag mappings."; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build(); + } + } +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/util/RequestValidationUtil.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/util/RequestValidationUtil.java index ab66e75d1c..e39ebb2366 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/util/RequestValidationUtil.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/util/RequestValidationUtil.java @@ -19,6 +19,7 @@ package io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.impl.util; import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; +import io.entgra.device.mgt.core.device.mgt.api.jaxrs.beans.*; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -492,6 +493,41 @@ public class RequestValidationUtil { } } + public static void validateTagDetails(Integer tagId, String tagName, TagInfo tagInfo) { + if (tagId == null && tagName == null) { + String msg = "Either tagId or tagName must be provided."; + log.error(msg); + throw new InputValidationException( + new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build()); + } + if (tagInfo == null) { + throw new InputValidationException( + new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage("Request body is " + + "empty").build()); + } + } + + public static void validateTagListDetails(List tagInfo) { + if (tagInfo == null) { + throw new InputValidationException( + new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage("Request body is " + + "empty").build()); + } + } + + public static void validateTagMappingDetails(TagMappingInfo tagMappingInfo) { + if (tagMappingInfo == null) { + throw new InputValidationException( + new ErrorResponse.ErrorResponseBuilder().setCode(400L).setMessage("Request body is empty").build()); + } else if (tagMappingInfo.getDeviceIdentifiers() == null || tagMappingInfo.getDeviceType() == null + || tagMappingInfo.getTags() == null) { + throw new InputValidationException( + new ErrorResponse.ErrorResponseBuilder().setCode(400L).setMessage("Invalid tag mapping request body").build()); + } + } + + + public static void validateScopes(List scopes) { if (scopes == null || scopes.isEmpty()) { throw new InputValidationException( diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/util/DeviceMgtAPIUtils.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/util/DeviceMgtAPIUtils.java index 5451572519..b6f44c042c 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/util/DeviceMgtAPIUtils.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/util/DeviceMgtAPIUtils.java @@ -21,10 +21,12 @@ package io.entgra.device.mgt.core.device.mgt.api.jaxrs.util; import io.entgra.device.mgt.core.apimgt.webapp.publisher.APIPublisherService; import io.entgra.device.mgt.core.application.mgt.common.services.ApplicationManager; import io.entgra.device.mgt.core.application.mgt.common.services.SubscriptionManager; +import io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.api.TagManagementService; import io.entgra.device.mgt.core.device.mgt.common.authorization.GroupAccessAuthorizationService; import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceStatusManagementService; import io.entgra.device.mgt.core.device.mgt.core.permission.mgt.PermissionManagerServiceImpl; import io.entgra.device.mgt.core.tenant.mgt.common.spi.TenantManagerAdminService; +import io.entgra.device.mgt.core.device.mgt.core.service.TagManagementProviderService; import org.apache.axis2.AxisFault; import org.apache.axis2.client.Options; import org.apache.axis2.java.security.SSLProtocolSocketFactory; @@ -505,6 +507,19 @@ public class DeviceMgtAPIUtils { return policyManagementService; } + public static TagManagementProviderService getTagManagementService() { + TagManagementProviderService tagManagementService; + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + tagManagementService = + (TagManagementProviderService) ctx.getOSGiService(TagManagementProviderService.class, null); + if (tagManagementService == null) { + String msg = "Tag Management service not initialized."; + log.error(msg); + throw new IllegalStateException(msg); + } + return tagManagementService; + } + public static PlatformConfigurationManagementService getPlatformConfigurationManagementService() { PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); PlatformConfigurationManagementService tenantConfigurationManagementService = diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/webapp/WEB-INF/cxf-servlet.xml b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/webapp/WEB-INF/cxf-servlet.xml index 7cdb4ffa0e..1b0f7abb32 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/webapp/WEB-INF/cxf-servlet.xml +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/webapp/WEB-INF/cxf-servlet.xml @@ -51,6 +51,7 @@ + @@ -103,6 +104,7 @@ + diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/test/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceManagementServiceImplTest.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/test/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceManagementServiceImplTest.java index b66773e84d..49e2809c25 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/test/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceManagementServiceImplTest.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/test/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceManagementServiceImplTest.java @@ -158,7 +158,7 @@ public class DeviceManagementServiceImplTest { Response response = this.deviceManagementService .getDevices(TEST_DEVICE_NAME, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, null, null, DEFAULT_STATUS_LIST, 1, 0, null, null, false, - 10, 5); + null, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.BAD_REQUEST.getStatusCode()); } @@ -178,22 +178,22 @@ public class DeviceManagementServiceImplTest { Response response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, null,null, DEFAULT_STATUS_LIST, 1, 0, null, null, false, - 10, 5); + null, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); response = this.deviceManagementService .getDevices(TEST_DEVICE_NAME, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, null, DEFAULT_OWNERSHIP, null, null, DEFAULT_STATUS_LIST, 1, 0, null, null, false, - 10, 5); + null, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); response = this.deviceManagementService .getDevices(TEST_DEVICE_NAME, TEST_DEVICE_TYPE, null, null, null, DEFAULT_OWNERSHIP, null, null, DEFAULT_STATUS_LIST, 1, 0, null, null, false, - 10, 5); + null, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); response = this.deviceManagementService .getDevices(TEST_DEVICE_NAME, TEST_DEVICE_TYPE, null, null, null, DEFAULT_OWNERSHIP, null, null, DEFAULT_STATUS_LIST, 1, 0, null, null, true, - 10, 5); + null, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); } @@ -307,7 +307,7 @@ public class DeviceManagementServiceImplTest { Mockito.when(deviceAccessAuthorizationService.isDeviceAdminUser()).thenReturn(true); deviceManagementService.getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, null,null, DEFAULT_STATUS_LIST, 1, - 0, null, null, false, 10, 5); + 0, null, null, false, null, 10, 5); } @Test(description = "Testing get devices when user is the device admin") @@ -326,11 +326,11 @@ public class DeviceManagementServiceImplTest { Response response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP - , null, null, DEFAULT_STATUS_LIST, 1, 0, null, null, false, 10, 5); + , null, null, DEFAULT_STATUS_LIST, 1, 0, null, null, false, null, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, null, DEFAULT_USERNAME, DEFAULT_ROLE, DEFAULT_OWNERSHIP - , null, null, DEFAULT_STATUS_LIST, 1, 0, null, null, false, 10, 5); + , null, null, DEFAULT_STATUS_LIST, 1, 0, null, null, false, null, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); } @@ -353,7 +353,7 @@ public class DeviceManagementServiceImplTest { Response response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, "newuser", null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, null, null, DEFAULT_STATUS_LIST, 0, 0, null, null, false, - 10, 5); + null, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.UNAUTHORIZED.getStatusCode()); Mockito.reset(this.deviceAccessAuthorizationService); } @@ -375,17 +375,17 @@ public class DeviceManagementServiceImplTest { Response response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, null, null, DEFAULT_STATUS_LIST, 0, 0, null, ifModifiedSince, false, - 10, 5); + null, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.NOT_MODIFIED.getStatusCode()); response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, null, null, DEFAULT_STATUS_LIST, 0, 0, null, ifModifiedSince, true, - 10, 5); + null, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.NOT_MODIFIED.getStatusCode()); response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, null, null, DEFAULT_STATUS_LIST, 0, 0, null, "ErrorModifiedSince", - false, 10, 5); + false, null, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.BAD_REQUEST.getStatusCode()); } @@ -406,17 +406,17 @@ public class DeviceManagementServiceImplTest { Response response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, null, null,DEFAULT_STATUS_LIST, 0, 0, since, null, false, - 10, 5); + null, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, null, null,DEFAULT_STATUS_LIST, 0, 0, since, null, true, - 10, 5); + null, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, null, null,DEFAULT_STATUS_LIST, 0, 0, "ErrorSince", null, false, - 10, 5); + null, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.BAD_REQUEST.getStatusCode()); } @@ -439,7 +439,7 @@ public class DeviceManagementServiceImplTest { Response response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, null, null, DEFAULT_STATUS_LIST, 1, 0, null, null, false, - 10, 5); + null, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); Mockito.reset(this.deviceManagementProviderService); } @@ -461,8 +461,8 @@ public class DeviceManagementServiceImplTest { Response response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, - null, null, DEFAULT_STATUS_LIST, 1, 0, null, null, false, - 10, 5); + null, null, DEFAULT_STATUS_LIST, 1, 0,null, null, false, + null, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); Mockito.reset(this.deviceAccessAuthorizationService); } diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/EnrolmentInfo.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/EnrolmentInfo.java index 450fe0c5df..6a80c23703 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/EnrolmentInfo.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/EnrolmentInfo.java @@ -21,7 +21,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import java.io.Serializable; -import java.math.BigInteger; +import java.util.List; @ApiModel(value = "EnrolmentInfo", description = "This class carries all information related to a devices enrollment" + " status.") @@ -61,6 +61,9 @@ public class EnrolmentInfo implements Serializable { @ApiModelProperty(name = "owner", value = "The device owner's name.", required = true ) private String owner; + @ApiModelProperty(name = "tags", value = "Tags associated with enrolment.", required = false ) + private List tags; + public EnrolmentInfo() { } @@ -134,6 +137,14 @@ public class EnrolmentInfo implements Serializable { this.owner = owner; } + public List getTags() { + return tags; + } + + public void setTags(List tags) { + this.tags = tags; + } + @Override public boolean equals(Object obj) { if (obj instanceof EnrolmentInfo) { diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/PaginationRequest.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/PaginationRequest.java index c4e01eb282..f6ba8d2fe7 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/PaginationRequest.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/PaginationRequest.java @@ -52,6 +52,7 @@ public class PaginationRequest { private Map customProperty = new HashMap<>(); private Map property = new HashMap<>(); private List statusList = new ArrayList<>(); + private List tags = new ArrayList<>(); private OperationLogFilters operationLogFilters = new OperationLogFilters(); private List sortColumn = new ArrayList<>(); private int deviceTypeId; @@ -199,6 +200,14 @@ public class PaginationRequest { public List getSortColumn() { return sortColumn; } + public List getTags() { + return tags; + } + + public void setTags(List tags) { + this.tags = tags; + } + /** * Convert SortColumns field parameter and splitting string into columnName and sortType * diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/tag/mgt/DeviceTag.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/tag/mgt/DeviceTag.java new file mode 100644 index 0000000000..f60dbe2aed --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/tag/mgt/DeviceTag.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you 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 io.entgra.device.mgt.core.device.mgt.common.tag.mgt; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * DTO of DeviceTag object which is used to manage Device Tags. + */ + +@ApiModel(value = "DeviceTag", description = "This is used to manage device tags.") +public class DeviceTag { + + @ApiModelProperty(name = "enrolmentId", value = "Defines the device id.", required = true) + private int enrolmentId; + + @ApiModelProperty(name = "tagId", value = "Defines the tag id.", required = true) + private int tagId; + + public int getEnrolmentId() { + return enrolmentId; + } + + public void setEnrolmentId(int enrolmentId) { + this.enrolmentId = enrolmentId; + } + + public int getTagId() { + return tagId; + } + + public void setTagId(int tagId) { + this.tagId = tagId; + } +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/tag/mgt/Tag.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/tag/mgt/Tag.java new file mode 100644 index 0000000000..a0546e5447 --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/tag/mgt/Tag.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you 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 io.entgra.device.mgt.core.device.mgt.common.tag.mgt; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * DTO of Tag object which is used to manage Tags in devices. + */ + +@ApiModel(value = "Tag", description = "This is used to manage tags in devices.") +public class Tag { + + @ApiModelProperty(name = "id", value = "Defines the tag ID.", required = false) + private int id; + + @ApiModelProperty(name = "name", value = "Defines the tag name.", required = true) + private String name; + + @ApiModelProperty(name = "description", value = "Defines the tag description.", required = false) + private String description; + + public Tag(String name, String description) { + this.name = name; + this.description = description; + } + + public Tag() {} + + public Tag(int id, String name, String description) { + this.id = id; + this.name = name; + this.description = description; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + @Override + public String toString() { + return "tag {" + + " id= " + id + + ", name= '" + name + '\'' + + ", description= '" + description + '\'' + + '}'; + } +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/tag/mgt/TagManagementException.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/tag/mgt/TagManagementException.java new file mode 100644 index 0000000000..f8c0755d65 --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/tag/mgt/TagManagementException.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you 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 io.entgra.device.mgt.core.device.mgt.common.tag.mgt; + +/** + * Custom exception class to be used in TagManagement related functionalities. + */ +public class TagManagementException extends Exception { + + private static final long serialVersionUID = -8933146283800122660L; + private String errorMessage; + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public TagManagementException(String msg, Exception nestedEx) { + super(msg, nestedEx); + setErrorMessage(msg); + } + + public TagManagementException(String message, Throwable cause) { + super(message, cause); + setErrorMessage(message); + } + + public TagManagementException(String msg) { + super(msg); + setErrorMessage(msg); + } + + public TagManagementException() { + super(); + } + + public TagManagementException(Throwable cause) { + super(cause); + } + +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/tag/mgt/TagMappingDTO.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/tag/mgt/TagMappingDTO.java new file mode 100644 index 0000000000..3bfe899cf2 --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/tag/mgt/TagMappingDTO.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you 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 io.entgra.device.mgt.core.device.mgt.common.tag.mgt; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.util.List; + +/** + * DTO of TagMapping object which is used to manage Device Tags. + */ + +@ApiModel(value = "TagMappingDTO", description = "This is used to manage device tags.") +public class TagMappingDTO { + + @ApiModelProperty(name = "deviceIdentifiers", value = "Defines the device identifiers.", required = true) + private List deviceIdentifiers; + + @ApiModelProperty(name = "deviceType", value = "Defines the device type.", required = true) + private String deviceType; + + @ApiModelProperty(name = "tags", value = "Defines the tag.", required = true) + private List tags; + + public TagMappingDTO() {} + + public TagMappingDTO(List deviceIdentifiers, String deviceType, List tags) { + this.deviceIdentifiers = deviceIdentifiers; + this.deviceType = deviceType; + this.tags = tags; + } + + public List getDeviceIdentifiers() { + return deviceIdentifiers; + } + + public void setDeviceIdentifiers(List deviceIdentifiers) { + this.deviceIdentifiers = deviceIdentifiers; + } + + public String getDeviceType() { + return deviceType; + } + + public void setDeviceType(String deviceType) { + this.deviceType = deviceType; + } + + public List getTags() { + return tags; + } + + public void setTags(List tags) { + this.tags = tags; + } +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/tag/mgt/TagNotFoundException.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/tag/mgt/TagNotFoundException.java new file mode 100644 index 0000000000..f80e41c096 --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/tag/mgt/TagNotFoundException.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you 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 io.entgra.device.mgt.core.device.mgt.common.tag.mgt; + +/** + * Custom exception class to be used in TagManagement related functionalities. + */ +public class TagNotFoundException extends Exception { + + private static final long serialVersionUID = -8933146283800122660L; + private String errorMessage; + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public TagNotFoundException(String msg, Exception nestedEx) { + super(msg, nestedEx); + setErrorMessage(msg); + } + + public TagNotFoundException(String message, Throwable cause) { + super(message, cause); + setErrorMessage(message); + } + + public TagNotFoundException(String msg) { + super(msg); + setErrorMessage(msg); + } + + public TagNotFoundException() { + super(); + } + + public TagNotFoundException(Throwable cause) { + super(cause); + } + +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/DeviceManagementDAOFactory.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/DeviceManagementDAOFactory.java index b7768f9c52..b4f5087c62 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/DeviceManagementDAOFactory.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/DeviceManagementDAOFactory.java @@ -171,6 +171,22 @@ public class DeviceManagementDAOFactory { throw new IllegalStateException("Database engine has not initialized properly."); } + public static TagDAO getTagDAO() { + if (databaseEngine != null) { + switch (databaseEngine) { + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_POSTGRESQL: + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_ORACLE: + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_MSSQL: + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_H2: + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_MYSQL: + return new TagDAOImpl(); + default: + throw new UnsupportedDatabaseEngineException("Unsupported database engine : " + databaseEngine); + } + } + throw new IllegalStateException("Database engine has not initialized properly."); + } + public static DeviceStatusDAO getDeviceStatusDAO() { return new DeviceStatusDAOImpl(); } diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/TagDAO.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/TagDAO.java new file mode 100644 index 0000000000..7db392dec6 --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/TagDAO.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you 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 io.entgra.device.mgt.core.device.mgt.core.dao; + +import io.entgra.device.mgt.core.device.mgt.common.tag.mgt.DeviceTag; +import io.entgra.device.mgt.core.device.mgt.common.tag.mgt.Tag; + +import java.util.List; + +/** + * This interface represents the key operations associated with persisting tag related information. + */ +public interface TagDAO { + + /** + * Add a new tag. + * + * @param tags to be added. + * @param tenantId of the tag. + * @throws TagManagementDAOException + */ + void addTags(List tags, int tenantId) throws TagManagementDAOException; + + /** + * Update an existing tag. + * + * @param tag to be updated. + * @param tenantId of the tag. + * @throws TagManagementDAOException + */ + void updateTag(Tag tag, int tenantId) throws TagManagementDAOException; + + /** + * Delete an existing tag. + * + * @param tagId of the tag. + * @param tenantId of the tag. + * @throws TagManagementDAOException + */ + void deleteTag(int tagId, int tenantId) throws TagManagementDAOException; + + /** + * Get a tag by id. + * + * @param tagId of the tag. + * @param tenantId of the tag. + * @return Tag object. + * @throws TagManagementDAOException + */ + Tag getTagById(int tagId, int tenantId) throws TagManagementDAOException; + + /** + * Method to retrieve a tag by its name. + * + * @param tagName - Name of the tag to be retrieved. + * @param tenantId - Tenant ID. + * @return Tag object retrieved from the database. + * @throws TagManagementDAOException if something goes wrong while retrieving the Tag. + */ + Tag getTagByName(String tagName, int tenantId) throws TagManagementDAOException; + + /** + * Get all tags for a tenant. + * + * @param tenantId of the tag. + * @return List of all tags. + * @throws TagManagementDAOException + */ + List getTags(int tenantId) throws TagManagementDAOException; + + /** + * Add a device tag mapping. + * + * @param deviceIdentifiers of the mapping. + * @param deviceType of the mapping. + * @param tagNames of the mapping. + * @param tenantId of the mapping. + * @throws TagManagementDAOException + */ + void addDeviceTagMapping(List deviceIdentifiers, String deviceType, List tagNames, int tenantId) + throws TagManagementDAOException; + + /** + * Delete a device tag mapping. + * + * @param deviceIdentifiers of the mapping. + * @param deviceType of the mapping. + * @param tagNames of the mapping. + * @param tenantId of the mapping. + * @throws TagManagementDAOException + */ + void deleteDeviceTagMapping(List deviceIdentifiers, String deviceType, List tagNames, int tenantId) + throws TagManagementDAOException; + + /** + * Get all device tags for a device. + * + * @param deviceId of the device. + * @param tenantId of the mapping. + * @return List of device tags. + * @throws TagManagementDAOException + */ + List getTagsForDevice(int deviceId, int tenantId) throws TagManagementDAOException; + + /** + * Get all devices for a tag. + * + * @param tagId of the tag. + * @param tenantId of the mapping. + * @return List of device tags. + * @throws TagManagementDAOException + */ + List getDevicesForTag(int tagId, int tenantId) throws TagManagementDAOException; +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/TagManagementDAOException.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/TagManagementDAOException.java new file mode 100644 index 0000000000..39fa7f696b --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/TagManagementDAOException.java @@ -0,0 +1,70 @@ +package io.entgra.device.mgt.core.device.mgt.core.dao; + +/** + * Custom exception class for tag management data access related exceptions. + */ +public class TagManagementDAOException extends Exception { + + private static final long serialVersionUID = 2021891706072918864L; + private String message; + private boolean uniqueConstraintViolation; + + /** + * Constructs a new exception with the specified detail message and nested exception. + * + * @param message error message + * @param nestedException exception + */ + public TagManagementDAOException(String message, Exception nestedException) { + super(message, nestedException); + setErrorMessage(message); + } + + /** + * Constructs a new exception with the specified detail message and cause. + * + * @param message the detail message. + * @param cause the cause of this exception. + */ + public TagManagementDAOException(String message, Throwable cause) { + super(message, cause); + setErrorMessage(message); + } + + /** + * Constructs a new exception with the specified detail message. + * + * @param message the detail message. + */ + public TagManagementDAOException(String message) { + super(message); + setErrorMessage(message); + } + + /** + * Constructs a new exception with the specified cause. + * + * @param cause the cause of this exception. + */ + public TagManagementDAOException(Throwable cause) { + super(cause); + } + + public TagManagementDAOException(String message, Throwable cause, boolean uniqueConstraintViolation) { + super(message, cause); + setErrorMessage(message); + this.uniqueConstraintViolation = uniqueConstraintViolation; + } + + public String getMessage() { + return message; + } + + public void setErrorMessage(String errorMessage) { + this.message = errorMessage; + } + + public boolean isUniqueConstraintViolation() { + return uniqueConstraintViolation; + } +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java index 3b8aa18647..c080980ca9 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java @@ -1030,6 +1030,8 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO { boolean isStatusProvided = false; Date since = request.getSince(); boolean isSinceProvided = false; + List tagList = request.getTags(); + boolean isTagsProvided = false; try { Connection conn = getConnection(); @@ -1084,6 +1086,21 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO { sql += buildStatusQuery(statusList); isStatusProvided = true; } + if (tagList != null && !tagList.isEmpty()) { + sql += " AND e.ID IN ( " + + "SELECT dtm.ENROLMENT_ID " + + "FROM DM_DEVICE_TAG_MAPPING dtm " + + "JOIN DM_TAG t ON dtm.TAG_ID = t.ID " + + "WHERE t.NAME IN ("; + for (int i = 0; i < tagList.size(); i++) { + if (i > 0) { + sql += ", "; + } + sql += "?"; + } + sql += ") GROUP BY dtm.ENROLMENT_ID HAVING COUNT(DISTINCT t.NAME) = ? )"; + isTagsProvided = true; + } try (PreparedStatement stmt = conn.prepareStatement(sql)) { int paramIdx = 1; @@ -1112,6 +1129,12 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO { stmt.setString(paramIdx++, status); } } + if (isTagsProvided) { + for (String tag : tagList) { + stmt.setString(paramIdx++, tag); + } + stmt.setInt(paramIdx++, tagList.size()); + } try (ResultSet rs = stmt.executeQuery()) { if (rs.next()) { @@ -1300,6 +1323,8 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO { boolean isStatusProvided = false; Date since = request.getSince(); boolean isSinceProvided = false; + List tagList = request.getTags(); + boolean isTagsProvided = false; try { Connection conn = getConnection(); @@ -1342,6 +1367,21 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO { sql += buildStatusQuery(statusList); isStatusProvided = true; } + if (tagList != null && !tagList.isEmpty()) { + sql += " AND e.ID IN ( " + + "SELECT dtm.ENROLMENT_ID " + + "FROM DM_DEVICE_TAG_MAPPING dtm " + + "JOIN DM_TAG t ON dtm.TAG_ID = t.ID " + + "WHERE t.NAME IN ("; + for (int i = 0; i < tagList.size(); i++) { + if (i > 0) { + sql += ", "; + } + sql += "?"; + } + sql += ") GROUP BY dtm.ENROLMENT_ID HAVING COUNT(DISTINCT t.NAME) = ? )"; + isTagsProvided = true; + } try (PreparedStatement stmt = conn.prepareStatement(sql)) { int paramIdx = 1; @@ -1368,6 +1408,12 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO { stmt.setString(paramIdx++, status); } } + if (isTagsProvided) { + for (String tag : tagList) { + stmt.setString(paramIdx++, tag); + } + stmt.setInt(paramIdx++, tagList.size()); + } try (ResultSet rs = stmt.executeQuery()) { if (rs.next()) { diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/TagDAOImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/TagDAOImpl.java new file mode 100644 index 0000000000..2a9813131b --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/TagDAOImpl.java @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you 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 io.entgra.device.mgt.core.device.mgt.core.dao.impl; + +import io.entgra.device.mgt.core.device.mgt.common.tag.mgt.DeviceTag; +import io.entgra.device.mgt.core.device.mgt.common.tag.mgt.Tag; +import io.entgra.device.mgt.core.device.mgt.core.dao.*; + +import java.sql.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static io.entgra.device.mgt.core.device.mgt.core.dao.util.TagManagementDAOUtil.loadDeviceTagMapping; +import static io.entgra.device.mgt.core.device.mgt.core.dao.util.TagManagementDAOUtil.loadTag; +import static io.entgra.device.mgt.core.device.mgt.core.dao.util.TagManagementDAOUtil.cleanupResources; + +public class TagDAOImpl implements TagDAO { + + protected Connection getConnection() throws SQLException { + return DeviceManagementDAOFactory.getConnection(); + } + + @Override + public void addTags(List tags, int tenantId) throws TagManagementDAOException { + String query = "INSERT INTO DM_TAG (NAME, DESCRIPTION, TENANT_ID) " + + "SELECT ?, ?, ? " + + "WHERE NOT EXISTS ( " + + " SELECT 1 FROM DM_TAG " + + " WHERE NAME = ? AND TENANT_ID = ? " + + ")"; + Connection connection; + PreparedStatement preparedStatement = null; + + try { + connection = getConnection(); + preparedStatement = connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS); + for (Tag tag : tags) { + preparedStatement.setString(1, tag.getName()); + preparedStatement.setString(2, tag.getDescription()); + preparedStatement.setInt(3, tenantId); + preparedStatement.setString(4, tag.getName()); + preparedStatement.setInt(5, tenantId); + preparedStatement.addBatch(); + } + int[] updateCounts = preparedStatement.executeBatch(); + for (int count : updateCounts) { + if (count == PreparedStatement.EXECUTE_FAILED) { + throw new TagManagementDAOException("Error occurred while adding tags, adding some tags failed."); + } + } + } catch (SQLException e) { + throw new TagManagementDAOException("Error occurred while adding tags", e); + } finally { + cleanupResources(preparedStatement, null); + } + } + + @Override + public void updateTag(Tag tag, int tenantId) throws TagManagementDAOException { + String query = "UPDATE DM_TAG SET NAME = ?, DESCRIPTION = ? WHERE ID = ? AND TENANT_ID = ?"; + Connection connection; + PreparedStatement preparedStatement = null; + + try { + connection = getConnection(); + preparedStatement = connection.prepareStatement(query); + preparedStatement.setString(1, tag.getName()); + preparedStatement.setString(2, tag.getDescription()); + preparedStatement.setInt(3, tag.getId()); + preparedStatement.setInt(4, tenantId); + preparedStatement.executeUpdate(); + } catch (SQLException e) { + throw new TagManagementDAOException("Error occurred while updating tag", e); + } finally { + cleanupResources(preparedStatement, null); + } + } + + @Override + public void deleteTag(int tagId, int tenantId) throws TagManagementDAOException { + String query = "DELETE FROM DM_TAG WHERE ID = ? AND TENANT_ID = ?"; + Connection connection; + PreparedStatement preparedStatement = null; + + try { + connection = getConnection(); + preparedStatement = connection.prepareStatement(query); + preparedStatement.setInt(1, tagId); + preparedStatement.setInt(2, tenantId); + preparedStatement.executeUpdate(); + } catch (SQLException e) { + throw new TagManagementDAOException("Error occurred while deleting tag", e); + } finally { + cleanupResources(preparedStatement, null); + } + } + + @Override + public Tag getTagById(int tagId, int tenantId) throws TagManagementDAOException { + String query = "SELECT * FROM DM_TAG WHERE ID = ? AND TENANT_ID = ?"; + Connection connection; + PreparedStatement preparedStatement = null; + ResultSet resultSet = null; + Tag tag = null; + + try { + connection = getConnection(); + preparedStatement = connection.prepareStatement(query); + preparedStatement.setInt(1, tagId); + preparedStatement.setInt(2, tenantId); + + resultSet = preparedStatement.executeQuery(); + if (resultSet.next()) { + tag = loadTag(resultSet); + } + } catch (SQLException e) { + throw new TagManagementDAOException("Error occurred while retrieving tag", e); + } finally { + cleanupResources(preparedStatement, resultSet); + } + return tag; + } + + @Override + public Tag getTagByName(String tagName, int tenantId) throws TagManagementDAOException { + String query = "SELECT * FROM DM_TAG WHERE NAME = ? AND TENANT_ID = ?"; + Connection connection; + PreparedStatement preparedStatement = null; + ResultSet resultSet = null; + Tag tag = null; + + try { + connection = getConnection(); + preparedStatement = connection.prepareStatement(query); + preparedStatement.setString(1, tagName); + preparedStatement.setInt(2, tenantId); + + resultSet = preparedStatement.executeQuery(); + if (resultSet.next()) { + tag = loadTag(resultSet); + } + } catch (SQLException e) { + throw new TagManagementDAOException("Error occurred while retrieving tag with name: " + tagName, e); + } finally { + cleanupResources(preparedStatement, resultSet); + } + return tag; + } + + + @Override + public List getTags(int tenantId) throws TagManagementDAOException { + String query = "SELECT * FROM DM_TAG WHERE TENANT_ID = ?"; + Connection connection; + PreparedStatement preparedStatement = null; + ResultSet resultSet = null; + List tags = new ArrayList<>(); + + try { + connection = getConnection(); + preparedStatement = connection.prepareStatement(query); + preparedStatement.setInt(1, tenantId); + + resultSet = preparedStatement.executeQuery(); + while (resultSet.next()) { + Tag tag = loadTag(resultSet); + tags.add(tag); + } + } catch (SQLException e) { + throw new TagManagementDAOException("Error occurred while retrieving tags", e); + } finally { + cleanupResources(preparedStatement, resultSet); + } + return tags; + } + + @Override + public void addDeviceTagMapping(List deviceIdentifiers, String deviceType, List tagNames, int tenantId) throws TagManagementDAOException { + String deviceIdentifiersPlaceholders = String.join(", ", Collections.nCopies(deviceIdentifiers.size(), "?")); + String tagNamesPlaceholders = String.join(", ", Collections.nCopies(tagNames.size(), "?")); + + String query = String.format( + "INSERT INTO DM_DEVICE_TAG_MAPPING (ENROLMENT_ID, TAG_ID, TENANT_ID) " + + "SELECT e.ID, t.ID, ? " + + "FROM DM_ENROLMENT e " + + "JOIN DM_DEVICE d ON d.ID = e.DEVICE_ID " + + "JOIN DM_TAG t ON t.NAME IN (%s) " + + "WHERE d.DEVICE_IDENTIFICATION IN (%s) " + + "AND e.DEVICE_TYPE = ? " + + "AND e.STATUS != 'REMOVED' " + + "AND e.TENANT_ID = ? " + + "AND t.TENANT_ID = ? " + + "AND NOT EXISTS ( " + + " SELECT 1 " + + " FROM DM_DEVICE_TAG_MAPPING m " + + " WHERE m.ENROLMENT_ID = e.ID " + + " AND m.TAG_ID = t.ID " + + " AND m.TENANT_ID = ? " + + ")", + tagNamesPlaceholders, + deviceIdentifiersPlaceholders + ); + + Connection connection; + PreparedStatement preparedStatement = null; + try { + connection = getConnection(); + preparedStatement = connection.prepareStatement(query); + int paramIndex = 1; + preparedStatement.setInt(paramIndex++, tenantId); + for (String tagName : tagNames) { + preparedStatement.setString(paramIndex++, tagName); + } + for (String deviceIdentifier : deviceIdentifiers) { + preparedStatement.setString(paramIndex++, deviceIdentifier); + } + preparedStatement.setString(paramIndex++, deviceType); + preparedStatement.setInt(paramIndex++, tenantId); + preparedStatement.setInt(paramIndex++, tenantId); + preparedStatement.setInt(paramIndex, tenantId); + preparedStatement.executeUpdate(); + } catch (SQLIntegrityConstraintViolationException e) { + throw new TagManagementDAOException("Tag is already mapped to this device", e, true); + } catch (SQLException e) { + throw new TagManagementDAOException("Error occurred while adding device tag", e); + } finally { + cleanupResources(preparedStatement, null); + } + } + + @Override + public void deleteDeviceTagMapping(List deviceIdentifiers, String deviceType, List tagNames, int tenantId) throws TagManagementDAOException { + String deviceIdentifiersPlaceholders = String.join(", ", Collections.nCopies(deviceIdentifiers.size(), "?")); + String tagNamesPlaceholders = String.join(", ", Collections.nCopies(tagNames.size(), "?")); + + String query = String.format( + "DELETE FROM DM_DEVICE_TAG_MAPPING " + + "WHERE ENROLMENT_ID IN ( " + + " SELECT e.ID " + + " FROM DM_ENROLMENT e " + + " JOIN DM_DEVICE d ON d.ID = e.DEVICE_ID " + + " WHERE d.DEVICE_IDENTIFICATION IN (%s) " + + " AND e.DEVICE_TYPE = ? " + + " AND e.TENANT_ID = ? " + + " AND e.STATUS != 'REMOVED' " + + ") " + + "AND TAG_ID IN ( " + + " SELECT t.ID " + + " FROM DM_TAG t " + + " WHERE t.NAME IN (%s) " + + " AND t.TENANT_ID = ? " + + ")", + deviceIdentifiersPlaceholders, + tagNamesPlaceholders + ); + Connection connection; + PreparedStatement preparedStatement = null; + try { + connection = getConnection(); + preparedStatement = connection.prepareStatement(query); + int paramIndex = 1; + for (String deviceIdentifier : deviceIdentifiers) { + preparedStatement.setString(paramIndex++, deviceIdentifier); + } + preparedStatement.setString(paramIndex++, deviceType); + preparedStatement.setInt(paramIndex++, tenantId); + for (String tagName : tagNames) { + preparedStatement.setString(paramIndex++, tagName); + } + preparedStatement.setInt(paramIndex, tenantId); + preparedStatement.executeUpdate(); + } catch (SQLException e) { + throw new TagManagementDAOException("Error occurred while deleting device tag mapping", e); + } finally { + cleanupResources(preparedStatement, null); + } + } + + @Override + public List getTagsForDevice(int deviceId, int tenantId) throws TagManagementDAOException { + String query = "SELECT * FROM DM_DEVICE_TAG_MAPPING WHERE DEVICE_ID = ? AND TENANT_ID = ?"; + Connection connection; + PreparedStatement preparedStatement = null; + ResultSet resultSet = null; + List deviceTags = new ArrayList<>(); + + try { + connection = getConnection(); + preparedStatement = connection.prepareStatement(query); + preparedStatement.setInt(1, deviceId); + preparedStatement.setInt(2, tenantId); + + resultSet = preparedStatement.executeQuery(); + while (resultSet.next()) { + DeviceTag deviceTag = loadDeviceTagMapping(resultSet); + deviceTags.add(deviceTag); + } + } catch (SQLException e) { + throw new TagManagementDAOException("Error occurred while retrieving device tags", e); + } finally { + cleanupResources(preparedStatement, resultSet); + } + return deviceTags; + } + + @Override + public List getDevicesForTag(int tagId, int tenantId) throws TagManagementDAOException { + String query = "SELECT * FROM DM_DEVICE_TAG_MAPPING WHERE TAG_ID = ? AND TENANT_ID = ?"; + Connection connection; + PreparedStatement preparedStatement = null; + ResultSet resultSet = null; + List deviceTags = new ArrayList<>(); + + try { + connection = getConnection(); + preparedStatement = connection.prepareStatement(query); + preparedStatement.setInt(1, tagId); + preparedStatement.setInt(2, tenantId); + + resultSet = preparedStatement.executeQuery(); + while (resultSet.next()) { + DeviceTag deviceTag = loadDeviceTagMapping(resultSet); + deviceTags.add(deviceTag); + } + } catch (SQLException e) { + throw new TagManagementDAOException("Error occurred while retrieving devices for tag", e); + } finally { + cleanupResources(preparedStatement, resultSet); + } + return deviceTags; + } +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java index 5710e0181f..29275128bf 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java @@ -71,6 +71,8 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { boolean isSinceProvided = false; String serial = request.getSerialNumber(); boolean isSerialProvided = false; + List tagList = request.getTags(); + boolean isTagsProvided = false; try { Connection conn = getConnection(); @@ -86,7 +88,10 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { "e.IS_TRANSFERRED, " + "e.DATE_OF_LAST_UPDATE, " + "e.DATE_OF_ENROLMENT, " + - "e.ID AS ENROLMENT_ID " + + "e.ID AS ENROLMENT_ID, " + + "( SELECT GROUP_CONCAT(t.NAME ORDER BY t.NAME SEPARATOR ', ') " + + "FROM DM_DEVICE_TAG_MAPPING dtm JOIN DM_TAG t ON dtm.TAG_ID = t.ID " + + "WHERE dtm.ENROLMENT_ID = e.ID ) AS TAGS " + "FROM DM_ENROLMENT e, " + "(SELECT d.ID, " + "d.DESCRIPTION, " + @@ -162,7 +167,27 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { sql += buildStatusQuery(statusList); isStatusProvided = true; } - sql = sql + " LIMIT ? OFFSET ?"; + sql += " AND e.ID IN (" + + "SELECT e.ID " + + "FROM DM_ENROLMENT e " + + "LEFT JOIN DM_DEVICE_TAG_MAPPING dtm ON e.ID = dtm.ENROLMENT_ID " + + "LEFT JOIN DM_TAG t ON dtm.TAG_ID = t.ID "; + + if (tagList != null && !tagList.isEmpty()) { + sql += " WHERE t.NAME IN ("; + for (int i = 0; i < tagList.size(); i++) { + if (i > 0) { + sql += ", "; + } + sql += "?"; + } + sql += ") GROUP BY e.ID HAVING COUNT(DISTINCT t.NAME) = ? "; + isTagsProvided = true; + } else { + sql += " GROUP BY e.ID "; + } + sql += ") "; + sql += " LIMIT ? OFFSET ?"; try (PreparedStatement stmt = conn.prepareStatement(sql)) { int paramIdx = 1; @@ -198,13 +223,19 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { stmt.setString(paramIdx++, status); } } + if (isTagsProvided) { + for (String tag : tagList) { + stmt.setString(paramIdx++, tag); + } + stmt.setInt(paramIdx++, tagList.size()); + } stmt.setInt(paramIdx++, request.getRowCount()); stmt.setInt(paramIdx, request.getStartIndex()); try (ResultSet rs = stmt.executeQuery()) { devices = new ArrayList<>(); while (rs.next()) { - Device device = DeviceManagementDAOUtil.loadDevice(rs); + Device device = DeviceManagementDAOUtil.loadDevice(rs, true); devices.add(device); } return devices; @@ -667,6 +698,8 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { boolean isSinceProvided = false; String serial = request.getSerialNumber(); boolean isSerialProvided = false; + List tagList = request.getTags(); + boolean isTagsProvided = false; try { Connection conn = getConnection(); @@ -682,7 +715,10 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { "e.IS_TRANSFERRED, " + "e.DATE_OF_LAST_UPDATE, " + "e.DATE_OF_ENROLMENT, " + - "e.ID AS ENROLMENT_ID " + + "e.ID AS ENROLMENT_ID, " + + "( SELECT GROUP_CONCAT(t.NAME ORDER BY t.NAME SEPARATOR ', ') " + + "FROM DM_DEVICE_TAG_MAPPING dtm JOIN DM_TAG t ON dtm.TAG_ID = t.ID " + + "WHERE dtm.ENROLMENT_ID = e.ID ) AS TAGS " + "FROM DM_ENROLMENT e, " + "(SELECT gd.DEVICE_ID, " + "gd.DESCRIPTION, " + @@ -739,7 +775,7 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { //Filter Group with serial number or any Custom Property in DM_DEVICE_INFO if (serial != null || !request.getCustomProperty().isEmpty()) { if (serial != null) { - sql += "AND EXISTS (" + + sql += " AND EXISTS (" + "SELECT VALUE_FIELD " + "FROM DM_DEVICE_INFO di " + "WHERE di.DEVICE_ID = d1.DEVICE_ID " + @@ -749,7 +785,7 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { } if (!request.getCustomProperty().isEmpty()) { for (Map.Entry entry : request.getCustomProperty().entrySet()) { - sql += "AND EXISTS (" + + sql += " AND EXISTS (" + "SELECT VALUE_FIELD " + "FROM DM_DEVICE_INFO di2 " + "WHERE di2.DEVICE_ID = d1.DEVICE_ID " + @@ -758,6 +794,24 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { } } } + if (tagList != null && !tagList.isEmpty()) { + sql += " AND e.ID IN (" + + "SELECT e.ID " + + "FROM DM_ENROLMENT e " + + "LEFT JOIN DM_DEVICE_TAG_MAPPING dtm ON e.ID = dtm.ENROLMENT_ID " + + "LEFT JOIN DM_TAG t ON dtm.TAG_ID = t.ID " + + "WHERE t.NAME IN ("; + for (int i = 0; i < tagList.size(); i++) { + if (i > 0) { + sql += ", "; + } + sql += "?"; + } + sql += ") GROUP BY e.ID HAVING COUNT(DISTINCT t.NAME) = ? ) "; + isTagsProvided = true; + } else { + sql += " GROUP BY e.ID "; + } sql = sql + " LIMIT ? OFFSET ?"; try (PreparedStatement stmt = conn.prepareStatement(sql)) { @@ -795,13 +849,19 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { stmt.setString(paramIdx++, "%" + entry.getValue() + "%"); } } + if (isTagsProvided) { + for (String tag : tagList) { + stmt.setString(paramIdx++, tag); + } + stmt.setInt(paramIdx++, tagList.size()); + } stmt.setInt(paramIdx++, request.getRowCount()); stmt.setInt(paramIdx, request.getStartIndex()); try (ResultSet rs = stmt.executeQuery()) { devices = new ArrayList<>(); while (rs.next()) { - Device device = DeviceManagementDAOUtil.loadDevice(rs); + Device device = DeviceManagementDAOUtil.loadDevice(rs, true); devices.add(device); } return devices; diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/device/PostgreSQLDeviceDAOImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/device/PostgreSQLDeviceDAOImpl.java index 0f502cf874..923189dea3 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/device/PostgreSQLDeviceDAOImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/device/PostgreSQLDeviceDAOImpl.java @@ -68,6 +68,8 @@ public class PostgreSQLDeviceDAOImpl extends GenericDeviceDAOImpl { boolean isSinceProvided = false; String serial = request.getSerialNumber(); boolean isSerialProvided = false; + List tagList = request.getTags(); + boolean isTagsProvided = false; try { conn = getConnection(); @@ -82,7 +84,10 @@ public class PostgreSQLDeviceDAOImpl extends GenericDeviceDAOImpl { "e.IS_TRANSFERRED, " + "e.DATE_OF_LAST_UPDATE, " + "e.DATE_OF_ENROLMENT, " + - "e.ID AS ENROLMENT_ID " + + "e.ID AS ENROLMENT_ID, " + + "(SELECT STRING_AGG(t.NAME, ', ') FROM DM_DEVICE_TAG_MAPPING dtm " + + "JOIN DM_TAG t ON dtm.TAG_ID = t.ID " + + "WHERE dtm.ENROLMENT_ID = e.ID) AS TAGS " + "FROM DM_ENROLMENT e, " + "(SELECT d.ID, " + "d.DESCRIPTION, " + @@ -155,6 +160,19 @@ public class PostgreSQLDeviceDAOImpl extends GenericDeviceDAOImpl { sql += buildStatusQuery(statusList); isStatusProvided = true; } + if (tagList != null && !tagList.isEmpty()) { + sql += " AND e.ID IN (SELECT e.ID FROM DM_ENROLMENT e " + + "LEFT JOIN DM_DEVICE_TAG_MAPPING dtm ON e.ID = dtm.ENROLMENT_ID " + + "LEFT JOIN DM_TAG t ON dtm.TAG_ID = t.ID WHERE t.NAME IN ("; + for (int i = 0; i < tagList.size(); i++) { + if (i > 0) { + sql += ", "; + } + sql += "?"; + } + sql += ") GROUP BY e.ID HAVING COUNT(DISTINCT t.NAME) = ? ) "; + isTagsProvided = true; + } sql = sql + " LIMIT ? OFFSET ?"; try (PreparedStatement stmt = conn.prepareStatement(sql)) { @@ -188,6 +206,12 @@ public class PostgreSQLDeviceDAOImpl extends GenericDeviceDAOImpl { stmt.setString(paramIdx++, status); } } + if (isTagsProvided) { + for (String tag : tagList) { + stmt.setString(paramIdx++, tag); + } + stmt.setInt(paramIdx++, tagList.size()); + } stmt.setInt(paramIdx++, request.getRowCount()); stmt.setInt(paramIdx, request.getStartIndex()); @@ -466,6 +490,8 @@ public class PostgreSQLDeviceDAOImpl extends GenericDeviceDAOImpl { boolean isSinceProvided = false; String serial = request.getSerialNumber(); boolean isSerialProvided = false; + List tagList = request.getTags(); + boolean isTagsProvided = false; try { conn = getConnection(); @@ -480,7 +506,10 @@ public class PostgreSQLDeviceDAOImpl extends GenericDeviceDAOImpl { "e.IS_TRANSFERRED, " + "e.DATE_OF_LAST_UPDATE, " + "e.DATE_OF_ENROLMENT, " + - "e.ID AS ENROLMENT_ID " + + "e.ID AS ENROLMENT_ID, " + + "(SELECT STRING_AGG(t.NAME, ', ') FROM DM_DEVICE_TAG_MAPPING dtm " + + "JOIN DM_TAG t ON dtm.TAG_ID = t.ID " + + "WHERE dtm.ENROLMENT_ID = e.ID) AS TAGS " + "FROM DM_ENROLMENT e, " + "(SELECT gd.DEVICE_ID, " + "gd.DESCRIPTION, " + @@ -555,6 +584,24 @@ public class PostgreSQLDeviceDAOImpl extends GenericDeviceDAOImpl { } } } + if (tagList != null && !tagList.isEmpty()) { + sql += " AND e.ID IN (" + + "SELECT e.ID " + + "FROM DM_ENROLMENT e " + + "LEFT JOIN DM_DEVICE_TAG_MAPPING dtm ON e.ID = dtm.ENROLMENT_ID " + + "LEFT JOIN DM_TAG t ON dtm.TAG_ID = t.ID " + + "WHERE t.NAME IN ("; + for (int i = 0; i < tagList.size(); i++) { + if (i > 0) { + sql += ", "; + } + sql += "?"; + } + sql += ") GROUP BY e.ID HAVING COUNT(DISTINCT t.NAME) = ? ) "; + isTagsProvided = true; + } else { + sql += " GROUP BY e.ID "; + } sql = sql + " LIMIT ? OFFSET ?"; try (PreparedStatement stmt = conn.prepareStatement(sql)) { @@ -592,13 +639,19 @@ public class PostgreSQLDeviceDAOImpl extends GenericDeviceDAOImpl { stmt.setString(paramIdx++, "%" + entry.getValue() + "%"); } } + if (isTagsProvided) { + for (String tag : tagList) { + stmt.setString(paramIdx++, tag); + } + stmt.setInt(paramIdx++, tagList.size()); + } stmt.setInt(paramIdx++, request.getRowCount()); stmt.setInt(paramIdx, request.getStartIndex()); try (ResultSet rs = stmt.executeQuery()) { devices = new ArrayList<>(); while (rs.next()) { - Device device = DeviceManagementDAOUtil.loadDevice(rs); + Device device = DeviceManagementDAOUtil.loadDevice(rs, true); devices.add(device); } return devices; diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java index 7de242ead9..47823054d8 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java @@ -69,6 +69,8 @@ public class SQLServerDeviceDAOImpl extends GenericDeviceDAOImpl { boolean isSinceProvided = false; String serial = request.getSerialNumber(); boolean isSerialProvided = false; + List tagList = request.getTags(); + boolean isTagsProvided = false; try { conn = getConnection(); @@ -83,7 +85,10 @@ public class SQLServerDeviceDAOImpl extends GenericDeviceDAOImpl { "e.IS_TRANSFERRED, " + "e.DATE_OF_LAST_UPDATE, " + "e.DATE_OF_ENROLMENT, " + - "e.ID AS ENROLMENT_ID " + + "e.ID AS ENROLMENT_ID, " + + "(SELECT STRING_AGG(t.NAME, ', ') FROM DM_DEVICE_TAG_MAPPING dtm " + + "JOIN DM_TAG t ON dtm.TAG_ID = t.ID " + + "WHERE dtm.ENROLMENT_ID = e.ID) AS TAGS " + "FROM DM_ENROLMENT e, " + "(SELECT d.ID, " + "d.DESCRIPTION, " + @@ -161,6 +166,19 @@ public class SQLServerDeviceDAOImpl extends GenericDeviceDAOImpl { sql += buildStatusQuery(statusList); isStatusProvided = true; } + if (tagList!= null && !tagList.isEmpty()) { + sql += " AND e.ID IN (SELECT e.ID FROM DM_ENROLMENT e " + + "LEFT JOIN DM_DEVICE_TAG_MAPPING dtm ON e.ID = dtm.ENROLMENT_ID " + + "LEFT JOIN DM_TAG t ON dtm.TAG_ID = t.ID WHERE t.NAME IN ("; + for (int i = 0; i < tagList.size(); i++) { + if (i > 0) { + sql += ", "; + } + sql += "?"; + } + sql += ") GROUP BY e.ID HAVING COUNT(DISTINCT t.NAME) = ? ) "; + isTagsProvided = true; + } sql = sql + " ORDER BY ENROLMENT_ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; try (PreparedStatement stmt = conn.prepareStatement(sql)) { @@ -197,13 +215,19 @@ public class SQLServerDeviceDAOImpl extends GenericDeviceDAOImpl { stmt.setString(paramIdx++, status); } } + if (isTagsProvided) { + for (String tag : tagList) { + stmt.setString(paramIdx++, tag); + } + stmt.setInt(paramIdx++, tagList.size()); + } stmt.setInt(paramIdx++, request.getStartIndex()); stmt.setInt(paramIdx, request.getRowCount()); try (ResultSet rs = stmt.executeQuery()) { devices = new ArrayList<>(); while (rs.next()) { - Device device = DeviceManagementDAOUtil.loadDevice(rs); + Device device = DeviceManagementDAOUtil.loadDevice(rs, true); devices.add(device); } return devices; @@ -485,6 +509,8 @@ public class SQLServerDeviceDAOImpl extends GenericDeviceDAOImpl { boolean isSinceProvided = false; String serial = request.getSerialNumber(); boolean isSerialProvided = false; + List tagList = request.getTags(); + boolean isTagsProvided = false; try { conn = getConnection(); @@ -499,7 +525,10 @@ public class SQLServerDeviceDAOImpl extends GenericDeviceDAOImpl { "e.IS_TRANSFERRED, " + "e.DATE_OF_LAST_UPDATE, " + "e.DATE_OF_ENROLMENT, " + - "e.ID AS ENROLMENT_ID " + + "e.ID AS ENROLMENT_ID, " + + "(SELECT STRING_AGG(t.NAME, ', ') FROM DM_DEVICE_TAG_MAPPING dtm " + + "JOIN DM_TAG t ON dtm.TAG_ID = t.ID " + + "WHERE dtm.ENROLMENT_ID = e.ID) AS TAGS " + "FROM DM_ENROLMENT e, " + "(SELECT gd.DEVICE_ID, " + "gd.DESCRIPTION, " + @@ -574,6 +603,24 @@ public class SQLServerDeviceDAOImpl extends GenericDeviceDAOImpl { } } } + + if (tagList != null && !tagList.isEmpty()) { + sql += " AND e.ID IN (" + + "SELECT e.ID FROM DM_ENROLMENT e " + + "LEFT JOIN DM_DEVICE_TAG_MAPPING dtm ON e.ID = dtm.ENROLMENT_ID " + + "LEFT JOIN DM_TAG t ON dtm.TAG_ID = t.ID " + + "WHERE t.NAME IN ("; + for (int i = 0; i < tagList.size(); i++) { + if (i > 0) { + sql += ", "; + } + sql += "?"; + } + sql += ") GROUP BY e.ID HAVING COUNT(DISTINCT t.NAME) = ?)"; + isTagsProvided = true; + } else { + sql += " GROUP BY e.ID "; + } sql = sql + " ORDER BY ENROLMENT_ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; try (PreparedStatement stmt = conn.prepareStatement(sql)) { @@ -611,13 +658,19 @@ public class SQLServerDeviceDAOImpl extends GenericDeviceDAOImpl { stmt.setString(paramIdx++, "%" + entry.getValue() + "%"); } } + if (isTagsProvided) { + for (String tag : tagList) { + stmt.setString(paramIdx++, tag); + } + stmt.setInt(paramIdx++, tagList.size()); + } stmt.setInt(paramIdx++, request.getStartIndex()); stmt.setInt(paramIdx, request.getRowCount()); try (ResultSet rs = stmt.executeQuery()) { devices = new ArrayList<>(); while (rs.next()) { - Device device = DeviceManagementDAOUtil.loadDevice(rs); + Device device = DeviceManagementDAOUtil.loadDevice(rs, true); devices.add(device); } return devices; diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/util/DeviceManagementDAOUtil.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/util/DeviceManagementDAOUtil.java index a8529398c7..6157f174fc 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/util/DeviceManagementDAOUtil.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/util/DeviceManagementDAOUtil.java @@ -26,16 +26,13 @@ import java.util.Date; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.el.lang.ELSupport; import org.wso2.carbon.context.CarbonContext; import io.entgra.device.mgt.core.device.mgt.common.Device; -import io.entgra.device.mgt.core.device.mgt.common.DeviceBilling; import io.entgra.device.mgt.core.device.mgt.common.DeviceIdentifier; import io.entgra.device.mgt.core.device.mgt.common.EnrolmentInfo; import io.entgra.device.mgt.core.device.mgt.common.device.details.DeviceInfo; import io.entgra.device.mgt.core.device.mgt.common.device.details.DeviceLocationHistorySnapshot; import io.entgra.device.mgt.core.device.mgt.common.device.details.DeviceMonitoringData; -import io.entgra.device.mgt.core.device.mgt.common.type.mgt.DeviceStatus; import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceManagementDAOException; import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceType; import io.entgra.device.mgt.core.device.mgt.core.internal.DeviceManagementDataHolder; @@ -143,6 +140,10 @@ public final class DeviceManagementDAOUtil { }*/ public static EnrolmentInfo loadEnrolment(ResultSet rs) throws SQLException { + return loadEnrolment(rs, false); + } + + public static EnrolmentInfo loadEnrolment(ResultSet rs, boolean isTagsProvided) throws SQLException { EnrolmentInfo enrolmentInfo = new EnrolmentInfo(); enrolmentInfo.setId(rs.getInt("ENROLMENT_ID")); enrolmentInfo.setOwner(rs.getString("OWNER")); @@ -151,6 +152,16 @@ public final class DeviceManagementDAOUtil { enrolmentInfo.setDateOfEnrolment(rs.getTimestamp("DATE_OF_ENROLMENT").getTime()); enrolmentInfo.setDateOfLastUpdate(rs.getTimestamp("DATE_OF_LAST_UPDATE").getTime()); enrolmentInfo.setStatus(EnrolmentInfo.Status.valueOf(rs.getString("STATUS"))); + if (isTagsProvided) { + List tags = new ArrayList<>(); + String tagColumn = rs.getString("TAGS"); + if (tagColumn != null) { + for (String tag : tagColumn.split(",")) { + tags.add(tag.trim()); + } + } + enrolmentInfo.setTags(tags); + } return enrolmentInfo; } @@ -224,6 +235,10 @@ public final class DeviceManagementDAOUtil { } public static Device loadDevice(ResultSet rs) throws SQLException { + return loadDevice(rs, false); + } + + public static Device loadDevice(ResultSet rs, boolean isTagsProvided) throws SQLException { Device device = new Device(); device.setId(rs.getInt("DEVICE_ID")); device.setName(rs.getString("DEVICE_NAME")); @@ -231,7 +246,7 @@ public final class DeviceManagementDAOUtil { device.setType(rs.getString("DEVICE_TYPE")); device.setDeviceIdentifier(rs.getString("DEVICE_IDENTIFICATION")); device.setLastUpdatedTimeStamp(rs.getTimestamp("LAST_UPDATED_TIMESTAMP").getTime()); - device.setEnrolmentInfo(loadEnrolment(rs)); + device.setEnrolmentInfo(loadEnrolment(rs, isTagsProvided)); return device; } diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/util/TagManagementDAOUtil.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/util/TagManagementDAOUtil.java new file mode 100644 index 0000000000..71b79e013f --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/util/TagManagementDAOUtil.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you 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 io.entgra.device.mgt.core.device.mgt.core.dao.util; + +import io.entgra.device.mgt.core.device.mgt.common.tag.mgt.DeviceTag; +import io.entgra.device.mgt.core.device.mgt.common.tag.mgt.Tag; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.naming.InitialContext; +import javax.sql.DataSource; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Hashtable; + +/** + * This class represents utilities required to work with tag management data + */ +public final class TagManagementDAOUtil { + + private static final Log log = LogFactory.getLog(TagManagementDAOUtil.class); + + /** + * Cleanup resources used to transaction + * + * @param stmt Prepared statement used + * @param rs Obtained results set + */ + public static void cleanupResources(PreparedStatement stmt, ResultSet rs) { + if (rs != null) { + try { + rs.close(); + } catch (SQLException e) { + log.warn("Error occurred while closing result set", e); + } + } + if (stmt != null) { + try { + stmt.close(); + } catch (SQLException e) { + log.warn("Error occurred while closing prepared statement", e); + } + } + } + + /** + * Lookup datasource using name and jndi properties + * + * @param dataSourceName Name of datasource to lookup + * @param jndiProperties Hash table of JNDI Properties + * @return datasource looked + */ + public static DataSource lookupDataSource(String dataSourceName, + final Hashtable jndiProperties) { + try { + if (jndiProperties == null || jndiProperties.isEmpty()) { + return (DataSource) InitialContext.doLookup(dataSourceName); + } + final InitialContext context = new InitialContext(jndiProperties); + return (DataSource) context.lookup(dataSourceName); + } catch (Exception e) { + throw new RuntimeException("Error in looking up data source: " + e.getMessage(), e); + } + } + + public static Tag loadTag(ResultSet resultSet) throws SQLException { + Tag tag = new Tag(); + tag.setId(resultSet.getInt("ID")); + tag.setName(resultSet.getString("NAME")); + tag.setDescription(resultSet.getString("DESCRIPTION")); + return tag; + } + + public static DeviceTag loadDeviceTagMapping(ResultSet resultSet) throws SQLException { + DeviceTag deviceTag = new DeviceTag(); + deviceTag.setEnrolmentId(resultSet.getInt("ENROLMENT_ID")); + deviceTag.setTagId(resultSet.getInt("TAG_ID")); + return deviceTag; + } + +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/internal/DeviceManagementServiceComponent.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/internal/DeviceManagementServiceComponent.java index b2e1529f40..669e60c593 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/internal/DeviceManagementServiceComponent.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/internal/DeviceManagementServiceComponent.java @@ -21,6 +21,7 @@ import io.entgra.device.mgt.core.device.mgt.common.authorization.GroupAccessAuth import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceStatusManagementService; import io.entgra.device.mgt.core.device.mgt.core.authorization.GroupAccessAuthorizationServiceImpl; import io.entgra.device.mgt.core.device.mgt.core.metadata.mgt.DeviceStatusManagementServiceImpl; +import io.entgra.device.mgt.core.device.mgt.core.service.*; import io.entgra.device.mgt.core.server.bootup.heartbeat.beacon.service.HeartBeatManagementService; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -349,6 +350,10 @@ public class DeviceManagementServiceComponent { ReportManagementService reportManagementService = new ReportManagementServiceImpl(); bundleContext.registerService(ReportManagementService.class.getName(), reportManagementService, null); + /* Registering Tag Management Service */ + TagManagementProviderService tagManagementProviderService = new TagManagementProviderServiceImpl(); + bundleContext.registerService(TagManagementProviderService.class.getName(), tagManagementProviderService, null); + /* Registering DeviceAccessAuthorization Service */ DeviceAccessAuthorizationService deviceAccessAuthorizationService = new DeviceAccessAuthorizationServiceImpl(); DeviceManagementDataHolder.getInstance().setDeviceAccessAuthorizationService(deviceAccessAuthorizationService); diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/DeviceManagementProviderServiceImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/DeviceManagementProviderServiceImpl.java index 851153de16..7e3f835ab0 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/DeviceManagementProviderServiceImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/DeviceManagementProviderServiceImpl.java @@ -22,7 +22,7 @@ import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import io.entgra.device.mgt.core.device.mgt.common.exceptions.ConflictException; import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceStatusManagementService; -import io.entgra.device.mgt.core.device.mgt.core.dao.TenantDAO; +import io.entgra.device.mgt.core.device.mgt.core.dao.*; import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceDetailsDTO; import io.entgra.device.mgt.core.device.mgt.core.dto.OwnerWithDeviceDTO; import io.entgra.device.mgt.core.device.mgt.core.dto.OperationDTO; @@ -119,13 +119,6 @@ import io.entgra.device.mgt.core.device.mgt.core.cache.impl.DeviceCacheManagerIm import io.entgra.device.mgt.core.device.mgt.core.common.Constants; import io.entgra.device.mgt.core.device.mgt.core.config.DeviceConfigurationManager; import io.entgra.device.mgt.core.device.mgt.core.config.DeviceManagementConfig; -import io.entgra.device.mgt.core.device.mgt.core.dao.ApplicationDAO; -import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceDAO; -import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceManagementDAOException; -import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceManagementDAOFactory; -import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceStatusDAO; -import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceTypeDAO; -import io.entgra.device.mgt.core.device.mgt.core.dao.EnrollmentDAO; import io.entgra.device.mgt.core.device.mgt.core.operation.mgt.dao.OperationDAO; import io.entgra.device.mgt.core.device.mgt.core.dao.util.DeviceManagementDAOUtil; import io.entgra.device.mgt.core.device.mgt.core.device.details.mgt.DeviceDetailsMgtException; @@ -185,6 +178,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv private MetadataDAO metadataDAO; private final DeviceStatusDAO deviceStatusDAO; private final TenantDAO tenantDao; + private final TagDAO tagDAO; int count = 0; public DeviceManagementProviderServiceImpl() { @@ -197,6 +191,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv this.metadataDAO = MetadataManagementDAOFactory.getMetadataDAO(); this.deviceStatusDAO = DeviceManagementDAOFactory.getDeviceStatusDAO(); this.tenantDao = DeviceManagementDAOFactory.getTenantDAO(); + this.tagDAO = DeviceManagementDAOFactory.getTagDAO(); /* Registering a listener to retrieve events when some device management service plugin is installed after * the component is done getting initialized */ diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/TagManagementProviderService.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/TagManagementProviderService.java new file mode 100644 index 0000000000..6fccdc5701 --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/TagManagementProviderService.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you 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 io.entgra.device.mgt.core.device.mgt.core.service; + +import io.entgra.device.mgt.core.device.mgt.common.exceptions.BadRequestException; +import io.entgra.device.mgt.core.device.mgt.common.tag.mgt.*; + +import java.util.List; + +/** + * Defines the contract of TagManagementService. + */ +public interface TagManagementProviderService { + + /** + * Method to add a tag to the database. + * + * @param tag - Tag to be added to the database. + * @throws TagManagementException if something goes wrong while adding the Tag. + */ + void addTags(List tag) throws TagManagementException, BadRequestException; + + /** + * Method to fetch all tags. + * + * @return List of all Tags. + * @throws TagManagementException if something goes wrong while fetching the Tags. + */ + List getAllTags() throws TagManagementException; + + /** + * Method to update a tag in the database. + * + * @param tag - Tag to be updated in the database. + * @throws TagManagementException if something goes wrong while updating the Tag. + */ + void updateTag(Tag tag) throws TagManagementException, TagNotFoundException, BadRequestException; + + /** + * Method to delete a tag from the database. + * + * @param tagId - ID of the tag to be deleted. + * @throws TagManagementException if something goes wrong while deleting the Tag. + */ + void deleteTag(int tagId) throws TagManagementException, TagNotFoundException; + + /** + * Method to retrieve a tag by its ID. + * + * @param tagId - ID of the tag to be retrieved. + * @return Tag object retrieved from the database. + * @throws TagManagementException if something goes wrong while retrieving the Tag. + */ + Tag getTagById(int tagId) throws TagManagementException, TagNotFoundException; + + /** + * Method to retrieve a tag by its name. + * + * @param tagName - Name of the tag to be retrieved. + * @return Tag object retrieved from the database. + * @throws TagManagementException if something goes wrong while retrieving the Tag. + * @throws TagNotFoundException if the Tag with the given name is not found. + */ + Tag getTagByName(String tagName) throws TagManagementException, TagNotFoundException, BadRequestException; + + /** + * Method to add a device-tag mapping. + * + * @param tagMappingDto - TagMappingDTO object containing mapping information. + * @throws TagManagementException if something goes wrong while adding the device-tag mapping. + */ + void addDeviceTagMapping(TagMappingDTO tagMappingDto) throws TagManagementException, BadRequestException; + + /** + * Method to delete a device-tag mapping. + * + * @param tagMappingDTO - TagMappingDTO object containing mapping information. + * @throws TagManagementException if something goes wrong while deleting the device-tag mapping. + */ + void deleteDeviceTagMapping(TagMappingDTO tagMappingDTO) throws TagManagementException, BadRequestException; +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/TagManagementProviderServiceImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/TagManagementProviderServiceImpl.java new file mode 100644 index 0000000000..d7c5b1f112 --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/TagManagementProviderServiceImpl.java @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you 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 io.entgra.device.mgt.core.device.mgt.core.service; + +import io.entgra.device.mgt.core.device.mgt.common.exceptions.BadRequestException; +import io.entgra.device.mgt.core.device.mgt.common.exceptions.TransactionManagementException; +import io.entgra.device.mgt.core.device.mgt.common.tag.mgt.*; +import io.entgra.device.mgt.core.device.mgt.core.dao.*; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.context.CarbonContext; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +public class TagManagementProviderServiceImpl implements TagManagementProviderService { + private static final Log log = LogFactory.getLog(TagManagementProviderServiceImpl.class); + + private final TagDAO tagDAO; + + public TagManagementProviderServiceImpl() { + this.tagDAO = DeviceManagementDAOFactory.getTagDAO(); + } + + @Override + public void addTags(List tags) throws TagManagementException, BadRequestException { + if (tags == null || tags.isEmpty()) { + String msg = "Received incomplete data for tags"; + log.error(msg); + throw new BadRequestException(msg); + } + try { + int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); + DeviceManagementDAOFactory.beginTransaction(); + for (Tag tag : tags) { + if (tag.getName() == null) { + throw new BadRequestException("Tag name cannot be null"); + } + } + if (log.isDebugEnabled()) { + log.debug("Starting creating Tags."); + } + tagDAO.addTags(tags, tenantId); + DeviceManagementDAOFactory.commitTransaction(); + } catch (TransactionManagementException e) { + String msg = "Error occurred while initiating transaction."; + log.error(msg, e); + throw new TagManagementException(msg, e); + } catch (TagManagementDAOException e) { + DeviceManagementDAOFactory.rollbackTransaction(); + String msg = "Error occurred while adding tags to database."; + log.error(msg, e); + throw new TagManagementException(msg, e); + } catch (Exception e) { + String msg = "Error occurred in creating tags."; + log.error(msg, e); + throw new TagManagementException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + @Override + public List getAllTags() throws TagManagementException { + try { + int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); + DeviceManagementDAOFactory.beginTransaction(); + return tagDAO.getTags(tenantId); + } catch (TransactionManagementException e) { + String msg = "Error occurred while initiating transaction."; + log.error(msg, e); + throw new TagManagementException(msg, e); + } catch (TagManagementDAOException e) { + DeviceManagementDAOFactory.rollbackTransaction(); + String msg = "Error occurred while retrieving tags."; + log.error(msg, e); + throw new TagManagementException(msg, e); + } catch (Exception e) { + String msg = "Error occurred in retrieving tags."; + log.error(msg, e); + throw new TagManagementException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + @Override + public Tag getTagById(int tagId) throws TagManagementException, TagNotFoundException { + try { + int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); + DeviceManagementDAOFactory.beginTransaction(); + Tag tag = tagDAO.getTagById(tagId, tenantId); + DeviceManagementDAOFactory.commitTransaction(); + if (tag == null) { + String msg = "Tag with ID " + tagId + " not found."; + throw new TagNotFoundException(msg); + } + return tag; + } catch (TransactionManagementException | TagManagementDAOException e) { + DeviceManagementDAOFactory.rollbackTransaction(); + String msg = "Error occurred while retrieving the tag with ID: " + tagId; + log.error(msg, e); + throw new TagManagementException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + @Override + public Tag getTagByName(String tagName) throws TagManagementException, TagNotFoundException, BadRequestException { + if (tagName == null || tagName.trim().isEmpty()) { + String msg = "Tag name cannot be null or empty."; + log.error(msg); + throw new BadRequestException(msg); + } + + try { + int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); + DeviceManagementDAOFactory.beginTransaction(); + Tag tag = tagDAO.getTagByName(tagName, tenantId); + DeviceManagementDAOFactory.commitTransaction(); + + if (tag == null) { + String msg = "Tag with name " + tagName + " not found."; + throw new TagNotFoundException(msg); + } + + return tag; + } catch (TransactionManagementException | TagManagementDAOException e) { + DeviceManagementDAOFactory.rollbackTransaction(); + String msg = "Error occurred while retrieving the tag with name: " + tagName; + log.error(msg, e); + throw new TagManagementException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + + @Override + public void updateTag(Tag tag) throws TagManagementException, TagNotFoundException, BadRequestException { + if (tag == null || tag.getName() == null) { + String msg = "Received incomplete data for tag update"; + log.error(msg); + throw new BadRequestException(msg); + } + try { + int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); + DeviceManagementDAOFactory.openConnection(); + Tag existingTag = tagDAO.getTagById(tag.getId(), tenantId); + if (existingTag == null) { + String msg = "Tag with ID: " + tag.getId() + " does not exist."; + log.error(msg); + throw new TagNotFoundException(msg); + } + tagDAO.updateTag(tag, tenantId); + } catch (TagManagementDAOException | SQLException e) { + DeviceManagementDAOFactory.rollbackTransaction(); + String msg = "Error occurred while updating the tag with ID: " + tag.getId(); + log.error(msg, e); + throw new TagManagementException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + + @Override + public void deleteTag(int tagId) throws TagManagementException, TagNotFoundException { + try { + int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); + DeviceManagementDAOFactory.openConnection(); + Tag existingTag = tagDAO.getTagById(tagId, tenantId); + if (existingTag == null) { + String msg = "Tag with ID: " + tagId + " does not exist."; + log.error(msg); + throw new TagNotFoundException(msg); + } + tagDAO.deleteTag(tagId, tenantId); + DeviceManagementDAOFactory.commitTransaction(); + } catch (TagManagementDAOException | SQLException e) { + DeviceManagementDAOFactory.rollbackTransaction(); + String msg = "Error occurred while deleting the tag with ID: " + tagId; + log.error(msg, e); + throw new TagManagementException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + @Override + public void addDeviceTagMapping(TagMappingDTO tagMappingDto) throws TagManagementException, BadRequestException { + if (tagMappingDto == null || tagMappingDto.getDeviceIdentifiers() == null || tagMappingDto.getTags() == null + || tagMappingDto.getDeviceType() == null) { + String msg = "Received incomplete data for device tag mapping."; + log.error(msg); + throw new BadRequestException(msg); + } + try { + int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); + DeviceManagementDAOFactory.openConnection(); + + List tagList = new ArrayList<>(); + for (String tagName : tagMappingDto.getTags()) { + Tag tag = new Tag(); + tag.setName(tagName); + tagList.add(tag); + } + + tagDAO.addTags(tagList, tenantId); + tagDAO.addDeviceTagMapping(tagMappingDto.getDeviceIdentifiers(), tagMappingDto.getDeviceType(), + tagMappingDto.getTags(), tenantId); + + } catch (TagManagementDAOException e) { + if (e.isUniqueConstraintViolation()) { + String msg = "Tag is already mapped to this device."; + log.info(msg, e); + throw new BadRequestException(msg); + } else { + DeviceManagementDAOFactory.rollbackTransaction(); + String msg = "Error occurred while adding device tag mapping."; + log.error(msg, e); + throw new TagManagementException(msg, e); + } + } catch (SQLException e) { + DeviceManagementDAOFactory.rollbackTransaction(); + String msg = "Error occurred while adding device tag mapping."; + log.error(msg, e); + throw new TagManagementException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + @Override + public void deleteDeviceTagMapping(TagMappingDTO tagMappingDto) throws TagManagementException, BadRequestException { + if (tagMappingDto == null || tagMappingDto.getDeviceIdentifiers() == null || tagMappingDto.getTags() == null + || tagMappingDto.getDeviceType() == null) { + String msg = "Received incomplete data for device tag mapping."; + log.error(msg); + throw new BadRequestException(msg); + } + try { + int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); + DeviceManagementDAOFactory.openConnection(); + tagDAO.deleteDeviceTagMapping(tagMappingDto.getDeviceIdentifiers(), tagMappingDto.getDeviceType(), + tagMappingDto.getTags(), tenantId); + DeviceManagementDAOFactory.commitTransaction(); + } catch (TagManagementDAOException | SQLException e) { + DeviceManagementDAOFactory.rollbackTransaction(); + String msg = "Error occurred while deleting device tag mappings."; + log.error(msg, e); + throw new TagManagementException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } +} diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/java/io/entgra/device/mgt/core/device/mgt/core/TestUtils.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/java/io/entgra/device/mgt/core/device/mgt/core/TestUtils.java index 4d8e11064d..b477cd2a53 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/java/io/entgra/device/mgt/core/device/mgt/core/TestUtils.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/java/io/entgra/device/mgt/core/device/mgt/core/TestUtils.java @@ -17,6 +17,7 @@ */ package io.entgra.device.mgt.core.device.mgt.core; +import io.entgra.device.mgt.core.device.mgt.common.tag.mgt.Tag; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import io.entgra.device.mgt.core.device.mgt.common.DeviceIdentifier; @@ -100,6 +101,29 @@ public class TestUtils { return group; } + public static Tag getTag1() { + return new Tag(1,"tag1", "This is tag1"); + } + + public static Tag getTag2() { + return new Tag( "tag2", "This is tag2"); + } + public static Tag getTag3() { + return new Tag("tag3", "This is tag3"); + } + + public static List createTagList1() { + List tagList = new ArrayList<>(); + tagList.add(new Tag(null, "This is tag1")); + return tagList; + } + + public static List createTagList2() { + List tagList = new ArrayList<>(); + tagList.add(getTag1()); + tagList.add(getTag2()); + return tagList; + } public static GroupPaginationRequest createPaginationRequest(){ GroupPaginationRequest request = new GroupPaginationRequest(0, 5); diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/java/io/entgra/device/mgt/core/device/mgt/core/common/TestDataHolder.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/java/io/entgra/device/mgt/core/device/mgt/core/common/TestDataHolder.java index 322b2b449d..cffbb3389a 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/java/io/entgra/device/mgt/core/device/mgt/core/common/TestDataHolder.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/java/io/entgra/device/mgt/core/device/mgt/core/common/TestDataHolder.java @@ -27,6 +27,7 @@ import io.entgra.device.mgt.core.device.mgt.common.device.details.DeviceData; import io.entgra.device.mgt.core.device.mgt.common.device.details.DeviceInfo; import io.entgra.device.mgt.core.device.mgt.common.group.mgt.DeviceGroup; import io.entgra.device.mgt.core.device.mgt.common.notification.mgt.Notification; +import io.entgra.device.mgt.core.device.mgt.common.tag.mgt.Tag; import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceType; import java.util.ArrayList; @@ -34,6 +35,7 @@ import java.util.Date; import java.util.List; import java.util.Properties; import java.util.Calendar; +import java.util.Arrays; public class TestDataHolder { @@ -46,6 +48,7 @@ public class TestDataHolder { public static final String OPERATION_CONFIG = "TEST-OPERATION-"; public static Device initialTestDevice; public static DeviceType initialTestDeviceType; + public static List TAGS = Arrays.asList("tag1", "tag2", "tag3"); public static Date getTimeBefore(int minutes) { Calendar calendar = Calendar.getInstance(); @@ -56,7 +59,7 @@ public class TestDataHolder { public static Device generateDummyDeviceData(String deviceType) { Device device = new Device(); device.setEnrolmentInfo(generateEnrollmentInfo(new Date().getTime(), new Date().getTime(), OWNER, EnrolmentInfo - .OwnerShip.BYOD, EnrolmentInfo.Status.ACTIVE)); + .OwnerShip.BYOD, EnrolmentInfo.Status.ACTIVE, TAGS)); device.setDescription("Test Description"); device.setDeviceIdentifier(initialDeviceIdentifier); device.setType(deviceType); @@ -65,16 +68,26 @@ public class TestDataHolder { public static EnrolmentInfo generateEnrollmentInfo(long dateOfEnrollment, long dateOfLastUpdate, String owner, EnrolmentInfo.OwnerShip ownership, - EnrolmentInfo.Status status) { + EnrolmentInfo.Status status, List tags) { EnrolmentInfo enrolmentInfo = new EnrolmentInfo(); enrolmentInfo.setDateOfEnrolment(dateOfEnrollment); enrolmentInfo.setDateOfLastUpdate(dateOfLastUpdate); enrolmentInfo.setOwner(owner); enrolmentInfo.setOwnership(ownership); enrolmentInfo.setStatus(status); + enrolmentInfo.setTags(tags); return enrolmentInfo; } + public static List getTagList() { + List tagList = new ArrayList<>(); + for (int i = 1; i <= 3; i++) { + Tag tag = new Tag("tag" + i, "This is tag" + i); + tagList.add(tag); + } + return tagList; + } + public static DeviceInfo generateDummyDeviceInfo() { DeviceInfo deviceInfo = new DeviceInfo(); deviceInfo.setDeviceModel("DUMMY_MODEL"); @@ -141,8 +154,12 @@ public class TestDataHolder { public static Device generateDummyDeviceData(DeviceIdentifier deviceIdentifier) { Device device = new Device(); + List tags = new ArrayList<>(); + tags.add("tag1"); + tags.add("tag2"); + tags.add("tag3"); device.setEnrolmentInfo(generateEnrollmentInfo(new Date().getTime(), new Date().getTime(), OWNER, EnrolmentInfo - .OwnerShip.BYOD, EnrolmentInfo.Status.ACTIVE)); + .OwnerShip.BYOD, EnrolmentInfo.Status.ACTIVE, tags)); device.setDescription("Test Description"); device.setDeviceIdentifier(deviceIdentifier.getId()); device.setType(deviceIdentifier.getType()); diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/java/io/entgra/device/mgt/core/device/mgt/core/dao/DevicePersistTests.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/java/io/entgra/device/mgt/core/device/mgt/core/dao/DevicePersistTests.java index a8bc1b6924..db51133e2e 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/java/io/entgra/device/mgt/core/device/mgt/core/dao/DevicePersistTests.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/java/io/entgra/device/mgt/core/device/mgt/core/dao/DevicePersistTests.java @@ -47,6 +47,7 @@ import java.util.List; public class DevicePersistTests extends BaseDeviceManagementTest { DeviceDAO deviceDAO; + TagDAO tagDAO; DeviceTypeDAO deviceTypeDAO; private static final Log log = LogFactory.getLog(DevicePersistTests.class); @@ -56,6 +57,7 @@ public class DevicePersistTests extends BaseDeviceManagementTest { public void init() throws Exception { initDataSource(); deviceDAO = DeviceManagementDAOFactory.getDeviceDAO(); + tagDAO = DeviceManagementDAOFactory.getTagDAO(); deviceTypeDAO = DeviceManagementDAOFactory.getDeviceTypeDAO(); } @@ -103,6 +105,8 @@ public class DevicePersistTests extends BaseDeviceManagementTest { int deviceId = deviceDAO.addDevice(TestDataHolder.initialTestDeviceType.getId(), device, tenantId); device.setId(deviceId); deviceDAO.addEnrollment(device, tenantId); + tagDAO.addTags(TestDataHolder.getTagList(), tenantId); + tagDAO.addDeviceTagMapping(Collections.singletonList(device.getDeviceIdentifier()), TestDataHolder.TEST_DEVICE_TYPE, TestDataHolder.TAGS, tenantId); DeviceManagementDAOFactory.commitTransaction(); TestDataHolder.initialTestDevice = device; } catch (DeviceManagementDAOException e) { @@ -115,6 +119,10 @@ public class DevicePersistTests extends BaseDeviceManagementTest { String msg = "Error occurred while initiating transaction"; log.error(msg, e); Assert.fail(msg, e); + } catch (TagManagementDAOException e) { + String msg = "Error occurred while adding tag mappings"; + log.error(msg, e); + Assert.fail(msg, e); } finally { DeviceManagementDAOFactory.closeConnection(); } @@ -508,6 +516,223 @@ public class DevicePersistTests extends BaseDeviceManagementTest { } } + @Test(dependsOnMethods = "testAddDeviceTest") + public void getDevicesWithTag() throws DeviceManagementDAOException, TransactionManagementException { + try { + PaginationRequest pr = new PaginationRequest(0, 10); + pr.setTags(Collections.singletonList("tag1")); + DeviceManagementDAOFactory.beginTransaction(); + List results = deviceDAO.getDevices(pr, TestDataHolder.SUPER_TENANT_ID); + Assert.assertEquals(1, results.size(), "No device returned"); + DeviceManagementDAOFactory.commitTransaction(); + } catch (DeviceManagementDAOException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the device" + e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + @Test(dependsOnMethods = "testAddDeviceTest") + public void getDevicesWithTags() throws DeviceManagementDAOException, TransactionManagementException { + try { + PaginationRequest pr = new PaginationRequest(0, 10); + pr.setTags(TestDataHolder.TAGS); + DeviceManagementDAOFactory.beginTransaction(); + List results = deviceDAO.getDevices(pr, TestDataHolder.SUPER_TENANT_ID); + Assert.assertEquals(1, results.size(), "No device returned"); + DeviceManagementDAOFactory.commitTransaction(); + } catch (DeviceManagementDAOException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the device" + e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + @Test(dependsOnMethods = "testAddDeviceTest") + public void getDevicesWithNonExistingTags() throws DeviceManagementDAOException, TransactionManagementException { + try { + PaginationRequest pr = new PaginationRequest(0, 10); + pr.setTags(Collections.singletonList("tag10")); + DeviceManagementDAOFactory.beginTransaction(); + List results = deviceDAO.getDevices(pr, TestDataHolder.SUPER_TENANT_ID); + Assert.assertEquals(0, results.size(), "No device returned"); + DeviceManagementDAOFactory.commitTransaction(); + } catch (DeviceManagementDAOException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the device" + e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + @Test(dependsOnMethods = "testAddDeviceTest") + public void getDevicesWithTagAndStatus() throws DeviceManagementDAOException, TransactionManagementException { + try { + PaginationRequest pr = new PaginationRequest(0, 10); + pr.setStatusList(Collections.singletonList(Status.ACTIVE.name())); + pr.setTags(Collections.singletonList("tag1")); + DeviceManagementDAOFactory.beginTransaction(); + List results = deviceDAO.getDevices(pr, TestDataHolder.SUPER_TENANT_ID); + Assert.assertEquals(1, results.size(), "No device returned"); + DeviceManagementDAOFactory.commitTransaction(); + } catch (DeviceManagementDAOException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the device" + e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + @Test(dependsOnMethods = "testAddDeviceTest") + public void getDevicesWithTagsAndStatus() throws DeviceManagementDAOException, TransactionManagementException { + List tags = new ArrayList<>() ; + try { + PaginationRequest pr = new PaginationRequest(0, 10); + pr.setStatusList(Collections.singletonList(Status.ACTIVE.name())); + pr.setTags(tags); + DeviceManagementDAOFactory.beginTransaction(); + List results = deviceDAO.getDevices(pr, TestDataHolder.SUPER_TENANT_ID); + Assert.assertEquals(1, results.size(), "No device returned"); + DeviceManagementDAOFactory.commitTransaction(); + } catch (DeviceManagementDAOException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the device" + e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + @Test(dependsOnMethods = "testAddDeviceTest") + public void getDeviceCountWithTag() throws DeviceManagementDAOException, TransactionManagementException { + try { + PaginationRequest pr = new PaginationRequest(0, 10); + pr.setTags(Collections.singletonList("tag1")); + DeviceManagementDAOFactory.beginTransaction(); + int result = deviceDAO.getDeviceCount(pr, TestDataHolder.SUPER_TENANT_ID); + Assert.assertEquals(1, result, "No device returned"); + DeviceManagementDAOFactory.commitTransaction(); + } catch (DeviceManagementDAOException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the device" + e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + @Test(dependsOnMethods = "testAddDeviceTest") + public void getDeviceCountWithTags() throws DeviceManagementDAOException, TransactionManagementException { + try { + PaginationRequest pr = new PaginationRequest(0, 10); + pr.setTags(TestDataHolder.TAGS); + DeviceManagementDAOFactory.beginTransaction(); + int result = deviceDAO.getDeviceCount(pr, TestDataHolder.SUPER_TENANT_ID); + Assert.assertEquals(1, result, "No device returned"); + DeviceManagementDAOFactory.commitTransaction(); + } catch (DeviceManagementDAOException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the device" + e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + @Test(dependsOnMethods = "testAddDeviceTest") + public void getDeviceCountWithTagAndStatus() throws DeviceManagementDAOException, TransactionManagementException { + try { + PaginationRequest pr = new PaginationRequest(0, 10); + pr.setStatusList(Collections.singletonList(Status.ACTIVE.name())); + pr.setTags(Collections.singletonList("tag1")); + DeviceManagementDAOFactory.beginTransaction(); + int result = deviceDAO.getDeviceCount(pr, TestDataHolder.SUPER_TENANT_ID); + Assert.assertEquals(1, result, "No device returned"); + DeviceManagementDAOFactory.commitTransaction(); + } catch (DeviceManagementDAOException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the device" + e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + @Test(dependsOnMethods = "testAddDeviceTest") + public void getDeviceCountWithTagsAndStatus() throws DeviceManagementDAOException, TransactionManagementException { + try { + PaginationRequest pr = new PaginationRequest(0, 10); + pr.setStatusList(Collections.singletonList(Status.ACTIVE.name())); + pr.setTags(TestDataHolder.TAGS); + DeviceManagementDAOFactory.beginTransaction(); + int result = deviceDAO.getDeviceCount(pr, TestDataHolder.SUPER_TENANT_ID); + Assert.assertEquals(1, result, "No device returned"); + DeviceManagementDAOFactory.commitTransaction(); + } catch (DeviceManagementDAOException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the device" + e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + @Test(dependsOnMethods = "testAddDeviceTest") + public void getDevicesWithTagAndGroupId() throws DeviceManagementDAOException, TransactionManagementException { + try { + PaginationRequest pr = new PaginationRequest(0, 10); + pr.setTags(Collections.singletonList("tag1")); + pr.setGroupId(1); + DeviceManagementDAOFactory.beginTransaction(); + List results = deviceDAO.searchDevicesInGroup(pr, TestDataHolder.SUPER_TENANT_ID); + Assert.assertEquals(0, results.size(), "No device returned"); + DeviceManagementDAOFactory.commitTransaction(); + } catch (DeviceManagementDAOException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the device" + e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + @Test(dependsOnMethods = "testAddDeviceTest") + public void getDevicesWithTagsAndGroupId() throws DeviceManagementDAOException, TransactionManagementException { + try { + PaginationRequest pr = new PaginationRequest(0, 10); + pr.setTags(TestDataHolder.TAGS); + pr.setGroupId(1); + DeviceManagementDAOFactory.beginTransaction(); + List results = deviceDAO.searchDevicesInGroup(pr, TestDataHolder.SUPER_TENANT_ID); + Assert.assertEquals(0, results.size(), "No device returned"); + DeviceManagementDAOFactory.commitTransaction(); + } catch (DeviceManagementDAOException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the device" + e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + @Test(dependsOnMethods = "testAddDeviceTest") + public void getDeviceCountWithTagAndGroupId() throws DeviceManagementDAOException, TransactionManagementException { + try { + PaginationRequest pr = new PaginationRequest(0, 10); + pr.setTags(Collections.singletonList("tag1")); + pr.setGroupId(1); + DeviceManagementDAOFactory.beginTransaction(); + int result = deviceDAO.getCountOfDevicesInGroup(pr, TestDataHolder.SUPER_TENANT_ID); + Assert.assertEquals(0, result, "No device returned"); + DeviceManagementDAOFactory.commitTransaction(); + } catch (DeviceManagementDAOException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the device" + e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + @Test(dependsOnMethods = "testAddDeviceTest") + public void getDeviceCountWithTagsAndGroupId() throws DeviceManagementDAOException, TransactionManagementException { + try { + PaginationRequest pr = new PaginationRequest(0, 10); + pr.setTags(TestDataHolder.TAGS); + pr.setGroupId(1); + DeviceManagementDAOFactory.beginTransaction(); + int result = deviceDAO.getCountOfDevicesInGroup(pr, TestDataHolder.SUPER_TENANT_ID); + Assert.assertEquals(0, result, "No device returned"); + DeviceManagementDAOFactory.commitTransaction(); + } catch (DeviceManagementDAOException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the device" + e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + @Test(dependsOnMethods = "testAddDeviceTest") public void getCountOfDevicesInGroup() throws DeviceManagementDAOException, TransactionManagementException { PaginationRequest pr = new PaginationRequest(0, 10); diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/java/io/entgra/device/mgt/core/device/mgt/core/service/TagManagementProviderServiceTest.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/java/io/entgra/device/mgt/core/device/mgt/core/service/TagManagementProviderServiceTest.java new file mode 100644 index 0000000000..5a516eb567 --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/java/io/entgra/device/mgt/core/device/mgt/core/service/TagManagementProviderServiceTest.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you 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 io.entgra.device.mgt.core.device.mgt.core.service; + +import io.entgra.device.mgt.core.device.mgt.common.exceptions.BadRequestException; +import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceManagementException; +import io.entgra.device.mgt.core.device.mgt.common.tag.mgt.Tag; +import io.entgra.device.mgt.core.device.mgt.common.tag.mgt.TagManagementException; +import io.entgra.device.mgt.core.device.mgt.common.tag.mgt.TagMappingDTO; +import io.entgra.device.mgt.core.device.mgt.common.tag.mgt.TagNotFoundException; +import io.entgra.device.mgt.core.device.mgt.core.TestUtils; +import io.entgra.device.mgt.core.device.mgt.core.common.BaseDeviceManagementTest; +import io.entgra.device.mgt.core.device.mgt.core.config.DeviceConfigurationManager; +import io.entgra.device.mgt.core.device.mgt.core.internal.DeviceManagementDataHolder; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.wso2.carbon.registry.core.jdbc.realm.InMemoryRealmService; +import org.wso2.carbon.user.core.service.RealmService; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + + +public class TagManagementProviderServiceTest extends BaseDeviceManagementTest { + + private TagManagementProviderService tagManagementProviderService; + + public static final String DEVICE_ID_1 = "100001"; + public static final String DEVICE_ID_2 = "100002"; + private static final String DEVICE_TYPE = "RANDOM_DEVICE_TYPE"; + + @BeforeClass + @Override + public void init() throws Exception { + tagManagementProviderService = new TagManagementProviderServiceImpl(); + RealmService realmService = new InMemoryRealmService(); + DeviceManagementDataHolder.getInstance().setRealmService(realmService); + realmService.getTenantManager().getSuperTenantDomain(); + DeviceConfigurationManager.getInstance().initConfig(); + } + + @Test(expectedExceptions = {TagManagementException.class, BadRequestException.class}) + public void createTagsNull() throws TagManagementException, BadRequestException { + tagManagementProviderService.addTags(null); + } + + @Test(expectedExceptions = {TagManagementException.class, BadRequestException.class}, dependsOnMethods = "createTagsNull") + public void createTagsNameNullError() throws TagManagementException, BadRequestException { + tagManagementProviderService.addTags(TestUtils.createTagList1()); + } + + @Test(dependsOnMethods = "createTagsNameNullError") + public void createTags() throws TagManagementException, BadRequestException { + tagManagementProviderService.addTags(TestUtils.createTagList2()); + } + + @Test(expectedExceptions = {TagNotFoundException.class}, dependsOnMethods = "createTags") + public void updateTagsNotFound() throws TagNotFoundException, TagManagementException, BadRequestException { + String updateDescString = "This tag is updated"; + tagManagementProviderService.updateTag(new Tag(10,"tag10", updateDescString)); + } + + @Test(dependsOnMethods = "updateTagsNotFound") + public void updateTags() throws TagNotFoundException, TagManagementException, BadRequestException { + String updateDescString = "This tag is updated"; + tagManagementProviderService.updateTag(new Tag(1,"tag1", updateDescString)); + Tag tag = tagManagementProviderService.getTagById(1); + Assert.assertEquals(tag.getDescription(), updateDescString); + } + + @Test(dependsOnMethods = "updateTags", expectedExceptions = {TagNotFoundException.class}) + public void getTagNotFoundById() throws TagManagementException, TagNotFoundException { + tagManagementProviderService.getTagById(10); + } + + @Test(dependsOnMethods = "getTagNotFoundById", expectedExceptions = {BadRequestException.class}) + public void getTagNotFoundByNameNull() throws TagManagementException, TagNotFoundException, BadRequestException { + tagManagementProviderService.getTagByName(null); + } + + @Test(dependsOnMethods = "getTagNotFoundByNameNull", expectedExceptions = {TagNotFoundException.class}) + public void getTagNotFoundByName() throws TagManagementException, TagNotFoundException, BadRequestException { + tagManagementProviderService.getTagByName("tag10"); + } + + @Test(dependsOnMethods = "getTagNotFoundByName") + public void getTagById() throws TagManagementException, TagNotFoundException { + Tag tag = tagManagementProviderService.getTagById(2); + Assert.assertEquals(tag.getName(), TestUtils.getTag2().getName()); + } + + @Test(dependsOnMethods = "getTagById") + public void getTagByName() throws TagManagementException, TagNotFoundException, BadRequestException { + Tag tag = tagManagementProviderService.getTagByName("tag2"); + Assert.assertEquals(tag.getName(), TestUtils.getTag2().getName()); + } + + @Test(dependsOnMethods = "getTagByName") + public void getTags() throws TagManagementException { + List tags = tagManagementProviderService.getAllTags(); + Assert.assertEquals(tags.size(), 3); + } + + @Test(expectedExceptions = {TagNotFoundException.class}, dependsOnMethods = "getTags") + public void deleteTagNotExists() throws TagManagementException, TagNotFoundException { + tagManagementProviderService.deleteTag(10); + } + + @Test(dependsOnMethods = "deleteTagNotExists") + public void deleteTag() throws TagManagementException, TagNotFoundException { + tagManagementProviderService.deleteTag(1); + List tags = tagManagementProviderService.getAllTags(); + Assert.assertEquals(tags.size(), 2); + } + + @Test(expectedExceptions = {BadRequestException.class}, dependsOnMethods = "deleteTag") + public void createTagMappingsNull() throws TagManagementException, BadRequestException { + tagManagementProviderService.addDeviceTagMapping(null); + } + + @Test(expectedExceptions = {BadRequestException.class}, dependsOnMethods = "createTagMappingsNull") + public void createTagsMappingsNullDeviceIdentifiers() throws TagManagementException, DeviceManagementException { + TagMappingDTO tagMappingDTO = new TagMappingDTO(); + tagMappingDTO.setDeviceIdentifiers(null); + tagMappingDTO.setDeviceType(DEVICE_TYPE); + tagMappingDTO.setTags(new ArrayList<>(Arrays.asList("tag1", "tag2"))); + tagManagementProviderService.addDeviceTagMapping(tagMappingDTO); + } + + @Test(expectedExceptions = {BadRequestException.class}, dependsOnMethods = "createTagsMappingsNullDeviceIdentifiers") + public void createTagsMappingsNullDeviceType() throws TagManagementException, DeviceManagementException { + TagMappingDTO tagMappingDTO = new TagMappingDTO(); + tagMappingDTO.setDeviceIdentifiers(new ArrayList<>(Arrays.asList(DEVICE_ID_1, DEVICE_ID_2))); + tagMappingDTO.setDeviceType(null); + tagMappingDTO.setTags(new ArrayList<>(Arrays.asList("tag1", "tag2"))); + tagManagementProviderService.addDeviceTagMapping(tagMappingDTO); + } + + @Test(expectedExceptions = {BadRequestException.class}, dependsOnMethods = "createTagsMappingsNullDeviceType") + public void createTagsMappingsNullTags() throws TagManagementException, DeviceManagementException { + TagMappingDTO tagMappingDTO = new TagMappingDTO(); + tagMappingDTO.setDeviceIdentifiers(new ArrayList<>(Arrays.asList(DEVICE_ID_1, DEVICE_ID_2))); + tagMappingDTO.setDeviceType(DEVICE_TYPE); + tagMappingDTO.setTags(null); + tagManagementProviderService.addDeviceTagMapping(tagMappingDTO); + } + + @Test(dependsOnMethods = "createTagsMappingsNullTags") + public void createTagsMappings() throws TagManagementException, DeviceManagementException { + TagMappingDTO tagMappingDTO = new TagMappingDTO(); + tagMappingDTO.setDeviceIdentifiers(new ArrayList<>(Arrays.asList(DEVICE_ID_1, DEVICE_ID_2))); + tagMappingDTO.setDeviceType(DEVICE_TYPE); + tagMappingDTO.setTags(new ArrayList<>(Arrays.asList("tag1", "tag2"))); + tagManagementProviderService.addDeviceTagMapping(tagMappingDTO); + } + + @Test(expectedExceptions = {BadRequestException.class}, dependsOnMethods = "createTagsMappings") + public void deleteTagMappingsNull() throws TagManagementException, BadRequestException { + tagManagementProviderService.deleteDeviceTagMapping(null); + } + + @Test(expectedExceptions = {BadRequestException.class}, dependsOnMethods = "deleteTagMappingsNull") + public void deleteTagsMappingsNullDeviceIdentifiers() throws TagManagementException, DeviceManagementException { + TagMappingDTO tagMappingDTO = new TagMappingDTO(); + tagMappingDTO.setDeviceIdentifiers(null); + tagMappingDTO.setDeviceType(DEVICE_TYPE); + tagMappingDTO.setTags(new ArrayList<>(Arrays.asList("tag1", "tag2"))); + tagManagementProviderService.deleteDeviceTagMapping(tagMappingDTO); + } + + @Test(expectedExceptions = {BadRequestException.class}, dependsOnMethods = "deleteTagsMappingsNullDeviceIdentifiers") + public void deleteTagsMappingsNullDeviceType() throws TagManagementException, DeviceManagementException { + TagMappingDTO tagMappingDTO = new TagMappingDTO(); + tagMappingDTO.setDeviceIdentifiers(new ArrayList<>(Arrays.asList(DEVICE_ID_1, DEVICE_ID_2))); + tagMappingDTO.setDeviceType(null); + tagMappingDTO.setTags(new ArrayList<>(Arrays.asList("tag1", "tag2"))); + tagManagementProviderService.deleteDeviceTagMapping(tagMappingDTO); + } + + @Test(expectedExceptions = {BadRequestException.class}, dependsOnMethods = "deleteTagsMappingsNullDeviceType") + public void deleteTagsMappingsNullTags() throws TagManagementException, DeviceManagementException { + TagMappingDTO tagMappingDTO = new TagMappingDTO(); + tagMappingDTO.setDeviceIdentifiers(new ArrayList<>(Arrays.asList(DEVICE_ID_1, DEVICE_ID_2))); + tagMappingDTO.setDeviceType(DEVICE_TYPE); + tagMappingDTO.setTags(null); + tagManagementProviderService.deleteDeviceTagMapping(tagMappingDTO); + } + + @Test(dependsOnMethods = "deleteTagsMappingsNullTags") + public void deleteTagsMappings() throws TagManagementException, DeviceManagementException { + TagMappingDTO tagMappingDTO = new TagMappingDTO(); + tagMappingDTO.setDeviceIdentifiers(new ArrayList<>(Arrays.asList(DEVICE_ID_1, DEVICE_ID_2))); + tagMappingDTO.setDeviceType(DEVICE_TYPE); + tagMappingDTO.setTags(new ArrayList<>(Arrays.asList("tag1", "tag2"))); + tagManagementProviderService.deleteDeviceTagMapping(tagMappingDTO); + } +} + diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/resources/sql/h2.sql b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/resources/sql/h2.sql index 5f94591885..6ed4f5fddd 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/resources/sql/h2.sql +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/resources/sql/h2.sql @@ -685,3 +685,25 @@ CREATE TABLE IF NOT EXISTS DM_METADATA ( CONSTRAINT METADATA_KEY_TENANT_ID UNIQUE (METADATA_KEY, TENANT_ID) ); -- END OF METADATA TABLE -- + +-- DM_TAG TABLE -- +CREATE TABLE IF NOT EXISTS DM_TAG ( + ID BIGINT AUTO_INCREMENT, + NAME VARCHAR(255) NOT NULL, + DESCRIPTION VARCHAR(255) NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + CONSTRAINT DM_TAG_NAME_UNIQUE UNIQUE (NAME) + ); +-- END OF DM_TAG TABLE -- + +-- DM_DEVICE_TAG_MAPPING TABLE -- +CREATE TABLE IF NOT EXISTS DM_DEVICE_TAG_MAPPING ( + ENROLMENT_ID BIGINT NOT NULL, + TAG_ID BIGINT NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (ENROLMENT_ID, TAG_ID, TENANT_ID), + FOREIGN KEY (ENROLMENT_ID) REFERENCES DM_ENROLMENT(ID), + FOREIGN KEY (TAG_ID) REFERENCES DM_TAG(ID) ON DELETE CASCADE + ); +-- END OF DM_DEVICE_TAG_MAPPING TABLE -- diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/resources/testng.xml b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/resources/testng.xml index 9e8e787ce0..58789e4fd9 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/resources/testng.xml +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/test/resources/testng.xml @@ -43,6 +43,7 @@ +