diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/UserManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/UserManagementService.java index 659276becb..6000845829 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/UserManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/UserManagementService.java @@ -48,6 +48,7 @@ import io.swagger.annotations.ResponseHeader; import org.apache.axis2.transport.http.HTTPConstants; import org.wso2.carbon.apimgt.annotations.api.Scopes; import org.wso2.carbon.apimgt.annotations.api.Scope; +import org.wso2.carbon.device.mgt.jaxrs.beans.ActivityList; import org.wso2.carbon.device.mgt.jaxrs.beans.BasicUserInfo; import org.wso2.carbon.device.mgt.jaxrs.beans.BasicUserInfoList; import org.wso2.carbon.device.mgt.jaxrs.beans.Credential; @@ -155,6 +156,12 @@ import java.util.List; description = "Sending Enrollment Invitations to Users", key = "perm:users:send-invitation", permissions = {"/device-mgt/users/manage"} + ), + @Scope( + name = "Get activities", + description = "Get activities", + key = "perm:get-activity", + permissions = {"/device-mgt/devices/owning-device/view"} ) } ) @@ -924,4 +931,80 @@ public interface UserManagementService { @POST @Path("/validate") Response validateUser(Credential credential); + + @GET + @Path("/device/activities") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Getting Activity Details", + notes = "Get the details of the operations/activities executed by the server on the devices registered" + + " with WSO2 EMM, during a defined time period.", + tags = "Activity Info Provider", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:get-activity") + }) + } + ) + @ApiResponses(value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully fetched the activity details.", + response = ActivityList.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 was last modified.\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.\n"), + @ApiResponse( + code = 401, + message = "Unauthorized. \n Unauthorized request."), + @ApiResponse( + code = 404, + message = "Not Found. \n No activities found.", + response = ErrorResponse.class), + @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 the activity data.", + response = ErrorResponse.class) + }) + Response getActivities( + @ApiParam( + name = "since", + value = "Checks if the requested variant was created since the specified date-time.\n" + + "Provide the value in the following format: EEE, d MMM yyyy HH:mm:ss Z.\n" + + "Example: Mon, 05 Jan 2014 15:10:00 +0200") + @QueryParam("since") String since, + @ApiParam( + name = "offset", + value = "The starting pagination index for the complete list of qualified items.", + defaultValue = "0") + @QueryParam("offset") int offset, + @ApiParam( + name = "limit", + value = "Provide how many activity details you require from the starting pagination index/offset.", + defaultValue = "5") + @QueryParam("limit") int limit, + @ApiParam( + name = "If-Modified-Since", + value = "Checks if the requested variant was modified, since the specified date-time\n." + + "Provide the value in the following format: EEE, d MMM yyyy HH:mm:ss Z\n." + + "Example: Mon, 05 Jan 2014 15:10:00 +0200") + @HeaderParam("If-Modified-Since") String ifModifiedSince); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/DeviceManagementAdminService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/DeviceManagementAdminService.java index 0ac0677151..b96977adfb 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/DeviceManagementAdminService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/DeviceManagementAdminService.java @@ -32,6 +32,7 @@ import io.swagger.annotations.ResponseHeader; import org.wso2.carbon.apimgt.annotations.api.Scope; import org.wso2.carbon.apimgt.annotations.api.Scopes; import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceList; import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; import org.wso2.carbon.device.mgt.jaxrs.util.Constants; @@ -39,6 +40,7 @@ import javax.validation.constraints.Size; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import java.util.List; @SwaggerDefinition( info = @Info( @@ -68,6 +70,12 @@ import javax.ws.rs.core.Response; description = "Getting Details of a Device", key = "perm:admin:devices:view", permissions = {"/device-mgt/devices/owning-device/view"} + ), + @Scope( + name = "Update the Device Owner", + description = "Update the ownership of the device", + key = "perm:admin:devices:update-enrollment", + permissions = {"/device-mgt/admin/devices/update-enrollment"} ) } ) @@ -167,4 +175,54 @@ public interface DeviceManagementAdminService { required = false, defaultValue = "5") @QueryParam("limit") int limit); + + @PUT + @Path("/device-owner") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "PUT", + value = "Update the device owner", + notes = "Update enrollment owner for given device Identifiers.", + tags = "Device Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:admin:devices:update-enrollment") + }) + } + ) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK. \n Successfully update the owner of devices.", + response = DeviceList.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 was last modified.\n" + + "Used by caches, or in conditional requests."), + }), + @ApiResponse( + code = 400, + message = "The incoming request has more than one selection criteria defined via the query parameters.", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while fetching the device list.", + response = ErrorResponse.class) + }) Response updateEnrollOwner( + @ApiParam( + name = "Device Owner", + value = "The username that is going to use for the new device owner of given devices.", + required = true) + @QueryParam("owner") String owner, + @ApiParam( + name = "Device Identifiers", + value = "List of device identifiers.", + required = true) + List deviceIdentifiers); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java index dae2bbbf53..329c559903 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java @@ -39,12 +39,16 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HttpStatus; import org.eclipse.wst.common.uriresolver.internal.util.URIEncoder; +import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.device.mgt.common.DeviceManagementException; import org.wso2.carbon.device.mgt.common.EnrolmentInfo; import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManagementException; +import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; +import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; import org.wso2.carbon.device.mgt.core.DeviceManagementConstants; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.EmailMetaInfo; +import org.wso2.carbon.device.mgt.jaxrs.beans.ActivityList; import org.wso2.carbon.device.mgt.jaxrs.beans.BasicUserInfo; import org.wso2.carbon.device.mgt.jaxrs.beans.BasicUserInfoList; import org.wso2.carbon.device.mgt.jaxrs.beans.BasicUserInfoWrapper; @@ -88,8 +92,11 @@ import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.security.SecureRandom; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -793,8 +800,96 @@ public class UserManagementServiceImpl implements UserManagementService { } catch (UserStoreException e) { String msg = "Error occurred while retrieving user store to validate user"; log.error(msg, e); - return Response.serverError().entity( - new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); + return Response.serverError().entity(new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()) + .build(); + } + } + + @GET + @Override + @Path("/device/activities") + public Response getActivities( + @QueryParam("since") String since, + @QueryParam("offset") int offset, + @QueryParam("limit") int limit, + @HeaderParam("If-Modified-Since") String ifModifiedSince) { + long ifModifiedSinceTimestamp; + long sinceTimestamp; + long timestamp = 0; + boolean isIfModifiedSinceSet = false; + String initiatedBy; + if (log.isDebugEnabled()) { + log.debug("getActivities since: " + since + " , offset: " + offset + " ,limit: " + limit + " ," + + "ifModifiedSince: " + ifModifiedSince); + } + RequestValidationUtil.validatePaginationParameters(offset, limit); + if (ifModifiedSince != null && !ifModifiedSince.isEmpty()) { + Date ifSinceDate; + SimpleDateFormat format = new SimpleDateFormat(Constants.DEFAULT_SIMPLE_DATE_FORMAT); + try { + ifSinceDate = format.parse(ifModifiedSince); + } catch (ParseException e) { + return Response.status(400).entity(new ErrorResponse.ErrorResponseBuilder() + .setMessage("Invalid date string is provided in 'If-Modified-Since' header").build()).build(); + } + ifModifiedSinceTimestamp = ifSinceDate.getTime(); + isIfModifiedSinceSet = true; + timestamp = ifModifiedSinceTimestamp / 1000; + } else if (since != null && !since.isEmpty()) { + Date sinceDate; + SimpleDateFormat format = new SimpleDateFormat(Constants.DEFAULT_SIMPLE_DATE_FORMAT); + try { + sinceDate = format.parse(since); + } catch (ParseException e) { + return Response.status(400).entity(new ErrorResponse.ErrorResponseBuilder() + .setMessage("Invalid date string is provided in 'since' filter").build()).build(); + } + sinceTimestamp = sinceDate.getTime(); + timestamp = sinceTimestamp / 1000; + } + + if (timestamp == 0) { + //If timestamp is not sent by the user, a default value is set, that is equal to current time-12 hours. + long time = System.currentTimeMillis() / 1000; + timestamp = time - 42300; + } + if (log.isDebugEnabled()) { + log.debug("getActivities final timestamp " + timestamp); + } + + List activities; + int count; + ActivityList activityList = new ActivityList(); + DeviceManagementProviderService dmService; + + initiatedBy = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + try { + if (log.isDebugEnabled()) { + log.debug("Calling database to get activities."); + } + dmService = DeviceMgtAPIUtils.getDeviceManagementService(); + activities = dmService.getActivitiesUpdatedAfterByUser(timestamp, initiatedBy, limit, offset); + if (log.isDebugEnabled()) { + log.debug("Calling database to get activity count with timestamp and user."); + } + count = dmService.getActivityCountUpdatedAfterByUser(timestamp, initiatedBy); + if (log.isDebugEnabled()) { + log.debug("Activity count: " + count); + } + + activityList.setList(activities); + activityList.setCount(count); + if ((activities == null || activities.isEmpty()) && isIfModifiedSinceSet) { + return Response.notModified().build(); + } + return Response.ok().entity(activityList).build(); + } catch (OperationManagementException e) { + String msg = + "Error Response occurred while fetching the activities updated after given time stamp for the user " + + initiatedBy + "."; + log.error(msg, e); + return Response.serverError().entity(new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()) + .build(); } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/DeviceManagementAdminServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/DeviceManagementAdminServiceImpl.java index a6d98fc73c..38e5804751 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/DeviceManagementAdminServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/DeviceManagementAdminServiceImpl.java @@ -20,18 +20,23 @@ package org.wso2.carbon.device.mgt.jaxrs.service.impl.admin; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.solr.common.StringUtils; +import org.wso2.carbon.apimgt.integration.generated.client.publisher.StringUtil; import org.wso2.carbon.base.MultitenantConstants; import org.wso2.carbon.context.CarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.DeviceManagementException; +import org.wso2.carbon.device.mgt.common.InvalidDeviceException; import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.UserNotFoundException; import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceList; import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; import org.wso2.carbon.device.mgt.jaxrs.service.api.admin.DeviceManagementAdminService; import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil; import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils; +import javax.validation.constraints.Past; import javax.validation.constraints.Size; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; @@ -87,4 +92,32 @@ public class DeviceManagementAdminServiceImpl implements DeviceManagementAdminSe } } + @PUT + @Override + @Path("/device-owner") + public Response updateEnrollOwner( + @QueryParam("owner") String owner, + List deviceIdentifiers){ + try { + if (DeviceMgtAPIUtils.getDeviceManagementService().updateEnrollment(owner, deviceIdentifiers)){ + String msg = "Device owner is updated successfully."; + return Response.status(Response.Status.OK).entity(msg).build(); + } + String msg = "Device owner updating is failed."; + log.error(msg); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } catch(InvalidDeviceException e){ + String msg = "Invalid device identifiers are found with the request."; + log.error(msg); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + }catch (DeviceManagementException e) { + String msg = "Error occurred when updating device owners."; + log.error(msg); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } catch (UserNotFoundException e) { + String msg = "Couldn't found the owner in user store to update the owner of devices."; + log.error(msg); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/Constants.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/Constants.java index 728c461c7b..4525cdd38d 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/Constants.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/Constants.java @@ -30,6 +30,7 @@ public class Constants { public static final String DEFAULT_STREAM_VERSION = "1.0.0"; public static final String SCOPE = "scope"; public static final String JDBC_USERSTOREMANAGER = "org.wso2.carbon.user.core.jdbc.JDBCUserStoreManager"; + public static final String DEFAULT_SIMPLE_DATE_FORMAT = "EEE, d MMM yyyy HH:mm:ss Z"; public static final int DEFAULT_PAGE_LIMIT = 50; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/UserNotFoundException.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/UserNotFoundException.java new file mode 100644 index 0000000000..640e28b752 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/UserNotFoundException.java @@ -0,0 +1,44 @@ +package org.wso2.carbon.device.mgt.common; +/* + * Copyright (c) 2019, 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. + */ + +public class UserNotFoundException extends Exception { + + private static final long serialVersionUID = -5705727414452641634L; + + public UserNotFoundException(String msg, Exception nestedEx) { + super(msg, nestedEx); + } + + public UserNotFoundException(String message, Throwable cause) { + super(message, cause); + } + + public UserNotFoundException(String msg) { + super(msg); + } + + public UserNotFoundException() { + super(); + } + + public UserNotFoundException(Throwable cause) { + super(cause); + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java index e768749d7f..93a254d2c7 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java @@ -426,5 +426,16 @@ public interface DeviceDAO { */ List findGeoClusters(String deviceType, GeoCoordinate southWest, GeoCoordinate northEast, int geohashLength,int tenantId) throws DeviceManagementDAOException; + + /*** + * This method is used to identify whether given device ids are exist or not. + * + * @param deviceIdentifiers List of device identifiers. + * @param tenantId tenant id. + * @return returns list of device ids that matches with device identifiers. + * @throws DeviceManagementDAOException throws {@link DeviceManagementDAOException} if connections establishment + * fails. + */ + List getDevicesByIdentifiers(List deviceIdentifiers, int tenantId) throws DeviceManagementDAOException; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EnrollmentDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EnrollmentDAO.java index 843e8df646..b8230d6cf2 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EnrollmentDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EnrollmentDAO.java @@ -18,6 +18,7 @@ */ package org.wso2.carbon.device.mgt.core.dao; +import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.EnrolmentInfo; import org.wso2.carbon.device.mgt.common.EnrolmentInfo.Status; @@ -50,4 +51,16 @@ public interface EnrollmentDAO { List getEnrollmentsOfUser(int deviceId, String user, int tenantId) throws DeviceManagementDAOException; + /*** + *This method is used to update the owner of the enrollment for given set of devices to given user. + * + * @param devices List of devices. + * @param owner Username of the new device owner. + * @param tenantId tenant id. + * @return either (1) true, if device owner updating is succeed or false. + * @throws DeviceManagementDAOException if an error occurs when updating device owner. + */ + boolean updateOwnerOfEnrollment(List devices, String owner, int tenantId) + throws DeviceManagementDAOException; + } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java index 66e15a47cf..1e8a01e244 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java @@ -40,6 +40,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; +import java.util.StringJoiner; public abstract class AbstractDeviceDAOImpl implements DeviceDAO { @@ -1245,4 +1246,53 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO { } return geoClusters; } + + @Override + public List getDevicesByIdentifiers(List deviceIdentifiers, int tenantId) + throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + int index = 1; + int counter = 0; + List devices = new ArrayList<>(); + + StringJoiner joiner = new StringJoiner(",", + "SELECT " + + "d1.ID AS DEVICE_ID, d1.DESCRIPTION, d1.NAME AS DEVICE_NAME, d1.DEVICE_TYPE, " + + "d1.DEVICE_IDENTIFICATION, e.OWNER, e.OWNERSHIP, e.STATUS, e.DATE_OF_LAST_UPDATE, " + + "e.DATE_OF_ENROLMENT, e.ID AS ENROLMENT_ID " + + "FROM " + + "DM_ENROLMENT e, " + + "(SELECT d.ID, d.DESCRIPTION, d.NAME, t.NAME AS DEVICE_TYPE, d.DEVICE_IDENTIFICATION " + + "FROM DM_DEVICE d, DM_DEVICE_TYPE t " + + "WHERE " + + "t.ID = d.DEVICE_TYPE_ID AND d.DEVICE_IDENTIFICATION IN (", + ") AND d.TENANT_ID = ?) d1 " + + "WHERE d1.ID = e.DEVICE_ID AND TENANT_ID = ? " + + "ORDER BY e.DATE_OF_LAST_UPDATE DESC, e.STATUS ASC"); + while (counter < deviceIdentifiers.size()) { + joiner.add("?"); + counter++; + } + String query = joiner.toString(); + try (PreparedStatement ps = conn.prepareStatement(query)) { + for (String identifier : deviceIdentifiers) { + ps.setObject(index++, identifier); + } + ps.setInt(index++, tenantId); + ps.setInt(index, tenantId); + try (ResultSet rs = ps.executeQuery()) { + if (rs.next()) { + Device device = DeviceManagementDAOUtil.loadDevice(rs); + devices.add(device); + } + } + } + return devices; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while obtaining the DB connection when adding tags", + e); + } + } + } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/EnrollmentDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/EnrollmentDAOImpl.java index 89e20dc242..7bbb94bc89 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/EnrollmentDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/EnrollmentDAOImpl.java @@ -18,6 +18,7 @@ */ package org.wso2.carbon.device.mgt.core.dao.impl; +import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.EnrolmentInfo; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; @@ -28,6 +29,7 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Statement; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Date; @@ -361,6 +363,44 @@ public class EnrollmentDAOImpl implements EnrollmentDAO { } } + @Override + public boolean updateOwnerOfEnrollment(List devices, String owner, int tenantId) + throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + boolean updateStatus = true; + String sql = "UPDATE DM_ENROLMENT SET OWNER = ? WHERE ID = ? AND TENANT_ID = ?"; + try (PreparedStatement ps = conn.prepareStatement(sql)) { + if (conn.getMetaData().supportsBatchUpdates()) { + for (Device device : devices) { + ps.setString(1, owner); + ps.setInt(2, device.getId()); + ps.setInt(3, tenantId); + ps.addBatch(); + } + for (int i : ps.executeBatch()) { + if (i == 0 || i == Statement.SUCCESS_NO_INFO || i == Statement.EXECUTE_FAILED) { + updateStatus = false; + } + } + } else { + for (Device device : devices) { + ps.setString(1, owner); + ps.setInt(2, device.getId()); + ps.setInt(3, tenantId); + if (ps.executeUpdate() == 0) { + updateStatus = false; + } + } + } + } + return updateStatus; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while obtaining the DB connection when adding tags", + e); + } + } + private Connection getConnection() throws SQLException { return DeviceManagementDAOFactory.getConnection(); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java index 5e7658ae71..291a636678 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java @@ -17,7 +17,17 @@ */ package org.wso2.carbon.device.mgt.core.service; -import org.wso2.carbon.device.mgt.common.*; +import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; +import org.wso2.carbon.device.mgt.common.DeviceManagementException; +import org.wso2.carbon.device.mgt.common.EnrolmentInfo; +import org.wso2.carbon.device.mgt.common.FeatureManager; +import org.wso2.carbon.device.mgt.common.InvalidDeviceException; +import org.wso2.carbon.device.mgt.common.MonitoringOperation; +import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig; +import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.PaginationResult; +import org.wso2.carbon.device.mgt.common.UserNotFoundException; import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManagementException; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; import org.wso2.carbon.device.mgt.common.license.mgt.License; @@ -657,4 +667,7 @@ public interface DeviceManagementProviderService { List getDeviceIdentifiersByStatus(String deviceType, String deviceStatus) throws DeviceManagementException; boolean bulkUpdateDeviceStatus(String deviceType, List deviceList, String status) throws DeviceManagementException; + + boolean updateEnrollment(String owner, List deviceIdentifiers) + throws DeviceManagementException, UserNotFoundException, InvalidDeviceException; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java index fac5c6faa5..a763b701c3 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java @@ -48,6 +48,7 @@ import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.PaginationResult; import org.wso2.carbon.device.mgt.common.TransactionManagementException; +import org.wso2.carbon.device.mgt.common.UserNotFoundException; import org.wso2.carbon.device.mgt.common.app.mgt.Application; import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManagementException; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; @@ -2808,7 +2809,8 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv success = deviceDAO.setEnrolmentStatusInBulk(deviceType, status, tenantId, deviceList); DeviceManagementDAOFactory.commitTransaction(); } catch (DeviceManagementDAOException e) { - String msg = "Error occurred in while updating status of devices :" +deviceType + " status : " + deviceList.toString(); + String msg = "Error occurred in while updating status of devices :" + deviceType + " status : " + deviceList + .toString(); log.error(msg, e); throw new DeviceManagementException(msg, e); } catch (SQLException e) { @@ -2821,6 +2823,66 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv return success; } + public boolean updateEnrollment(String owner, List deviceIdentifiers) + throws DeviceManagementException, UserNotFoundException, InvalidDeviceException { + + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + List existingDevices; + owner = validateOwner(owner, tenantId); + try { + DeviceManagementDAOFactory.beginTransaction(); + existingDevices = deviceDAO.getDevicesByIdentifiers(deviceIdentifiers, tenantId); + if (existingDevices.size() != deviceIdentifiers.size()) { + for (Device device : existingDevices) { + deviceIdentifiers.remove(device.getDeviceIdentifier()); + } + String msg = + "Couldn't find device ids for requested all device identifiers. Therefore payload should " + + "contains device identifiers which are not in the system. Invalid device " + + "identifiers are " + deviceIdentifiers.toString(); + log.error(msg); + throw new InvalidDeviceException(msg); + } + if (enrollmentDAO.updateOwnerOfEnrollment(existingDevices, owner, tenantId)) { + DeviceManagementDAOFactory.commitTransaction(); + return true; + } + DeviceManagementDAOFactory.rollbackTransaction(); + return false; + } catch (TransactionManagementException e) { + String msg = "Error occurred while initiating transaction"; + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } catch (DeviceManagementDAOException e) { + String msg = "Error occurred either verifying existence of device ids or updating owner of the device."; + log.error(msg); + throw new DeviceManagementException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + private String validateOwner(String owner, int tenantId) throws UserNotFoundException, DeviceManagementException { + try { + if (StringUtils.isEmpty(owner)) { + owner = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + } else { + boolean isUserExisit = DeviceManagementDataHolder.getInstance().getRealmService() + .getTenantUserRealm(tenantId).getUserStoreManager().isExistingUser(owner); + if (!isUserExisit) { + String msg = "Owner does not exist in the user storage. Owner: " + owner; + log.error(msg); + throw new UserNotFoundException(msg); + } + } + return owner; + } catch (UserStoreException e) { + String msg = "Error occurred when checking whether owner is exist or not. Owner: " + owner; + log.error(msg); + throw new DeviceManagementException(msg, e); + } + } + private void extractDeviceLocationToUpdate(Device device) { List properties = device.getProperties(); if (properties != null) { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.v09.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/UserManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.v09.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/UserManagementService.java index d161259aa3..3167ff572f 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.v09.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/UserManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.v09.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/UserManagementService.java @@ -25,8 +25,6 @@ import io.swagger.annotations.ExtensionProperty; import io.swagger.annotations.Extension; import io.swagger.annotations.Tag; import io.swagger.annotations.Api; -import io.swagger.annotations.AuthorizationScope; -import io.swagger.annotations.Authorization; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiResponse; @@ -35,6 +33,7 @@ import io.swagger.annotations.ResponseHeader; import org.apache.axis2.transport.http.HTTPConstants; import org.wso2.carbon.apimgt.annotations.api.Scopes; import org.wso2.carbon.apimgt.annotations.api.Scope; +import org.wso2.carbon.device.mgt.jaxrs.beans.ActivityList; import org.wso2.carbon.device.mgt.jaxrs.beans.BasicUserInfo; import org.wso2.carbon.device.mgt.jaxrs.beans.BasicUserInfoList; import org.wso2.carbon.device.mgt.jaxrs.beans.EnrollmentInvitation; @@ -806,4 +805,80 @@ public interface UserManagementService { value = "List of email address of recipients", required = true) @Valid EnrollmentInvitation enrollmentInvitation); + + @GET + @Path("/device/activities") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Getting Activity Details", + notes = "Get the details of the operations/activities executed by the server on the devices registered" + + " with WSO2 EMM, during a defined time period.", + tags = "Activity Info Provider", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:get-activity") + }) + } + ) + @ApiResponses(value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully fetched the activity details.", + response = ActivityList.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 was last modified.\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.\n"), + @ApiResponse( + code = 401, + message = "Unauthorized. \n Unauthorized request."), + @ApiResponse( + code = 404, + message = "Not Found. \n No activities found.", + response = ErrorResponse.class), + @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 the activity data.", + response = ErrorResponse.class) + }) + Response getActivities( + @ApiParam( + name = "since", + value = "Checks if the requested variant was created since the specified date-time.\n" + + "Provide the value in the following format: EEE, d MMM yyyy HH:mm:ss Z.\n" + + "Example: Mon, 05 Jan 2014 15:10:00 +0200") + @QueryParam("since") String since, + @ApiParam( + name = "offset", + value = "The starting pagination index for the complete list of qualified items.", + defaultValue = "0") + @QueryParam("offset") int offset, + @ApiParam( + name = "limit", + value = "Provide how many activity details you require from the starting pagination index/offset.", + defaultValue = "5") + @QueryParam("limit") int limit, + @ApiParam( + name = "If-Modified-Since", + value = "Checks if the requested variant was modified, since the specified date-time\n." + + "Provide the value in the following format: EEE, d MMM yyyy HH:mm:ss Z\n." + + "Example: Mon, 05 Jan 2014 15:10:00 +0200") + @HeaderParam("If-Modified-Since") String ifModifiedSince); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.v09.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/DeviceManagementAdminService.java b/components/device-mgt/org.wso2.carbon.device.mgt.v09.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/DeviceManagementAdminService.java index 3a89b9c522..6a9ff80640 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.v09.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/DeviceManagementAdminService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.v09.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/DeviceManagementAdminService.java @@ -33,6 +33,7 @@ import io.swagger.annotations.ResponseHeader; import org.wso2.carbon.apimgt.annotations.api.Scope; import org.wso2.carbon.apimgt.annotations.api.Scopes; import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceList; import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; import org.wso2.carbon.device.mgt.jaxrs.util.Constants; @@ -40,6 +41,7 @@ import javax.validation.constraints.Size; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import java.util.List; @SwaggerDefinition( info = @Info( @@ -168,4 +170,54 @@ public interface DeviceManagementAdminService { required = false, defaultValue = "5") @QueryParam("limit") int limit); + + @PUT + @Path("/device-owner") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "PUT", + value = "Update the device owner", + notes = "Update enrollment owner for given device Identifiers.", + tags = "Device Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:admin:devices:update-enrollment") + }) + } + ) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK. \n Successfully update the owner of devices.", + response = DeviceList.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 was last modified.\n" + + "Used by caches, or in conditional requests."), + }), + @ApiResponse( + code = 400, + message = "The incoming request has more than one selection criteria defined via the query parameters.", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while fetching the device list.", + response = ErrorResponse.class) + }) Response updateEnrollOwner( + @ApiParam( + name = "Device Owner", + value = "The username that is going to use for the new device owner of given devices.", + required = true) + @QueryParam("owner") String owner, + @ApiParam( + name = "Device Identifiers", + value = "List of device identifiers.", + required = true) + List deviceIdentifiers); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.v09.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.v09.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java index adc7c41cf7..7d2a02fc31 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.v09.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.v09.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java @@ -23,12 +23,16 @@ import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.wst.common.uriresolver.internal.util.URIEncoder; +import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.device.mgt.common.DeviceManagementException; import org.wso2.carbon.device.mgt.common.EnrolmentInfo; import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManagementException; +import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; +import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; import org.wso2.carbon.device.mgt.core.DeviceManagementConstants; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.EmailMetaInfo; +import org.wso2.carbon.device.mgt.jaxrs.beans.ActivityList; import org.wso2.carbon.device.mgt.jaxrs.beans.BasicUserInfo; import org.wso2.carbon.device.mgt.jaxrs.beans.BasicUserInfoList; import org.wso2.carbon.device.mgt.jaxrs.beans.BasicUserInfoWrapper; @@ -67,8 +71,11 @@ import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.security.SecureRandom; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -635,6 +642,94 @@ public class UserManagementServiceImpl implements UserManagementService { return Response.status(Response.Status.OK).entity("Invitation mails have been sent.").build(); } + @GET + @Override + @Path("/device/activities") + public Response getActivities( + @QueryParam("since") String since, + @QueryParam("offset") int offset, + @QueryParam("limit") int limit, + @HeaderParam("If-Modified-Since") String ifModifiedSince) { + long ifModifiedSinceTimestamp; + long sinceTimestamp; + long timestamp = 0; + boolean isIfModifiedSinceSet = false; + String initiatedBy; + if (log.isDebugEnabled()) { + log.debug("getActivities since: " + since + " , offset: " + offset + " ,limit: " + limit + " ," + + "ifModifiedSince: " + ifModifiedSince); + } + RequestValidationUtil.validatePaginationParameters(offset, limit); + if (ifModifiedSince != null && !ifModifiedSince.isEmpty()) { + Date ifSinceDate; + SimpleDateFormat format = new SimpleDateFormat(Constants.DEFAULT_SIMPLE_DATE_FORMAT); + try { + ifSinceDate = format.parse(ifModifiedSince); + } catch (ParseException e) { + return Response.status(400).entity(new ErrorResponse.ErrorResponseBuilder() + .setMessage("Invalid date string is provided in 'If-Modified-Since' header").build()).build(); + } + ifModifiedSinceTimestamp = ifSinceDate.getTime(); + isIfModifiedSinceSet = true; + timestamp = ifModifiedSinceTimestamp / 1000; + } else if (since != null && !since.isEmpty()) { + Date sinceDate; + SimpleDateFormat format = new SimpleDateFormat(Constants.DEFAULT_SIMPLE_DATE_FORMAT); + try { + sinceDate = format.parse(since); + } catch (ParseException e) { + return Response.status(400).entity(new ErrorResponse.ErrorResponseBuilder() + .setMessage("Invalid date string is provided in 'since' filter").build()).build(); + } + sinceTimestamp = sinceDate.getTime(); + timestamp = sinceTimestamp / 1000; + } + + if (timestamp == 0) { + //If timestamp is not sent by the user, a default value is set, that is equal to current time-12 hours. + long time = System.currentTimeMillis() / 1000; + timestamp = time - 42300; + } + if (log.isDebugEnabled()) { + log.debug("getActivities final timestamp " + timestamp); + } + + List activities; + int count; + ActivityList activityList = new ActivityList(); + DeviceManagementProviderService dmService; + + initiatedBy = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + try { + if (log.isDebugEnabled()) { + log.debug("Calling database to get activities."); + } + dmService = DeviceMgtAPIUtils.getDeviceManagementService(); + activities = dmService.getActivitiesUpdatedAfterByUser(timestamp, initiatedBy, limit, offset); + if (log.isDebugEnabled()) { + log.debug("Calling database to get activity count with timestamp and user."); + } + count = dmService.getActivityCountUpdatedAfterByUser(timestamp, initiatedBy); + if (log.isDebugEnabled()) { + log.debug("Activity count: " + count); + } + + activityList.setList(activities); + activityList.setCount(count); + if ((activities == null || activities.isEmpty()) && isIfModifiedSinceSet) { + return Response.notModified().build(); + } + return Response.ok().entity(activityList).build(); + } catch (OperationManagementException e) { + String msg = + "Error Response occurred while fetching the activities updated after given time stamp for the user " + + initiatedBy + "."; + log.error(msg, e); + return Response.serverError().entity(new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()) + .build(); + } + } + private Map buildDefaultUserClaims(String firstName, String lastName, String emailAddress) { Map defaultUserClaims = new HashMap<>(); defaultUserClaims.put(Constants.USER_CLAIM_FIRST_NAME, firstName); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.v09.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/DeviceManagementAdminServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.v09.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/DeviceManagementAdminServiceImpl.java index 609e559784..7227f3cb0c 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.v09.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/DeviceManagementAdminServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.v09.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/DeviceManagementAdminServiceImpl.java @@ -26,7 +26,9 @@ import org.wso2.carbon.context.CarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.DeviceManagementException; +import org.wso2.carbon.device.mgt.common.InvalidDeviceException; import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.UserNotFoundException; import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceList; import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; import org.wso2.carbon.device.mgt.jaxrs.service.api.admin.DeviceManagementAdminService; @@ -88,4 +90,32 @@ public class DeviceManagementAdminServiceImpl implements DeviceManagementAdminSe } } + @PUT + @Override + @Path("/device-owner") + public Response updateEnrollOwner( + @QueryParam("owner") String owner, + List deviceIdentifiers){ + try { + if (DeviceMgtAPIUtils.getDeviceManagementService().updateEnrollment(owner, deviceIdentifiers)){ + String msg = "Device owner is updated successfully."; + return Response.status(Response.Status.OK).entity(msg).build(); + } + String msg = "Device owner updating is failed."; + log.error(msg); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } catch(InvalidDeviceException e){ + String msg = "Invalid device identifiers are found with the request."; + log.error(msg); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + }catch (DeviceManagementException e) { + String msg = "Error occurred when updating the device owner."; + log.error(msg); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } catch (UserNotFoundException e) { + String msg = "Couldn't found the owner in user store to update the owner of devices."; + log.error(msg); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.v09.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/Constants.java b/components/device-mgt/org.wso2.carbon.device.mgt.v09.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/Constants.java index 31a83cf03d..dd942c2aae 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.v09.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/Constants.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.v09.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/Constants.java @@ -30,6 +30,7 @@ public class Constants { public static final String DEFAULT_STREAM_VERSION = "1.0.0"; public static final String SCOPE = "scope"; public static final String JDBC_USERSTOREMANAGER = "org.wso2.carbon.user.core.jdbc.JDBCUserStoreManager"; + public static final String DEFAULT_SIMPLE_DATE_FORMAT = "EEE, d MMM yyyy HH:mm:ss Z"; public static final int DEFAULT_PAGE_LIMIT = 50;