revert-70aa11f8
kamidu 8 years ago
commit 77a8fed7de

@ -41,16 +41,13 @@ import java.util.List;
public class Profiles { public class Profiles {
@XmlElement(name = "Profile") @XmlElement(name = "Profile")
protected List<String> profile; protected List<String> profile = new ArrayList<String>();;
/** /**
* Gets the value of the profile property. * Gets the value of the profile property.
* *
*/ */
public List<String> getProfile() { public List<String> getProfile() {
if (profile == null) {
profile = new ArrayList<String>();
}
return this.profile; return this.profile;
} }

@ -30,8 +30,8 @@ public class RoleInfo {
@ApiModelProperty(name = "roleName", value = "The name of the role.", required = true) @ApiModelProperty(name = "roleName", value = "The name of the role.", required = true)
private String roleName; private String roleName;
@ApiModelProperty(name = "scopes", value = "Lists out all the scopes associated with roles.", @ApiModelProperty(name = "scopes", value = "Lists out all the scopes associated with roles.",
required = true, dataType = "List[org.wso2.carbon.device.mgt.jaxrs.beans.Scope]") required = true, dataType = "List[java.lang.String]")
private List<Scope> scopes; private List<String> scopes;
@ApiModelProperty(name = "users", value = "The list of users assigned to the selected role.", @ApiModelProperty(name = "users", value = "The list of users assigned to the selected role.",
required = true, dataType = "List[java.lang.String]") required = true, dataType = "List[java.lang.String]")
private String[] users; private String[] users;
@ -44,11 +44,11 @@ public class RoleInfo {
this.roleName = roleName; this.roleName = roleName;
} }
public List<Scope> getScopes() { public List<String> getScopes() {
return scopes; return scopes;
} }
public void setScopes(List<Scope> scopes) { public void setScopes(List<String> scopes) {
this.scopes = scopes; this.scopes = scopes;
} }

@ -166,55 +166,6 @@ public interface RoleManagementService {
required = false) required = false)
@HeaderParam("If-Modified-Since") String ifModifiedSince); @HeaderParam("If-Modified-Since") String ifModifiedSince);
@PUT
@Path("/scopes")
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "PUT",
value = "Updating authorization scopes.",
notes = "This REST API can be used to update the associated roles of the scopes",
tags = "Role Management"
)
@ApiResponses(value = {
@ApiResponse(
code = 200,
message = "OK. \n Scopes has been updated successfully",
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "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 = 400,
message = "Bad Request. \n Invalid request or validation error.",
response = ErrorResponse.class),
@ApiResponse(
code = 404,
message = "Not Found. \n Scopes to be updated does not exist.",
response = ErrorResponse.class),
@ApiResponse(
code = 415,
message = "Unsupported media type. \n The entity of the request was in a not supported format.",
response = ErrorResponse.class),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Server error occurred while updating the scopes.",
response = ErrorResponse.class)
})
@org.wso2.carbon.apimgt.annotations.api.Scope(key = "role:manage", name = "Add roles", description = "")
Response updateScopes(
@ApiParam(
name = "Scopes",
value = "List of scopes to be updated",
required = true) List<Scope> scopes);
@GET @GET
@Path("/{roleName}") @Path("/{roleName}")
@ApiOperation( @ApiOperation(
@ -418,11 +369,7 @@ public interface RoleManagementService {
name = "roleName", name = "roleName",
value = "Name of the role to de deleted.", value = "Name of the role to de deleted.",
required = true) required = true)
@PathParam("roleName") String roleName, @PathParam("roleName") String roleName);
@ApiParam(
name = "role",
value = "Details about the role to be added.",
required = true) RoleInfo role);
@PUT @PUT
@Path("/{roleName}/users") @Path("/{roleName}/users")

