Add an API to update the device owner for given device identifiers.

Further, add an API to get device activities without passing the username. Username is retrieved from the carbon context.
4.x.x
lasanthaDLPDS 6 years ago
parent 65eb70139b
commit cc989148d6

@ -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("/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);
}

@ -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<String> deviceIdentifiers);
}

@ -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("/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("EEE, d MMM yyyy HH:mm:ss Z");
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("EEE, d MMM yyyy HH:mm:ss Z");
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<Activity> 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();
}
}

@ -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<String> 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();
}
}
}

@ -0,0 +1,45 @@
package org.wso2.carbon.device.mgt.common;
/*
* Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. 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);
}
}

@ -426,5 +426,16 @@ public interface DeviceDAO {
*/
List<GeoCluster> 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<Device> getDevicesByIdentifiers(List<String> deviceIdentifiers, int tenantId) throws DeviceManagementDAOException;
}

@ -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<EnrolmentInfo> 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<Device> devices, String owner, int tenantId)
throws DeviceManagementDAOException;
}

@ -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<Device> getDevicesByIdentifiers(List<String> deviceIdentifiers, int tenantId)
throws DeviceManagementDAOException {
try {
Connection conn = this.getConnection();
int index = 1;
int counter = 0;
List<Device> 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);
}
}
}

@ -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<Device> 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();
}

@ -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<String> getDeviceIdentifiersByStatus(String deviceType, String deviceStatus) throws DeviceManagementException;
boolean bulkUpdateDeviceStatus(String deviceType, List<String> deviceList, String status) throws DeviceManagementException;
boolean updateEnrollment(String owner, List<String> deviceIdentifiers)
throws DeviceManagementException, UserNotFoundException, InvalidDeviceException;
}

@ -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<String> deviceIdentifiers)
throws DeviceManagementException, UserNotFoundException, InvalidDeviceException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
List<Device> 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<Device.Property> properties = device.getProperties();
if (properties != null) {

@ -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("/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);
}

@ -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<String> deviceIdentifiers);
}

@ -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("/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("EEE, d MMM yyyy HH:mm:ss Z");
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("EEE, d MMM yyyy HH:mm:ss Z");
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<Activity> 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<String, String> buildDefaultUserClaims(String firstName, String lastName, String emailAddress) {
Map<String, String> defaultUserClaims = new HashMap<>();
defaultUserClaims.put(Constants.USER_CLAIM_FIRST_NAME, firstName);

@ -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<String> 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();
}
}
}

Loading…
Cancel
Save