@ -112,27 +112,6 @@ public class RoleManagementServiceImpl implements RoleManagementService {
} }
} }
@PUT
@Path("/scopes")
@Override
public Response updateScopes(List<Scope> scopes) {
RequestValidationUtil.validateScopes(scopes);
try {
ScopeManagementService scopeManagementService = DeviceMgtAPIUtils.getScopeManagementService();
if (scopeManagementService == null) {
log.error("Scope management service initialization is failed, hence scopes will not be retrieved");
} else {
scopeManagementService.updateScopes(DeviceMgtUtil.convertScopestoAPIScopes(scopes));
}
return Response.status(Response.Status.OK).entity("Scopes has been successfully updated").build();
} catch (ScopeManagementException e) {
String msg = "Error occurred while updating the scopes";
log.error(msg, e);
return Response.serverError().entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
}
}
@GET @GET
@Path("/{roleName}") @Path("/{roleName}")
@Override @Override
@ -143,6 +122,7 @@ public class RoleManagementServiceImpl implements RoleManagementService {
} }
RequestValidationUtil.validateRoleName(roleName); RequestValidationUtil.validateRoleName(roleName);
RoleInfo roleInfo = new RoleInfo(); RoleInfo roleInfo = new RoleInfo();
List<String> scopes = new ArrayList<>();
try { try {
final UserStoreManager userStoreManager = DeviceMgtAPIUtils.getUserStoreManager(); final UserStoreManager userStoreManager = DeviceMgtAPIUtils.getUserStoreManager();
if (!userStoreManager.isExistingRole(roleName)) { if (!userStoreManager.isExistingRole(roleName)) {
@ -150,15 +130,26 @@ public class RoleManagementServiceImpl implements RoleManagementService {
new ErrorResponse.ErrorResponseBuilder().setMessage("No role exists with the name '" + new ErrorResponse.ErrorResponseBuilder().setMessage("No role exists with the name '" +
roleName + "'").build()).build(); roleName + "'").build()).build();
} }
ScopeManagementService scopeManagementService = DeviceMgtAPIUtils.getScopeManagementService();
if (scopeManagementService == null) {
log.error("Scope management service initialization is failed, hence scopes will not be retrieved");
} else {
scopes = DeviceMgtUtil.convertAPIScopesToScopeKeys(scopeManagementService.getScopesOfRole(roleName));
}
roleInfo.setRoleName(roleName); roleInfo.setRoleName(roleName);
roleInfo.setUsers(userStoreManager.getUserListOfRole(roleName)); roleInfo.setUsers(userStoreManager.getUserListOfRole(roleName));
roleInfo.setScopes(scopes);
return Response.status(Response.Status.OK).entity(roleInfo).build(); return Response.status(Response.Status.OK).entity(roleInfo).build();
} catch (UserStoreException e) { } catch (UserStoreException e) {
String msg = "Error occurred while retrieving the user role '" + roleName + "'"; String msg = "Error occurred while retrieving the user role '" + roleName + "'";
log.error(msg, e); log.error(msg, e);
return Response.serverError().entity( return Response.serverError().entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
} catch (ScopeManagementException e) {
String msg = "Error occurred while retrieving the scopes";
log.error(msg, e);
return Response.serverError().entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
} }
} }
@ -234,7 +225,7 @@ public class RoleManagementServiceImpl implements RoleManagementService {
if (scopeManagementService == null) { if (scopeManagementService == null) {
log.error("Scope management service initialization is failed, hence scopes will not be updated"); log.error("Scope management service initialization is failed, hence scopes will not be updated");
} else { } else {
scopeManagementService.updateScopes(DeviceMgtUtil.convertScopestoAPIScopes(roleInfo.getScopes())); scopeManagementService.updateScopes(roleInfo.getScopes(), roleName);
} }
} }
//TODO: Need to send the updated role information in the entity back to the client //TODO: Need to send the updated role information in the entity back to the client
@ -256,9 +247,8 @@ public class RoleManagementServiceImpl implements RoleManagementService {
@DELETE @DELETE
@Path("/{roleName}") @Path("/{roleName}")
@Override @Override
public Response deleteRole(@PathParam("roleName") String roleName, RoleInfo roleInfo) { public Response deleteRole(@PathParam("roleName") String roleName) {
RequestValidationUtil.validateRoleName(roleName); RequestValidationUtil.validateRoleName(roleName);
RequestValidationUtil.validateScopes(roleInfo.getScopes());
try { try {
final UserRealm userRealm = DeviceMgtAPIUtils.getUserRealm(); final UserRealm userRealm = DeviceMgtAPIUtils.getUserRealm();
@ -277,22 +267,23 @@ public class RoleManagementServiceImpl implements RoleManagementService {
// Delete all authorizations for the current role before deleting // Delete all authorizations for the current role before deleting
authorizationManager.clearRoleAuthorization(roleName); authorizationManager.clearRoleAuthorization(roleName);
//updating scopes //removing scopes
ScopeManagementService scopeManagementService = DeviceMgtAPIUtils.getScopeManagementService(); ScopeManagementService scopeManagementService = DeviceMgtAPIUtils.getScopeManagementService();
if (scopeManagementService == null) { if (scopeManagementService == null) {
log.error("Scope management service initialization is failed, hence scopes will not be updated"); log.error("Scope management service initialization is failed, hence scopes will not be updated");
} else { } else {
scopeManagementService.updateScopes(DeviceMgtUtil.convertScopestoAPIScopes(roleInfo.getScopes())); scopeManagementService.removeScopes(roleName);
} }
return Response.status(Response.Status.OK).build(); return Response.status(Response.Status.OK).entity("Role '" + roleName + "' has " +
"successfully been deleted").build();
} catch (UserStoreException e) { } catch (UserStoreException e) {
String msg = "Error occurred while deleting the role '" + roleName + "'"; String msg = "Error occurred while deleting the role '" + roleName + "'";
log.error(msg, e); log.error(msg, e);
return Response.serverError().entity( return Response.serverError().entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
} catch (ScopeManagementException e) { } catch (ScopeManagementException e) {
String msg = "Error occurred while updating scopes of role '" + roleName + "'"; String msg = "Error occurred while deleting scopes of role '" + roleName + "'";
log.error(msg, e); log.error(msg, e);
return Response.serverError().entity( return Response.serverError().entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();

@ -65,15 +65,13 @@ public class DeviceMgtUtil {
} }
public static List<Scope> convertScopestoAPIScopes(List<org.wso2.carbon.device.mgt.jaxrs.beans.Scope> scopes) { public static List<Scope> convertScopesListToAPIScopes(List<String> scopes, String roleName) {
List<Scope> convertedScopes = new ArrayList<>(); List<Scope> convertedScopes = new ArrayList<>();
Scope convertedScope; Scope convertedScope;
for (org.wso2.carbon.device.mgt.jaxrs.beans.Scope scope : scopes) { for (String scope : scopes) {
convertedScope = new Scope(); convertedScope = new Scope();
convertedScope.setKey(scope.getKey()); convertedScope.setKey(scope);
convertedScope.setName(scope.getName()); convertedScope.setRoles(roleName);
convertedScope.setDescription(scope.getDescription());
convertedScope.setRoles(scope.getRoles());
convertedScopes.add(convertedScope); convertedScopes.add(convertedScope);
} }
return convertedScopes; return convertedScopes;
@ -87,12 +85,18 @@ public class DeviceMgtUtil {
convertedScope.setKey(scope.getKey()); convertedScope.setKey(scope.getKey());
convertedScope.setName(scope.getName()); convertedScope.setName(scope.getName());
convertedScope.setDescription(scope.getDescription()); convertedScope.setDescription(scope.getDescription());
convertedScope.setRoles(scope.getRoles());
convertedScopes.add(convertedScope); convertedScopes.add(convertedScope);
} }
return convertedScopes; return convertedScopes;
} }
public static List<String> convertAPIScopesToScopeKeys(List<Scope> scopes) {
List<String> convertedScopes = new ArrayList<>();
for (Scope scope : scopes) {
convertedScopes.add(scope.getKey());
}
return convertedScopes;
}
/** /**
* Returns a new BadRequestException * Returns a new BadRequestException
* *

@ -34,6 +34,15 @@ public interface ScopeManagementService {
*/ */
void updateScopes(List<Scope> scopes) throws ScopeManagementException; void updateScopes(List<Scope> scopes) throws ScopeManagementException;
/**
* This method is used to update the given list of scopes keys with the role name.
*
* @param scopeKeys List of scopes to be updated.
* @param roleName Role name
* @throws ScopeManagementException
*/
void updateScopes(List<String> scopeKeys, String roleName) throws ScopeManagementException;
/** /**
* This method is used to retrieve all the scopes. * This method is used to retrieve all the scopes.
* *
@ -50,4 +59,20 @@ public interface ScopeManagementService {
*/ */
String getRolesOfScope(String scopeKey) throws ScopeManagementException; String getRolesOfScope(String scopeKey) throws ScopeManagementException;
/**
* This method is to retrieve the scopes of the given role
* @param roleName key of the scope
* @return List of scopes
* @throws ScopeManagementException
*/
List<Scope> getScopesOfRole(String roleName) throws ScopeManagementException;
/**
* This method is used to remove the scopes of a given user role.
*
* @param roleName Role name
* @throws ScopeManagementException
*/
void removeScopes(String roleName) throws ScopeManagementException;
} }

@ -32,6 +32,8 @@ import org.wso2.carbon.device.mgt.common.push.notification.NotificationContext;
import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy; import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy;
import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationExecutionFailedException; import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationExecutionFailedException;
import org.wso2.carbon.device.mgt.core.DeviceManagementConstants; import org.wso2.carbon.device.mgt.core.DeviceManagementConstants;
import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager;
import org.wso2.carbon.device.mgt.core.config.task.TaskConfiguration;
import org.wso2.carbon.device.mgt.core.dao.DeviceDAO; import org.wso2.carbon.device.mgt.core.dao.DeviceDAO;
import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException;
import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory;
@ -106,16 +108,34 @@ public class OperationManagerImpl implements OperationManager {
org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation operationDto = org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation operationDto =
OperationDAOUtil.convertOperation(operation); OperationDAOUtil.convertOperation(operation);
int operationId = this.lookupOperationDAO(operation).addOperation(operationDto); int operationId = this.lookupOperationDAO(operation).addOperation(operationDto);
boolean isScheduledOperation = this.isTaskScheduledOperation(operation);
boolean isNotRepeated = false;
boolean hasExistingTaskOperation;
int enrolmentId;
if (operationDto.getControl() ==
org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Control.NO_REPEAT) {
isNotRepeated = true;
}
//TODO have to create a sql to load device details from deviceDAO using single query. //TODO have to create a sql to load device details from deviceDAO using single query.
String operationCode = operationDto.getCode();
for (DeviceIdentifier deviceId : deviceIds) { for (DeviceIdentifier deviceId : deviceIds) {
Device device = getDevice(deviceId); Device device = getDevice(deviceId);
if (operationDto.getControl() == enrolmentId = device.getEnrolmentInfo().getId();
org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Control.NO_REPEAT) { //Do not repeat the task operations
operationDAO.updateEnrollmentOperationsStatus(device.getEnrolmentInfo().getId(), operationDto.getCode(), if (isScheduledOperation) {
hasExistingTaskOperation = operationDAO.updateTaskOperation(enrolmentId, operationCode);
if (!hasExistingTaskOperation) {
operationMappingDAO.addOperationMapping(operationId, enrolmentId);
}
} else if (isNotRepeated) {
operationDAO.updateEnrollmentOperationsStatus(enrolmentId, operationCode,
org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Status.PENDING, org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Status.PENDING,
org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Status.REPEATED); org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Status.REPEATED);
operationMappingDAO.addOperationMapping(operationId, enrolmentId);
} else {
operationMappingDAO.addOperationMapping(operationId, enrolmentId);
} }
operationMappingDAO.addOperationMapping(operationId, device.getEnrolmentInfo().getId());
if (notificationStrategy != null) { if (notificationStrategy != null) {
try { try {
notificationStrategy.execute(new NotificationContext(deviceId, operation)); notificationStrategy.execute(new NotificationContext(deviceId, operation));
@ -129,7 +149,7 @@ public class OperationManagerImpl implements OperationManager {
OperationManagementDAOFactory.commitTransaction(); OperationManagementDAOFactory.commitTransaction();
Activity activity = new Activity(); Activity activity = new Activity();
activity.setActivityId(DeviceManagementConstants.OperationAttributes.ACTIVITY + operationId); activity.setActivityId(DeviceManagementConstants.OperationAttributes.ACTIVITY + operationId);
activity.setCode(operationDto.getCode()); activity.setCode(operationCode);
activity.setCreatedTimeStamp(new Date().toString()); activity.setCreatedTimeStamp(new Date().toString());
activity.setType(Activity.Type.valueOf(operationDto.getType().toString())); activity.setType(Activity.Type.valueOf(operationDto.getType().toString()));
return activity; return activity;
@ -788,4 +808,15 @@ public class OperationManagerImpl implements OperationManager {
return enrolmentId; return enrolmentId;
} }
private boolean isTaskScheduledOperation(Operation operation) {
TaskConfiguration taskConfiguration = DeviceConfigurationManager.getInstance().getDeviceManagementConfig().
getTaskConfiguration();
for (TaskConfiguration.Operation op:taskConfiguration.getOperations()) {
if (operation.getCode().equals(op.getOperationName())) {
return true;
}
}
return false;
}
} }

@ -60,6 +60,8 @@ public interface OperationDAO {
void updateEnrollmentOperationsStatus(int enrolmentId, String operationCode, Operation.Status existingStatus, void updateEnrollmentOperationsStatus(int enrolmentId, String operationCode, Operation.Status existingStatus,
Operation.Status newStatus) throws OperationManagementDAOException; Operation.Status newStatus) throws OperationManagementDAOException;
boolean updateTaskOperation(int enrolmentId, String operationCode) throws OperationManagementDAOException;
void addOperationResponse(int enrolmentId, int operationId, Object operationResponse) void addOperationResponse(int enrolmentId, int operationId, Object operationResponse)
throws OperationManagementDAOException; throws OperationManagementDAOException;

@ -153,6 +153,44 @@ public class GenericOperationDAOImpl implements OperationDAO {
} }
} }
@Override
public boolean updateTaskOperation(int enrolmentId, String operationCode)
throws OperationManagementDAOException {
PreparedStatement stmt = null;
ResultSet rs = null;
boolean result = false;
try {
Connection connection = OperationManagementDAOFactory.getConnection();
String query = "SELECT EOM.ID FROM DM_ENROLMENT_OP_MAPPING AS EOM INNER JOIN DM_OPERATION DM " +
"ON DM.ID = EOM.OPERATION_ID WHERE EOM.ENROLMENT_ID = ? AND DM.OPERATION_CODE = ? AND " +
"EOM.STATUS = ?;";
stmt = connection.prepareStatement(query);
stmt.setInt(1, enrolmentId);
stmt.setString(2, operationCode);
stmt.setString(3, Operation.Status.PENDING.toString());
// This will return only one result always.
rs = stmt.executeQuery();
int id = 0;
if (rs.next()) {
id = rs.getInt("ID");
}
if (id != 0) {
stmt = connection.prepareStatement("UPDATE DM_ENROLMENT_OP_MAPPING SET UPDATED_TIMESTAMP = ? " +
"WHERE ID = ?");
stmt.setLong(1, System.currentTimeMillis() / 1000);
stmt.setInt(2, id);
stmt.executeUpdate();
result = true;
}
} catch (SQLException e) {
throw new OperationManagementDAOException("Error occurred while update device mapping operation status " +
"metadata", e);
} finally {
OperationManagementDAOUtil.cleanupResources(stmt);
}
return result;
}
@Override @Override
public void addOperationResponse(int enrolmentId, int operationId, Object operationResponse) public void addOperationResponse(int enrolmentId, int operationId, Object operationResponse)
throws OperationManagementDAOException { throws OperationManagementDAOException {

@ -18,6 +18,7 @@
package org.wso2.carbon.device.mgt.core.scope.mgt; package org.wso2.carbon.device.mgt.core.scope.mgt;
import org.apache.commons.lang.StringUtils;
import org.wso2.carbon.apimgt.api.model.Scope; import org.wso2.carbon.apimgt.api.model.Scope;
import org.wso2.carbon.device.mgt.common.TransactionManagementException; import org.wso2.carbon.device.mgt.common.TransactionManagementException;
import org.wso2.carbon.device.mgt.common.scope.mgt.ScopeManagementException; import org.wso2.carbon.device.mgt.common.scope.mgt.ScopeManagementException;
@ -59,6 +60,33 @@ public class ScopeManagementServiceImpl implements ScopeManagementService {
} }
} }
@Override
public void updateScopes(List<String> scopeKeys, String roleName) throws ScopeManagementException {
List<Scope> scopes = new ArrayList<>();
try {
List<Scope> allScopes = this.getAllScopes();
for (Scope scope : allScopes) {
for (String key : scopeKeys) {
if (scope.getKey().equals(key)) {
scope.setRoles(scope.getRoles() + "," + roleName);
scopes.add(scope);
}
}
}
ScopeManagementDAOFactory.beginTransaction();
scopeManagementDAO.updateScopes(scopes);
ScopeManagementDAOFactory.commitTransaction();
} catch (TransactionManagementException e) {
ScopeManagementDAOFactory.rollbackTransaction();
throw new ScopeManagementException("Transactional error occurred while adding the scopes.", e);
} catch (ScopeManagementDAOException e) {
ScopeManagementDAOFactory.rollbackTransaction();
throw new ScopeManagementException("Error occurred while adding the scopes to database.", e);
} finally {
ScopeManagementDAOFactory.closeConnection();
}
}
@Override @Override
public List<Scope> getAllScopes() throws ScopeManagementException { public List<Scope> getAllScopes() throws ScopeManagementException {
List<Scope> scopes = new ArrayList<>(); List<Scope> scopes = new ArrayList<>();
@ -94,4 +122,52 @@ public class ScopeManagementServiceImpl implements ScopeManagementService {
return roles; return roles;
} }
@Override
public List<Scope> getScopesOfRole(String roleName) throws ScopeManagementException {
if (roleName == null || roleName.isEmpty()) {
throw new ScopeManagementException("Role name is null or empty");
}
List<Scope> filteredScopes = new ArrayList<>();
try {
ScopeManagementDAOFactory.openConnection();
List<Scope> allScopes = scopeManagementDAO.getScopesHavingRole(roleName);
String roles[];
for (Scope scope : allScopes) {
roles = scope.getRoles().split(",");
for (String role : roles) {
if (roleName.equals(role.trim())) {
filteredScopes.add(scope);
}
}
}
} catch (SQLException e) {
throw new ScopeManagementException("SQL error occurred while retrieving scopes of role from database.", e);
} catch (ScopeManagementDAOException e) {
throw new ScopeManagementException("Error occurred while retrieving scopes of role from database.", e);
} finally {
ScopeManagementDAOFactory.closeConnection();
}
return filteredScopes;
}
@Override
public void removeScopes(String roleName) throws ScopeManagementException {
List<Scope> scopes = this.getScopesOfRole(roleName);
String roles[];
ArrayList<String> filteredRoles = new ArrayList<>();
for (Scope scope : scopes) {
roles = scope.getRoles().split(",");
for (String role : roles) {
if (!roleName.equals(role.trim())) {
filteredRoles.add(role);
}
}
scope.setRoles(StringUtils.join(filteredRoles, ","));
filteredRoles.clear();
}
this.updateScopes(scopes);
}
} }

@ -51,4 +51,14 @@ public interface ScopeManagementDAO {
*/ */
String getRolesOfScope(String scopeKey) throws ScopeManagementDAOException; String getRolesOfScope(String scopeKey) throws ScopeManagementDAOException;
/**
* This method is to retrieve all the scopes of the given role name.
* Thus it returns the scopes even if the part of the given name is matched.
*
* @param roleName Role name
* @return List of scopes
* @throws ScopeManagementDAOException
*/
List<Scope> getScopesHavingRole(String roleName) throws ScopeManagementDAOException;
} }

@ -64,23 +64,14 @@ public class ScopeManagementDAOImpl implements ScopeManagementDAO {
Connection conn; Connection conn;
PreparedStatement stmt = null; PreparedStatement stmt = null;
ResultSet rs = null; ResultSet rs = null;
List<Scope> scopes = new ArrayList<>(); List<Scope> scopes;
Scope scope;
try { try {
conn = this.getConnection(); conn = this.getConnection();
String sql = "SELECT * FROM IDN_OAUTH2_SCOPE"; String sql = "SELECT * FROM IDN_OAUTH2_SCOPE";
stmt = conn.prepareStatement(sql); stmt = conn.prepareStatement(sql);
rs = stmt.executeQuery(); rs = stmt.executeQuery();
scopes = this.getScopesFromResultSet(rs);
while (rs.next()) {
scope = new Scope();
scope.setKey(rs.getString("SCOPE_KEY"));
scope.setName(rs.getString("NAME"));
scope.setDescription(rs.getString("DESCRIPTION"));
scope.setRoles(rs.getString("ROLES"));
scopes.add(scope);
}
return scopes; return scopes;
} catch (SQLException e) { } catch (SQLException e) {
throw new ScopeManagementDAOException("Error occurred while fetching the details of the scopes.", e); throw new ScopeManagementDAOException("Error occurred while fetching the details of the scopes.", e);
@ -114,8 +105,44 @@ public class ScopeManagementDAOImpl implements ScopeManagementDAO {
} }
} }
@Override
public List<Scope> getScopesHavingRole(String roleName) throws ScopeManagementDAOException {
Connection conn;
PreparedStatement stmt = null;
ResultSet rs = null;
List<Scope> scopes;
try {
conn = this.getConnection();
String sql = "SELECT * FROM IDN_OAUTH2_SCOPE WHERE ROLES LIKE ?";
stmt = conn.prepareStatement(sql);
stmt.setString(1, "%" + roleName + "%");
rs = stmt.executeQuery();
scopes = this.getScopesFromResultSet(rs);
return scopes;
} catch (SQLException e) {
throw new ScopeManagementDAOException("Error occurred while fetching the details of the scopes.", e);
} finally {
ScopeManagementDAOUtil.cleanupResources(stmt, rs);
}
}
private Connection getConnection() throws SQLException { private Connection getConnection() throws SQLException {
return ScopeManagementDAOFactory.getConnection(); return ScopeManagementDAOFactory.getConnection();
} }
private List<Scope> getScopesFromResultSet(ResultSet rs) throws SQLException {
List<Scope> scopes = new ArrayList<>();
Scope scope;
while (rs.next()) {
scope = new Scope();
scope.setKey(rs.getString("SCOPE_KEY"));
scope.setName(rs.getString("NAME"));
scope.setDescription(rs.getString("DESCRIPTION"));
scope.setRoles(rs.getString("ROLES"));
scopes.add(scope);
}
return scopes;
}
} }

@ -47,7 +47,7 @@
<div id="role-create-error-msg" class="alert alert-danger hidden" role="alert"> <div id="role-create-error-msg" class="alert alert-danger hidden" role="alert">
<i class="icon fw fw-error"></i><span></span> <i class="icon fw fw-error"></i><span></span>
</div> </div>
<label class="wr-input-label">Domain *</label> <label class="wr-input-label">User Store Domain</label>
<div class="wr-input-control"> <div class="wr-input-control">
<select id="domain" class="form-control select"> <select id="domain" class="form-control select">
@ -106,6 +106,7 @@
</div> </div>
</div> </div>
<!-- /content --> <!-- /content -->
<div id="app-context" data-app-context="{{@app.context}}" class="hidden"></div>
</div> </div>
</div> </div>
<!-- /content/body --> <!-- /content/body -->

@ -31,6 +31,8 @@ function inputIsValid(regExp, inputString) {
var validateInline = {}; var validateInline = {};
var clearInline = {}; var clearInline = {};
var apiBasePath = "/api/device-mgt/v1.0";
var enableInlineError = function (inputField, errorMsg, errorSign) { var enableInlineError = function (inputField, errorMsg, errorSign) {
var fieldIdentifier = "#" + inputField; var fieldIdentifier = "#" + inputField;
var errorMsgIdentifier = "#" + inputField + " ." + errorMsg; var errorMsgIdentifier = "#" + inputField + " ." + errorMsg;
@ -113,12 +115,12 @@ function formatRepoSelection (user) {
} }
$(document).ready(function () { $(document).ready(function () {
var appContext = $("#app-context").data("app-context");
$("#users").select2({ $("#users").select2({
multiple:true, multiple:true,
tags: false, tags: false,
ajax: { ajax: {
url: window.location.origin + "/devicemgt/api/invoker/execute/", url: appContext + "/api/invoker/execute/",
method: "POST", method: "POST",
dataType: 'json', dataType: 'json',
delay: 250, delay: 250,
@ -128,15 +130,17 @@ $(document).ready(function () {
data: function (params) { data: function (params) {
var postData = {}; var postData = {};
postData.actionMethod = "GET"; postData.actionMethod = "GET";
postData.actionUrl = "/devicemgt_admin/users/view-users?username=" + params.term; postData.actionUrl = apiBasePath + "/users/search/usernames?filter=" + params.term;
postData.actionPayload = null; postData.actionPayload = null;
return JSON.stringify(postData); return JSON.stringify(postData);
}, },
processResults: function (data, page) { processResults: function (data, page) {
var newData = []; var newData = [];
$.each(data.responseContent, function (index, value) { $.each(data, function (index, value) {
value.id = value.username; var user = {};
newData.push(value); user.username = value.username;
user.id = value.username;
newData.push(user);
}); });
return { return {
results: newData results: newData
@ -153,7 +157,7 @@ $(document).ready(function () {
/** /**
* Following click function would execute * Following click function would execute
* when a user clicks on "Add Role" button * when a user clicks on "Add Role" button
* on Add Role page in WSO2 Devicemgt Console. * on Add Role page in WSO2 MDM Console.
*/ */
$("button#add-role-btn").click(function() { $("button#add-role-btn").click(function() {
var rolenameInput = $("input#rolename"); var rolenameInput = $("input#rolename");
@ -188,7 +192,7 @@ $(document).ready(function () {
} }
addRoleFormData.users = users; addRoleFormData.users = users;
var addRoleAPI = "/devicemgt_admin/roles"; var addRoleAPI = apiBasePath + "/roles";
invokerUtil.post( invokerUtil.post(
addRoleAPI, addRoleAPI,
@ -205,10 +209,10 @@ $(document).ready(function () {
//// Refreshing with success message //// Refreshing with success message
//$("#role-create-form").addClass("hidden"); //$("#role-create-form").addClass("hidden");
//$("#role-created-msg").removeClass("hidden"); //$("#role-created-msg").removeClass("hidden");
window.location.href = '/devicemgt/role/edit-permission/' + roleName + '?wizard=true'; window.location.href = appContext + '/role/edit-permission/' + roleName;
} }
}, function (data) { }, function (data) {
if (JSON.parse(data.responseText).errorMessage.indexOf("RoleExisting") > -1) { if (JSON.parse(data).errorMessage.indexOf("RoleExisting") > -1) {
$(errorMsg).text("Role name : " + roleName + " already exists. Pick another role name."); $(errorMsg).text("Role name : " + roleName + " already exists. Pick another role name.");
} else { } else {
$(errorMsg).text(JSON.parse(data.responseText).errorMessage); $(errorMsg).text(JSON.parse(data.responseText).errorMessage);

@ -78,6 +78,20 @@
</a> </a>
</div> </div>
</div> </div>
<div id="child-deselect-error-content" class="hide">
<div class="content">
<div class="row">
<div class="col-lg-5 col-md-6 col-centered">
<h3>Can't deselect child permissions when parent permission is selected.</h3>
<div class="buttons">
<a href="#" id="child-deselect-error-link" class="btn-operations">
Ok
</a>
</div>
</div>
</div>
</div>
</div>
<!-- /content --> <!-- /content -->
</div> </div>
</div> </div>

@ -26,7 +26,7 @@ function onRequest(context) {
var userModule = require("/app/modules/business-controllers/user.js")["userModule"]; var userModule = require("/app/modules/business-controllers/user.js")["userModule"];
var uri = request.getRequestURI(); var uri = request.getRequestURI();
var uriMatcher = new URIMatcher(String(uri)); var uriMatcher = new URIMatcher(String(uri));
var isMatched = uriMatcher.match("/{context}/roles/edit-role-permission/{rolename}"); var isMatched = uriMatcher.match("/{context}/role/edit-permission/{rolename}");
if (isMatched) { if (isMatched) {
var matchedElements = uriMatcher.elements(); var matchedElements = uriMatcher.elements();

@ -31,6 +31,8 @@
var modalPopup = ".wr-modalpopup"; var modalPopup = ".wr-modalpopup";
var modalPopupContent = modalPopup + " .modalpopup-content"; var modalPopupContent = modalPopup + " .modalpopup-content";
var apiBasePath = "/api/device-mgt/v1.0";
/* /*
* hide popup function. * hide popup function.
*/ */
@ -96,13 +98,13 @@ $(document).ready(function () {
var listPartialSrc = $("#list-partial").attr("src"); var listPartialSrc = $("#list-partial").attr("src");
var treeTemplateSrc = $("#tree-template").attr("src"); var treeTemplateSrc = $("#tree-template").attr("src");
var roleName = $("#permissionList").data("currentrole"); var roleName = $("#permissionList").data("currentrole");
var serviceUrl = "/devicemgt_admin/roles/permissions?rolename=" + encodeURIComponent(roleName); var serviceUrl = apiBasePath + "/roles/" +encodeURIComponent(roleName)+"/permissions";
$.registerPartial("list", listPartialSrc, function(){ $.registerPartial("list", listPartialSrc, function(){
$.template("treeTemplate", treeTemplateSrc, function (template) { $.template("treeTemplate", treeTemplateSrc, function (template) {
invokerUtil.get(serviceUrl, invokerUtil.get(serviceUrl,
function(data){ function(data){
data = JSON.parse(data); data = JSON.parse(data);
var treeData = data.responseContent; var treeData = data;
if(treeData.nodeList.length > 0){ if(treeData.nodeList.length > 0){
treeData = { nodeList: treeData.nodeList }; treeData = { nodeList: treeData.nodeList };
var content = template(treeData); var content = template(treeData);
@ -117,8 +119,12 @@ $(document).ready(function () {
$("#permissionList li input").click(function(){ $("#permissionList li input").click(function(){
var parentInput = $(this).parents("ul:eq(1) > li").find('input:eq(0)'); var parentInput = $(this).parents("ul:eq(1) > li").find('input:eq(0)');
if(parentInput && parentInput.is(':checked')){ if(parentInput && parentInput.is(':checked')){
parentInput.prop('checked', false); $(modalPopupContent).html($('#child-deselect-error-content').html());
return true; showPopup();
$("a#child-deselect-error-link").click(function () {
hidePopup();
});
return false;
} }
}); });
$('#permissionList').tree_view(); $('#permissionList').tree_view();
@ -135,24 +141,25 @@ $(document).ready(function () {
*/ */
$("button#update-permissions-btn").click(function() { $("button#update-permissions-btn").click(function() {
var roleName = $("#permissionList").data("currentrole"); var roleName = $("#permissionList").data("currentrole");
var updateRolePermissionAPI = "/devicemgt_admin/roles?rolename=" + roleName; var updateRolePermissionAPI = apiBasePath + "/roles/" + roleName;
var updateRolePermissionData = {}; var updateRolePermissionData = {};
var perms = []; var perms = [];
$("#permissionList li input:checked").each(function(){ $("#permissionList li input:checked").each(function(){
perms.push($(this).data("resourcepath")); perms.push($(this).data("resourcepath"));
}); })
updateRolePermissionData.permissions = perms; updateRolePermissionData.permissions = perms;
invokerUtil.put( invokerUtil.put(
updateRolePermissionAPI, updateRolePermissionAPI,
updateRolePermissionData, updateRolePermissionData,
function (jqXHR) { function (data, textStatus, jqXHR) {
if (JSON.parse(jqXHR).status == 200 || jqXHR.status == 200) { if (jqXHR.status == 200) {
// Refreshing with success message // Refreshing with success message
$("#role-create-form").addClass("hidden"); $("#role-create-form").addClass("hidden");
$("#role-created-msg").removeClass("hidden"); $("#role-created-msg").removeClass("hidden");
} }
}, function (data) { }, function (data) {
$(errorMsg).text(JSON.parse(data.responseText).errorMessage); var payload = JSON.parse(data.responseText);
$(errorMsg).text(payload.message);
$(errorMsgWrapper).removeClass("hidden"); $(errorMsgWrapper).removeClass("hidden");
} }
); );

@ -29,7 +29,7 @@
<div id="role-create-error-msg" class="alert alert-danger hidden" role="alert"> <div id="role-create-error-msg" class="alert alert-danger hidden" role="alert">
<i class="icon fw fw-error"></i><span></span> <i class="icon fw fw-error"></i><span></span>
</div> </div>
<label class="wr-input-label">Domain *</label> <label class="wr-input-label">Domain</label>
<div class="wr-input-control"> <div class="wr-input-control">
<select id="domain" class="form-control select"> <select id="domain" class="form-control select">
<option>PRIMARY</option> <option>PRIMARY</option>
@ -81,6 +81,7 @@
</div> </div>
</div> </div>
<!-- /content --> <!-- /content -->
<div id="app-context" data-app-context="{{@app.context}}" class="hidden"></div>
</div> </div>
</div> </div>
<!-- /content/body --> <!-- /content/body -->

@ -1,21 +1,3 @@
/*
* Copyright (c) 2016, 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.
*/
/** /**
* Checks if provided input is valid against RegEx input. * Checks if provided input is valid against RegEx input.
* *
@ -31,6 +13,8 @@ function inputIsValid(regExp, inputString) {
var validateInline = {}; var validateInline = {};
var clearInline = {}; var clearInline = {};
var apiBasePath = "/api/device-mgt/v1.0";
var enableInlineError = function (inputField, errorMsg, errorSign) { var enableInlineError = function (inputField, errorMsg, errorSign) {
var fieldIdentifier = "#" + inputField; var fieldIdentifier = "#" + inputField;
var errorMsgIdentifier = "#" + inputField + " ." + errorMsg; var errorMsgIdentifier = "#" + inputField + " ." + errorMsg;
@ -113,12 +97,12 @@ function formatRepoSelection (user) {
} }
$(document).ready(function () { $(document).ready(function () {
var appContext = $("#app-context").data("app-context");
$("#users").select2({ $("#users").select2({
multiple:true, multiple:true,
tags: false, tags: false,
ajax: { ajax: {
url: window.location.origin + "/devicemgt/api/invoker/execute/", url: appContext + "/api/invoker/execute/",
method: "POST", method: "POST",
dataType: 'json', dataType: 'json',
delay: 250, delay: 250,
@ -128,7 +112,7 @@ $(document).ready(function () {
data: function (params) { data: function (params) {
var postData = {}; var postData = {};
postData.actionMethod = "GET"; postData.actionMethod = "GET";
postData.actionUrl = "/devicemgt_admin/users/view-users?username=" + params.term; postData.actionUrl = apiBasePath + "/users/search/usernames?filter=" + params.term;
postData.actionPayload = null; postData.actionPayload = null;
return JSON.stringify(postData); return JSON.stringify(postData);
}, },
@ -155,7 +139,7 @@ $(document).ready(function () {
/** /**
* Following click function would execute * Following click function would execute
* when a user clicks on "Add Role" button * when a user clicks on "Add Role" button
* on Add Role page in WSO2 Devicemgt Console. * on Add Role page in WSO2 MDM Console.
*/ */
$("button#add-role-btn").click(function() { $("button#add-role-btn").click(function() {
var rolenameInput = $("input#rolename"); var rolenameInput = $("input#rolename");
@ -183,12 +167,12 @@ $(document).ready(function () {
addRoleFormData.roleName = domain + "/" + roleName; addRoleFormData.roleName = domain + "/" + roleName;
} }
var addRoleAPI = "/devicemgt_admin/roles?rolename=" + encodeURIComponent(currentRoleName); var addRoleAPI = apiBasePath + "/roles/" + currentRoleName;
invokerUtil.put( invokerUtil.put(
addRoleAPI, addRoleAPI,
addRoleFormData, addRoleFormData,
function (jqXHR) { function (data, textStatus, jqXHR) {
if (JSON.parse(jqXHR).status == 200 || jqXHR.status == 200) { if (jqXHR.status == 200) {
// Clearing user input fields. // Clearing user input fields.
$("input#rolename").val(""); $("input#rolename").val("");
$("#domain").val(""); $("#domain").val("");
@ -197,7 +181,8 @@ $(document).ready(function () {
$("#role-created-msg").removeClass("hidden"); $("#role-created-msg").removeClass("hidden");
} }
}, function (data) { }, function (data) {
$(errorMsg).text(JSON.parse(data.responseText).errorMessage); var payload = JSON.parse(data.responseText);
$(errorMsg).text(payload.message);
$(errorMsgWrapper).removeClass("hidden"); $(errorMsgWrapper).removeClass("hidden");
} }
); );

@ -16,7 +16,7 @@
* under the License. * under the License.
*/ */
var loadRoleBasedActionURL = function (action, rolename) { var loadRoleBasedActionURL = function (action, rolename) {
var href = $("#ast-container").data("app-context") + "roles/" + action + "?rolename=" + rolename; var href = $("#ast-container").data("app-context") + "role/" + action + "/" + rolename;
$(location).attr('href', href); $(location).attr('href', href);
}; };
@ -113,13 +113,13 @@ function loadRoles(searchQuery) {
class: "text-right content-fill text-left-on-grid-view no-wrap", class: "text-right content-fill text-left-on-grid-view no-wrap",
data: null, data: null,
render: function ( data, type, row, meta ) { render: function ( data, type, row, meta ) {
return '<a onclick="javascript:loadRoleBasedActionURL(\'edit-role\', \'' + data.name + '\')" data-role="' + data.name + return '<a onclick="javascript:loadRoleBasedActionURL(\'edit\', \'' + data.name + '\')" data-role="' + data.name +
'" data-click-event="edit-form" class="btn padding-reduce-on-grid-view edit-role-link"><span class="fw-stack fw-lg">' + '" data-click-event="edit-form" class="btn padding-reduce-on-grid-view edit-role-link"><span class="fw-stack fw-lg">' +
'<i class="fw fw-ring fw-stack-2x"></i><i class="fw fw-user fw-stack-1x"></i>' + '<i class="fw fw-ring fw-stack-2x"></i><i class="fw fw-user fw-stack-1x"></i>' +
'<span class="fw-stack fw-move-right fw-move-bottom"><i class="fw fw-circle fw-stack-2x fw-stroke fw-inverse"></i>' + '<span class="fw-stack fw-move-right fw-move-bottom"><i class="fw fw-circle fw-stack-2x fw-stroke fw-inverse"></i>' +
'<i class="fw fw-circle fw-stack-2x"></i><i class="fw fw-edit fw-stack-1x fw-inverse"></i></span></span>' + '<i class="fw fw-circle fw-stack-2x"></i><i class="fw fw-edit fw-stack-1x fw-inverse"></i></span></span>' +
'<span class="hidden-xs hidden-on-grid-view">Edit</span></a>' + '<span class="hidden-xs hidden-on-grid-view">Edit</span></a>' +
'<a onclick="javascript:loadRoleBasedActionURL(\'edit-role-permission\', \'' + data.name + '<a onclick="javascript:loadRoleBasedActionURL(\'edit-permission\', \'' + data.name +
'\')" data-role="' + data.name + '" data-click-event="edit-form" class="btn padding-reduce-on-grid-view edit-permission-link">' + '\')" data-role="' + data.name + '" data-click-event="edit-form" class="btn padding-reduce-on-grid-view edit-permission-link">' +
'<span class="fw-stack fw-lg"><i class="fw fw-ring fw-stack-2x"></i><i class="fw fw-security-policy fw-stack-1x"></i>' + '<span class="fw-stack fw-lg"><i class="fw fw-ring fw-stack-2x"></i><i class="fw fw-security-policy fw-stack-1x"></i>' +
'<span class="fw-stack fw-move-right fw-move-bottom"><i class="fw fw-circle fw-stack-2x fw-stroke fw-inverse"></i>' + '<span class="fw-stack fw-move-right fw-move-bottom"><i class="fw fw-circle fw-stack-2x fw-stroke fw-inverse"></i>' +

@ -50,7 +50,7 @@ $(document).ready(function () {
changePasswordFormData.oldPassword = unescape((oldPassword)); changePasswordFormData.oldPassword = unescape((oldPassword));
var changePasswordAPI = "/api/device-mgt/v1.0/users" + user + "/credentials"; var changePasswordAPI = "/api/device-mgt/v1.0/users/" + user + "/credentials";
invokerUtil.put( invokerUtil.put(
changePasswordAPI, changePasswordAPI,

@ -81,7 +81,7 @@ public class JWTClientManagerServiceImpl implements JWTClientManagerService {
addJWTClient(tenantDomain, jwtClient); addJWTClient(tenantDomain, jwtClient);
} catch (JWTClientAlreadyExistsException e) { } catch (JWTClientAlreadyExistsException e) {
log.warn("Attempting to register a jwt client for the tenant " + tenantDomain + log.warn("Attempting to register a jwt client for the tenant " + tenantDomain +
" when one already exists. Returning existing jwt client"); " when one already exists. Returning existing jwt client", e);
return getJWTClient(tenantDomain); return getJWTClient(tenantDomain);
} catch (JWTClientConfigurationException e) { } catch (JWTClientConfigurationException e) {
throw new JWTClientException("Failed to parse jwt configuration for tenant " + tenantDomain, e); throw new JWTClientException("Failed to parse jwt configuration for tenant " + tenantDomain, e);
@ -110,7 +110,7 @@ public class JWTClientManagerServiceImpl implements JWTClientManagerService {
addJWTClient(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, defaultJWTClient); addJWTClient(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, defaultJWTClient);
} catch (JWTClientAlreadyExistsException e) { } catch (JWTClientAlreadyExistsException e) {
log.warn("Attempting to register a jwt client for the super tenant" + log.warn("Attempting to register a jwt client for the super tenant" +
" when one already exists. Returning existing jwt client"); " when one already exists. Returning existing jwt client", e);
} }
} }
} }

@ -588,7 +588,3 @@ DM_DEVICE.ID = DM_DEVICE_DETAIL.DEVICE_ID
ORDER BY TENANT_ID, DEVICE_ID; ORDER BY TENANT_ID, DEVICE_ID;
-- END OF DASHBOARD RELATED VIEWS -- -- END OF DASHBOARD RELATED VIEWS --
SELECT feom.DEVICE_IDENTIFICATION, feom.DEVICE_TYPE, or.OPERATION_RESPONSE, feom.CREATED_TIMESTAMP
FROM DM_DEVICE_OPERATION_RESPONSE dor, (SELECT eom.OPERATION_ID, fe.DEVICE_IDENTIFICATION, fe.DEVICE_TYPE, fe.ENROLMENT_ID, eom.CREATED_TIMESTAMP, eom.UPDATED_TIMESTAMP, or.RECEIVED_TIMESTAMP FROM DM_ENROLMENT_OP_MAPPING eom, (SELECT e.ID AS ENROLMENT_ID, fd.DEVICE_ID, fd.DEVICE_IDENTIFICATION, fd.DEVICE_TYPE FROM DM_ENROLMENT e, (SELECT DISTINCT d.ID AS DEVICE_ID, d.DEVICE_IDENTIFICATION, t.NAME AS DEVICE_TYPE FROM DM_DEVICE d, DM_DEVICE_TYPE t WHERE d.DEVICE_TYPE_ID = t.ID AND d.TENANT_ID = -1234) fd WHERE e.DEVICE_ID = fd.DEVICE_ID AND e.TENANT_ID = -1234) fe WHERE eom.ENROLMENT_ID = fe.ENROLMENT_ID) feom WHERE or.OPERATION_ID = or.OPERATION_ID;

Loading…
Cancel
Save