Yohan Avishke 5 years ago
commit 6def2e1efa

@ -55,7 +55,7 @@ public class AuthenticationHandler extends AbstractHandler {
private static final String X_JWT_ASSERTION = "X-JWT-Assertion";
private static final String JWTTOKEN = "JWTToken";
private static final String AUTHORIZATION = "Authorization";
private static final String BEARER = "Bearer ";
private static final String BEARER = "Basic ";
private static final String CONTENT_TYPE = "Content-Type";
private IOTServerConfiguration iotServerConfiguration;
@ -95,7 +95,7 @@ public class AuthenticationHandler extends AbstractHandler {
log.debug("Verify Cert:\n" + mdmSignature);
}
URI certVerifyUrl = new URI(iotServerConfiguration.getVerificationEndpoint() + "ios");
Map<String, String> certVerifyHeaders = this.setHeaders(this.restInvoker);
Map<String, String> certVerifyHeaders = this.setHeaders();
Certificate certificate = new Certificate();
certificate.setPem(mdmSignature);
@ -127,7 +127,7 @@ public class AuthenticationHandler extends AbstractHandler {
String deviceType = this.getDeviceType(messageContext.getTo().getAddress().trim());
URI certVerifyUrl = new URI(iotServerConfiguration.getVerificationEndpoint() + deviceType);
Map<String, String> certVerifyHeaders = this.setHeaders(this.restInvoker);
Map<String, String> certVerifyHeaders = this.setHeaders();
Certificate certificate = new Certificate();
certificate.setPem(subjectDN);
certificate.setTenantId(tenantId);
@ -157,7 +157,7 @@ public class AuthenticationHandler extends AbstractHandler {
}
String deviceType = this.getDeviceType(messageContext.getTo().getAddress().trim());
URI certVerifyUrl = new URI(iotServerConfiguration.getVerificationEndpoint() + deviceType);
Map<String, String> certVerifyHeaders = this.setHeaders(this.restInvoker);
Map<String, String> certVerifyHeaders = this.setHeaders();
Certificate certificate = new Certificate();
certificate.setPem(encodedPem);
@ -184,9 +184,6 @@ public class AuthenticationHandler extends AbstractHandler {
} catch (URISyntaxException e) {
log.error("Error while processing certificate.", e);
return false;
} catch (APIMCertificateMGTException e) {
log.error("Error while processing certificate.", e);
return false;
} catch (CertificateException e) {
log.error("Certificate issue occurred when generating converting PEM to x509Certificate", e);
return false;
@ -212,9 +209,9 @@ public class AuthenticationHandler extends AbstractHandler {
return null;
}
private Map<String, String> setHeaders(RESTInvoker restInvoker) throws APIMCertificateMGTException {
private Map<String, String> setHeaders() {
Map<String, String> map = new HashMap<>();
String accessToken = Utils.getAccessToken(iotServerConfiguration, restInvoker);
String accessToken = Utils.getBase64EncodedToken(iotServerConfiguration);
map.put(AUTHORIZATION, BEARER + accessToken);
map.put(CONTENT_TYPE, "application/json");
return map;

@ -135,38 +135,14 @@ public class Utils {
}
/**
* This class get the access token from the key manager.
* This method is used to get the base64 encoded token.
*
* @param iotServerConfiguration Instance of the IoTsererConfiguration.
* @return Access token will be returned.
* @throws APIMCertificateMGTException
*/
public static String getAccessToken(IOTServerConfiguration iotServerConfiguration, RESTInvoker restInvoker)
throws APIMCertificateMGTException {
try {
if (clientId == null || clientSecret == null) {
getClientSecretes(iotServerConfiguration, restInvoker);
}
URI tokenUrl = new URI(iotServerConfiguration.getOauthTokenEndpoint());
String tokenContent = "grant_type=password&username=" + iotServerConfiguration.getUsername() + "&password=" +
iotServerConfiguration.getPassword() + "&scope=activity-view";
String tokenBasicAuth = "Basic " + Base64.encode((clientId + ":" + clientSecret).getBytes());
Map<String, String> tokenHeaders = new HashMap<>();
tokenHeaders.put("Authorization", tokenBasicAuth);
tokenHeaders.put("Content-Type", "application/x-www-form-urlencoded");
RESTResponse response = restInvoker.invokePOST(tokenUrl, tokenHeaders, tokenContent);
if (log.isDebugEnabled()) {
log.debug("Token response:" + response.getContent());
}
JSONObject jsonResponse = new JSONObject(response.getContent());
return jsonResponse.getString("access_token");
} catch (URISyntaxException | IOException e) {
throw new APIMCertificateMGTException("Error occurred while trying to call oauth token endpoint", e);
} catch (JSONException e) {
throw new APIMCertificateMGTException("Error occurred while converting the json to object", e);
}
public static String getBase64EncodedToken(IOTServerConfiguration iotServerConfiguration) {
return Base64.encode((iotServerConfiguration.getUsername() + ":" + iotServerConfiguration.getPassword()).
getBytes());
}
/**

@ -92,8 +92,6 @@ public class AuthenticationHandlerTest extends BaseAPIHandlerTest {
HashMap<String, String> transportHeaders = new HashMap<>();
transportHeaders.put(AuthConstants.MDM_SIGNATURE, "some cert");
setMockClient();
this.mockClient.setResponse(getDCRResponse());
this.mockClient.setResponse(getAccessTokenReponse());
this.mockClient.setResponse(getValidationResponse());
boolean response = this.handler.handleRequest(createSynapseMessageContext("<empty/>", this.synapseConfiguration,
transportHeaders, "https://test.com/testservice/device-mgt/testdevice"));
@ -107,7 +105,6 @@ public class AuthenticationHandlerTest extends BaseAPIHandlerTest {
HashMap<String, String> transportHeaders = new HashMap<>();
transportHeaders.put(AuthConstants.PROXY_MUTUAL_AUTH_HEADER, "Test Header");
setMockClient();
this.mockClient.setResponse(getAccessTokenReponse());
this.mockClient.setResponse(getValidationResponse());
boolean response = this.handler.handleRequest(createSynapseMessageContext("<empty/>", this.synapseConfiguration,
transportHeaders, "https://test.com/testservice/device-mgt/testdevice"));
@ -121,7 +118,6 @@ public class AuthenticationHandlerTest extends BaseAPIHandlerTest {
HashMap<String, String> transportHeaders = new HashMap<>();
transportHeaders.put(AuthConstants.MUTUAL_AUTH_HEADER, "Test Header");
setMockClient();
this.mockClient.setResponse(getAccessTokenReponse());
this.mockClient.setResponse(getValidationResponse());
MessageContext messageContext = createSynapseMessageContext("<empty/>", this.synapseConfiguration,
transportHeaders, "https://test.com/testservice/device-mgt/testdevice");
@ -141,7 +137,6 @@ public class AuthenticationHandlerTest extends BaseAPIHandlerTest {
HashMap<String, String> transportHeaders = new HashMap<>();
transportHeaders.put(AuthConstants.ENCODED_PEM, "encoded pem");
setMockClient();
this.mockClient.setResponse(getAccessTokenReponse());
this.mockClient.setResponse(getValidationResponse());
MessageContext messageContext = createSynapseMessageContext("<empty/>", this.synapseConfiguration,
transportHeaders, "https://test.com/testservice/device-mgt/testdevice");
@ -156,7 +151,6 @@ public class AuthenticationHandlerTest extends BaseAPIHandlerTest {
HashMap<String, String> transportHeaders = new HashMap<>();
transportHeaders.put(AuthConstants.ENCODED_PEM, "encoded pem");
setMockClient();
this.mockClient.setResponse(getAccessTokenReponse());
this.mockClient.setResponse(getInvalidResponse());
MessageContext messageContext = createSynapseMessageContext("<empty/>", this.synapseConfiguration,
transportHeaders, "https://test.com/testservice/device-mgt/testdevice");
@ -185,7 +179,6 @@ public class AuthenticationHandlerTest extends BaseAPIHandlerTest {
HashMap<String, String> transportHeaders = new HashMap<>();
transportHeaders.put(AuthConstants.ENCODED_PEM, "encoded pem");
setMockClient();
this.mockClient.setResponse(getAccessTokenReponse());
this.mockClient.setResponse(null);
MessageContext messageContext = createSynapseMessageContext("<empty/>", this.synapseConfiguration,
transportHeaders, "https://test.com/testservice/device-mgt/testdevice");

@ -37,6 +37,10 @@
<param-name>doAuthentication</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>basicAuth</param-name>
<param-value>true</param-value>
</context-param>
<!--publish to apim-->
<context-param>

@ -324,9 +324,14 @@ public class CertificateGenerator {
KeyStoreReader keyStoreReader = new KeyStoreReader();
if (distinguishedName != null && !distinguishedName.isEmpty()) {
if (distinguishedName.contains("/CN=")) {
String[] dnSplits = distinguishedName.split("/CN=");
String commonNameExtracted = dnSplits[dnSplits.length - 1];
lookUpCertificate = keyStoreReader.getCertificateBySerial(commonNameExtracted);
String[] dnSplits = distinguishedName.split("/");
for (String dnPart : dnSplits) {
if (dnPart.contains("CN=")) {
String commonNameExtracted = dnPart.replace("CN=", "");
lookUpCertificate = keyStoreReader.getCertificateBySerial(commonNameExtracted);
break;
}
}
} else {
LdapName ldapName;
try {
@ -711,4 +716,4 @@ public class CertificateGenerator {
return generateCertificateFromCSR(privateKeyCA, certificationRequest,
certCA.getIssuerX500Principal().getName());
}
}
}

@ -41,6 +41,10 @@
<param-name>isDefault</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>basicAuth</param-name>
<param-value>true</param-value>
</context-param>
<!--publish to apim-->
<context-param>

@ -0,0 +1,277 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2019, Entgra (Pvt) Ltd. (http://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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>device-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.2.9-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>io.entgra.carbon.device.mgt.config.api</artifactId>
<packaging>war</packaging>
<name>Entgra Carbon - Mobile Device Management Configuration API</name>
<description>Entgra Carbon - Mobile Device Management Configuration API</description>
<url>https://entgra.io</url>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<packagingExcludes>WEB-INF/lib/*cxf*.jar</packagingExcludes>
<warName>api#device-mgt-config#v1.0</warName>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<destFile>${basedir}/target/coverage-reports/jacoco-unit.exec</destFile>
</configuration>
<executions>
<execution>
<id>jacoco-initialize</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-site</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${basedir}/target/coverage-reports/jacoco-unit.exec</dataFile>
<outputDirectory>${basedir}/target/coverage-reports/site</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<log4j.configuration>file:src/test/resources/log4j.properties</log4j.configuration>
</systemPropertyVariables>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>deploy</id>
<build>
<defaultGoal>compile</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<copy todir="${basedir}/../../../repository/deployment/server/webapps" overwrite="true">
<fileset dir="${basedir}/target">
<include name="api#device-mgt-config#v1.0.war" />
</fileset>
</copy>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>client</id>
<build>
<defaultGoal>test</defaultGoal>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.core</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.apache.axis2.wso2</groupId>
<artifactId>axis2-client</artifactId>
</exclusion>
<exclusion>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</exclusion>
<exclusion>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.certificate.mgt.core</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.core</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.carbon.identity.framework</groupId>
<artifactId>org.wso2.carbon.user.mgt</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-core</artifactId>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.orbit.com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jaxrs</artifactId>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.orbit.com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.apimgt.annotations</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-testng</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.identity.jwt.client.extension</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.wso2.tomcat</groupId>
<artifactId>tomcat</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.tomcat</groupId>
<artifactId>tomcat-servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

@ -0,0 +1,50 @@
/*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.carbon.device.mgt.config.jaxrs;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ApiOriginFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.addHeader("Access-Control-Allow-Origin", "*");
res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
res.addHeader("Access-Control-Allow-Headers", "Content-Type");
chain.doFilter(request, response);
}
public void destroy() {
//do nothing
}
public void init(FilterConfig filterConfig) throws ServletException {
//do nothing
}
}

@ -0,0 +1,77 @@
/*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.carbon.device.mgt.config.jaxrs.beans;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotNull;
@ApiModel(description = "")
public class ErrorListItem {
@NotNull
private String code = null;
@NotNull
private String message = null;
@ApiModelProperty(required = true, value = "")
@JsonProperty("code")
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public ErrorListItem() {}
public ErrorListItem(String code, String msg) {
this.code = code;
this.message = msg;
}
/**
* Description about individual errors occurred
**/
@ApiModelProperty(required = true, value = "Description about individual errors occurred")
@JsonProperty("message")
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("errorItem {\n");
sb.append(" code: ").append(code).append("\n");
sb.append(" message: ").append(message).append("\n");
sb.append("}\n");
return sb.toString();
}
}

@ -0,0 +1,150 @@
/*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.carbon.device.mgt.config.jaxrs.beans;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.ArrayList;
import java.util.List;
@ApiModel(description = "")
public class ErrorResponse {
private Long code = null;
private String message = null;
private String description = null;
private String moreInfo = null;
private List<ErrorListItem> errorItems = new ArrayList<>();
public ErrorResponse() {}
@JsonProperty(value = "code")
@ApiModelProperty(required = true, value = "")
public Long getCode() {
return code;
}
public void setCode(Long code) {
this.code = code;
}
@JsonProperty(value = "message")
@ApiModelProperty(required = true, value = "ErrorResponse message.")
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@JsonProperty(value = "description")
@ApiModelProperty(value = "A detail description about the error message.")
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@JsonProperty(value = "moreInfo")
@ApiModelProperty(value = "Preferably an url with more details about the error.")
public String getMoreInfo() {
return moreInfo;
}
public void setMoreInfo(String moreInfo) {
this.moreInfo = moreInfo;
}
public void addErrorListItem(ErrorListItem item) {
this.errorItems.add(item);
}
/**
* If there are more than one error list them out. For example, list out validation errors by each field.
*/
@JsonProperty(value = "errorItems")
@ApiModelProperty(value = "If there are more than one error list them out. \n" +
"For example, list out validation errors by each field.")
public List<ErrorListItem> getErrorItems() {
return errorItems;
}
public void setErrorItems(List<ErrorListItem> error) {
this.errorItems = error;
}
public static class ErrorResponseBuilder {
private Long code = null;
private String message = null;
private String description = null;
private String moreInfo = null;
private List<ErrorListItem> error;
public ErrorResponseBuilder() {
this.error = new ArrayList<>();
}
public ErrorResponseBuilder setCode(long code) {
this.code = code;
return this;
}
public ErrorResponseBuilder setMessage(String message) {
this.message = message;
return this;
}
public ErrorResponseBuilder setDescription(String description) {
this.description = description;
return this;
}
public ErrorResponseBuilder setMoreInfo(String moreInfo) {
this.moreInfo = moreInfo;
return this;
}
public ErrorResponseBuilder addErrorItem(String code, String msg) {
ErrorListItem item = new ErrorListItem();
item.setCode(code);
item.setMessage(msg);
this.error.add(item);
return this;
}
public ErrorResponse build() {
ErrorResponse errorResponse = new ErrorResponse();
errorResponse.setCode(code);
errorResponse.setMessage(message);
errorResponse.setErrorItems(error);
errorResponse.setDescription(description);
errorResponse.setMoreInfo(moreInfo);
return errorResponse;
}
}
}

@ -0,0 +1,97 @@
/*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.carbon.device.mgt.config.jaxrs.common;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
@Provider
@Produces(APPLICATION_JSON)
@Consumes(APPLICATION_JSON)
public class GsonMessageBodyHandler implements MessageBodyWriter<Object>, MessageBodyReader<Object> {
public static final String DATE_FORMAT = "EEE, d MMM yyyy HH:mm:ss Z";
private Gson gson;
private static final String UTF_8 = "UTF-8";
public boolean isReadable(Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) {
return true;
}
private Gson getGson() {
if (gson == null) {
final GsonBuilder gsonBuilder = new GsonBuilder();
gson = gsonBuilder.setDateFormat(DATE_FORMAT).create();
}
return gson;
}
public Object readFrom(Class<Object> objectClass, Type type, Annotation[] annotations,
MediaType mediaType, MultivaluedMap<String, String> stringStringMultivaluedMap,
InputStream entityStream)
throws IOException, WebApplicationException {
InputStreamReader reader = new InputStreamReader(entityStream, "UTF-8");
try {
return getGson().fromJson(reader, type);
} finally {
reader.close();
}
}
public boolean isWriteable(Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) {
return true;
}
public long getSize(Object o, Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) {
return -1;
}
public void writeTo(Object object, Class<?> aClass, Type type, Annotation[] annotations,
MediaType mediaType, MultivaluedMap<String, Object> stringObjectMultivaluedMap,
OutputStream entityStream)
throws IOException, WebApplicationException {
OutputStreamWriter writer = new OutputStreamWriter(entityStream, UTF_8);
try {
getGson().toJson(object, type, writer);
} finally {
writer.close();
}
}
}

@ -0,0 +1,134 @@
/*
* 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.
*/
package io.entgra.carbon.device.mgt.config.jaxrs.service;
import io.entgra.carbon.device.mgt.config.jaxrs.beans.ErrorResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Extension;
import io.swagger.annotations.ExtensionProperty;
import io.swagger.annotations.Info;
import io.swagger.annotations.ResponseHeader;
import io.swagger.annotations.SwaggerDefinition;
import io.swagger.annotations.Tag;
import org.wso2.carbon.apimgt.annotations.api.Scope;
import org.wso2.carbon.apimgt.annotations.api.Scopes;
import org.wso2.carbon.device.mgt.common.configuration.mgt.DeviceConfiguration;
import org.wso2.carbon.device.mgt.common.search.PropertyMap;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@SwaggerDefinition(
info = @Info(
version = "1.0.0",
title = "",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = "name", value = "DeviceManagementConfiguration"),
@ExtensionProperty(name = "context",
value = "/api/device-mgt-config/v1.0/configurations"),
})
}
),
tags = {
@Tag(name = "device_management", description = "")
}
)
@Path("/configurations")
@Api(value = "Device Management Configuration")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Scopes(scopes = {
@Scope(
name = "View configurations",
description = "",
key = "perm:view-configuration",
permissions = {"/device-mgt/platform-configurations/view"}
)
}
)
public interface DeviceManagementConfigService {
@GET
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "Getting General device Configurations",
notes = "This API is responsible for send device configuration data to an IOT device when the " +
"device starts provisioning",
tags = "Device Management Configuration"
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully fetched the device configurations.",
response = DeviceConfiguration.class,
responseContainer = "List",
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource has been modified " +
"the last time.Used by caches, or in " +
"conditional requests."),
}
),
@ApiResponse(
code = 400,
message = "Bad request.\n The request contains invalid parameters"),
@ApiResponse(
code = 401,
message = "Unauthorized.\n The requested is not authorized"),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Server error occurred while " +
"fetching device configurations.",
response = ErrorResponse.class)
})
Response getConfiguration(@ApiParam(
name = "token",
value = "value for identify an already enrolled and authorized device",
required = true)
@HeaderParam("token")
String token,
@ApiParam(
name = "properties",
value = "The properties list using for query a device",
required = true)
@QueryParam("properties")
String properties);
}

@ -0,0 +1,151 @@
/*
* 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.
*/
package io.entgra.carbon.device.mgt.config.jaxrs.service.impl;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.entgra.carbon.device.mgt.config.jaxrs.beans.ErrorResponse;
import io.entgra.carbon.device.mgt.config.jaxrs.service.DeviceManagementConfigService;
import io.entgra.carbon.device.mgt.config.jaxrs.util.DeviceMgtAPIUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.common.AppRegistrationCredentials;
import org.wso2.carbon.device.mgt.common.ApplicationRegistrationException;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.DeviceNotFoundException;
import org.wso2.carbon.device.mgt.common.configuration.mgt.AmbiguousConfigurationException;
import org.wso2.carbon.device.mgt.common.configuration.mgt.DeviceConfiguration;
import org.wso2.carbon.device.mgt.core.DeviceManagementConstants;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil;
import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo;
import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.util.Map;
@Path("/configurations")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class DeviceManagementConfigServiceImpl implements DeviceManagementConfigService {
private static final Log log = LogFactory.getLog(DeviceManagementConfigServiceImpl.class);
@Override
@GET
public Response getConfiguration(@HeaderParam("token") String token,
@QueryParam("properties") String properties) {
DeviceManagementProviderService dms = DeviceMgtAPIUtils.getDeviceManagementService();
try {
if (token == null || token.isEmpty()) {
String msg = "No valid token property found";
log.error(msg);
return Response.status(Response.Status.UNAUTHORIZED).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()
).build();
}
if (properties == null || properties.isEmpty()) {
String msg = "Devices configuration retrieval criteria cannot be null or empty.";
log.error(msg);
return Response.status(Response.Status.BAD_REQUEST).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()
).build();
}
ObjectMapper mapper = new ObjectMapper();
properties = parseUriParamsToJSON(properties);
Map<String, String> deviceProps = mapper.readValue(properties,
new TypeReference<Map<String, String>>() {
});
deviceProps.put("token", token);
DeviceConfiguration devicesConfiguration =
dms.getDeviceConfiguration(deviceProps);
setAccessTokenToDeviceConfigurations(devicesConfiguration);
return Response.status(Response.Status.OK).entity(devicesConfiguration).build();
} catch (DeviceManagementException e) {
String msg = "Error occurred while retrieving configurations";
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
} catch (DeviceNotFoundException e) {
log.error(e.getMessage(), e);
return Response.status(Response.Status.BAD_REQUEST).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(e.getMessage()).build()).build();
} catch (AmbiguousConfigurationException e) {
String msg = "Configurations are ambiguous";
log.error(msg, e);
return Response.status(Response.Status.BAD_REQUEST).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
} catch (JsonParseException | JsonMappingException e) {
String msg = "Malformed device property structure";
log.error(msg.concat(" ").concat(properties), e);
return Response.status(Response.Status.BAD_REQUEST).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
} catch (IOException e) {
String msg = "Error occurred while parsing query param JSON data";
log.error(msg.concat(" ").concat(properties), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
}
}
private String parseUriParamsToJSON(String uriParams) {
uriParams = uriParams.replaceAll("=", "\":\"");
uriParams = uriParams.replaceAll("&", "\",\"");
return "{\"" + uriParams + "\"}";
}
private void setAccessTokenToDeviceConfigurations(DeviceConfiguration devicesConfiguration)
throws DeviceManagementException {
try {
AppRegistrationCredentials credentials =
DeviceManagerUtil.getApplicationRegistrationCredentials(
System.getProperty(DeviceManagementConstants
.ConfigurationManagement.IOT_GATEWAY_HOST),
System.getProperty(DeviceManagementConstants
.ConfigurationManagement.IOT_GATEWAY_HTTPS_PORT),
DeviceManagementConstants.ConfigurationManagement.ADMIN_CREDENTIALS);
AccessTokenInfo accessTokenForAdmin = DeviceManagerUtil.getAccessTokenForDeviceOwner(
DeviceManagementConstants.ConfigurationManagement.SCOPES_FOR_TOKEN,
credentials.getClient_id(), credentials.getClient_secret(),
devicesConfiguration.getDeviceOwner());
devicesConfiguration.setAccessToken(accessTokenForAdmin.getAccessToken());
devicesConfiguration.setRefreshToken(accessTokenForAdmin.getRefreshToken());
} catch (ApplicationRegistrationException e) {
String msg = "Failure on retrieving application registration";
log.error(msg, e);
throw new DeviceManagementException(msg, e);
} catch (JWTClientException e) {
String msg = "Error occurred while creating JWT client : " + e.getMessage();
log.error(msg, e);
throw new DeviceManagementException(msg, e);
}
}
}

@ -0,0 +1,43 @@
/*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.carbon.device.mgt.config.jaxrs.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
/**
* MDMAPIUtils class provides utility function used by CDM REST-API classes.
*/
public class DeviceMgtAPIUtils {
private static Log log = LogFactory.getLog(DeviceMgtAPIUtils.class);
public static DeviceManagementProviderService getDeviceManagementService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
DeviceManagementProviderService deviceManagementProviderService =
(DeviceManagementProviderService) ctx.getOSGiService(DeviceManagementProviderService.class, null);
if (deviceManagementProviderService == null) {
String msg = "DeviceImpl Management provider service has not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
return deviceManagementProviderService;
}
}

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2019, Entgra (Pvt) Ltd. (http://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.
-->
<!-- This file contains the list of permissions that are associated with URL end points
of the web app. Each permission should contain the name, permission path ,API path
(URL) , HTTP method and OAUTH2 authorization scope (not-required).
When defining dynamic paths for APIs, path variables are denoted by '*' notation.
For ex:
Actual API endpoint: devicemgt_admin/1.0.0/devices/{device-id}
URL to be represented here: /devices/*
NOTE: All the endpoints of the web app should be available in this file. Otherwise
it will result 403 error at the runtime.
-->
<PermissionConfiguration>
<APIVersion></APIVersion>
<!--Permission Tree Name-->
<Permission>
<name>Device Management Configuration</name>
<path>/device-mgt-config</path>
<url>/</url>
<method>GET</method>
</Permission>
</PermissionConfiguration>

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
~ Copyright (c) 2019, Entgra (Pvt) Ltd. (http://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.
-->
<!--
This file defines class loading policy of the whole container. But this behaviour can be overridden by individual webapps by putting this file into the META-INF/ directory.
-->
<Classloading xmlns="http://wso2.org/projects/as/classloading">
<!-- Parent-first or child-first. Default behaviour is child-first.-->
<ParentFirst>false</ParentFirst>
<!--
Default environments that contains provides to all the webapps. This can be overridden by individual webapps by specifing required environments
Tomcat environment is the default and every webapps gets it even if they didn't specify it.
e.g. If a webapps requires CXF, they will get both Tomcat and CXF.
-->
<Environments>CXF,Carbon</Environments>
</Classloading>

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">
<jaxrs:server id="services-10" address="/">
<jaxrs:serviceBeans>
<ref bean="configManagementService"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean="jsonProvider"/>
</jaxrs:providers>
</jaxrs:server>
<bean id="configManagementService"
class="io.entgra.carbon.device.mgt.config.jaxrs.service.impl.DeviceManagementConfigServiceImpl"/>
<bean id="jsonProvider" class="io.entgra.carbon.device.mgt.config.jaxrs.common.GsonMessageBodyHandler"/>
</beans>

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name>Device-Config-Webapp</display-name>
<servlet>
<description>JAX-WS/JAX-RS Device Configuration Endpoint</description>
<display-name>JAX-WS/JAX-RS Servlet</display-name>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<!-- configure a security filter -->
<init-param>
<param-name>swagger.security.filter</param-name>
<param-value>ApiAuthorizationFilterImpl</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
<context-param>
<param-name>doAuthentication</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>nonSecuredEndPoints</param-name>
<param-value>
/api/device-mgt-config/v1.0/configurations
</param-value>
</context-param>
<!--publish to apim-->
<context-param>
<param-name>managed-api-enabled</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>managed-api-owner</param-name>
<param-value>admin</param-value>
</context-param>
<context-param>
<param-name>isSharedWithAllTenants</param-name>
<param-value>true</param-value>
</context-param>
<!-- Below configuration is used to redirect http requests to https -->
<security-constraint>
<web-resource-collection>
<web-resource-name>DeviceMgt-Admin</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<filter>
<filter-name>ApiOriginFilter</filter-name>
<filter-class>io.entgra.carbon.device.mgt.config.jaxrs.ApiOriginFilter</filter-class>
</filter>
<filter>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
<init-param>
<param-name>hstsEnabled</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter>
<filter-name>ContentTypeBasedCachePreventionFilter</filter-name>
<filter-class>org.wso2.carbon.ui.filters.cache.ContentTypeBasedCachePreventionFilter</filter-class>
<init-param>
<param-name>patterns</param-name>
<param-value>text/html" ,application/json" ,text/plain</param-value>
</init-param>
<init-param>
<param-name>filterAction</param-name>
<param-value>enforce</param-value>
</init-param>
<init-param>
<param-name>httpHeaders</param-name>
<param-value>Cache-Control: no-store, no-cache, must-revalidate, private</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>ContentTypeBasedCachePreventionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>ApiOriginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

@ -0,0 +1,23 @@
<!--
~ Copyright (c) 2019, Entgra (Pvt) Ltd. (http://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.
-->
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="DeviceManagementExtensions">
<parameter name="useDefaultListeners" value="false"/>
</suite>

@ -901,12 +901,7 @@ public interface DeviceManagementService {
required = true)
@PathParam("device-id")
@Size(max = 45)
String deviceId,
@ApiParam(
name = "permanentDelete",
value = "Boolean flag indicating whether to permanently delete the device.",
required = false)
@QueryParam("permanentDelete") boolean permanentDelete);
String deviceId);
@GET
@Path("/{type}/{id}/features")

@ -15,6 +15,22 @@
* specific language governing permissions and limitations
* under the License.
*
*
* Copyright (c) 2019, Entgra (pvt) Ltd. (https://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.jaxrs.service.api.admin;
@ -76,6 +92,12 @@ import java.util.List;
description = "Update the ownership of the device",
key = "perm:admin:devices:update-enrollment",
permissions = {"/device-mgt/admin/devices/update-enrollment"}
),
@Scope(
name = "Permanently Delete the device specified by device id",
description = "Permanently Delete the device specified by device id",
key = "perm:devices:permanent-delete",
permissions = {"/device-mgt/admin/devices/permanent-delete"}
)
}
)
@ -225,4 +247,72 @@ public interface DeviceManagementAdminService {
value = "List of device identifiers.",
required = true)
List<String> deviceIdentifiers);
@DELETE
@Path("/type/{device-type}/id/{device-id}")
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
consumes = MediaType.APPLICATION_JSON,
httpMethod = "DELETE",
value = "Permanently remove the Device Specified by the Device ID",
notes = "Returns the status of the permanently deleted device operation and the details of the deleted device.",
tags = "Device Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:devices:permanent-delete")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully deleted the device permanently.",
response = Device.class,
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource has been modified the last time.\n" +
"Used by caches, or in conditional requests."),
}),
@ApiResponse(
code = 304,
message = "Not Modified. Empty body because the client already has the latest " +
"version of the requested resource."),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error.",
response = ErrorResponse.class),
@ApiResponse(
code = 404,
message = "Not Found. \n No device is found under the provided type and id.",
response = ErrorResponse.class),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n " +
"Server error occurred while retrieving information requested device.",
response = ErrorResponse.class)
})
Response deleteDevicePermanently(
@ApiParam(
name = "device-type",
value = "The device type, such as ios, android, or windows.",
required = true)
@PathParam("device-type")
@Size(max = 45)
String deviceType,
@ApiParam(
name = "device-id",
value = "The device identifier of the device.",
required = true)
@PathParam("device-id")
@Size(max = 45)
String deviceId);
}

@ -105,7 +105,6 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Path("/devices")
@Produces(MediaType.APPLICATION_JSON)
@ -326,8 +325,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
@Override
@Path("/type/{device-type}/id/{device-id}")
public Response deleteDevice(@PathParam("device-type") String deviceType,
@PathParam("device-id") String deviceId,
@QueryParam("permanentDelete") boolean permanentDelete) {
@PathParam("device-id") String deviceId) {
DeviceManagementProviderService deviceManagementProviderService =
DeviceMgtAPIUtils.getDeviceManagementService();
try {
@ -336,16 +334,8 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
if (persistedDevice == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
boolean response;
if (permanentDelete) {
response = deviceManagementProviderService.deleteDevice(deviceIdentifier);
} else {
response = deviceManagementProviderService.disenrollDevice(deviceIdentifier);
}
boolean response = deviceManagementProviderService.disenrollDevice(deviceIdentifier);
return Response.status(Response.Status.OK).entity(response).build();
} catch (DeviceManagementException e) {
String msg = "Error encountered while deleting device of type : " + deviceType + " and " +
"ID : " + deviceId;

@ -15,28 +15,43 @@
* specific language governing permissions and limitations
* under the License.
*
*
* Copyright (c) 2019, Entgra (pvt) Ltd. (https://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package 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.DeviceIdentifier;
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.core.service.DeviceManagementProviderService;
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;
@ -99,25 +114,53 @@ public class DeviceManagementAdminServiceImpl implements DeviceManagementAdminSe
@QueryParam("owner") String owner,
List<String> deviceIdentifiers){
try {
if (DeviceMgtAPIUtils.getDeviceManagementService().updateEnrollment(owner, deviceIdentifiers)){
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){
} catch (InvalidDeviceException e) {
String msg = "Invalid device identifiers are found with the request.";
log.error(msg);
log.error(msg, e);
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
}catch (DeviceManagementException e) {
} catch (DeviceManagementException e) {
String msg = "Error occurred when updating device owners.";
log.error(msg);
log.error(msg, e);
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);
log.error(msg, e);
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
}
}
@DELETE
@Override
@Path("/type/{device-type}/id/{device-id}")
public Response deleteDevicePermanently(@PathParam("device-type") String deviceType,
@PathParam("device-id") String deviceId) {
DeviceManagementProviderService deviceManagementProviderService =
DeviceMgtAPIUtils.getDeviceManagementService();
try {
DeviceIdentifier deviceIdentifier = new DeviceIdentifier(deviceId, deviceType);
Device persistedDevice = deviceManagementProviderService.getDevice(deviceIdentifier, true);
if (persistedDevice == null) {
String msg = "No device found with the device type: " + deviceType +
" having the device ID: " + deviceId + " to permanently delete.";
log.error(msg);
return Response.status(Response.Status.NOT_FOUND).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
}
boolean response = deviceManagementProviderService.deleteDevice(deviceIdentifier);
return Response.status(Response.Status.OK).entity(response).build();
} catch (DeviceManagementException e) {
String msg = "Error encountered while permanently deleting device of type : " + deviceType + " and " +
"ID : " + deviceId;
log.error(msg, e);
return Response.status(Response.Status.BAD_REQUEST).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
}
}
}

@ -137,7 +137,8 @@ public class DeviceTypeManagementAdminServiceImpl implements DeviceTypeManagemen
@Override
@PUT
public Response updateDeviceType(String type, DeviceType deviceType) {
@Path("/{type}")
public Response updateDeviceType(@PathParam("type") String type, DeviceType deviceType) {
if (deviceType != null && deviceType.getDeviceTypeMetaDefinition() != null) {
if (deviceType.getName() == null || !deviceType.getName().equals(type)) {
return Response.status(Response.Status.BAD_REQUEST).entity("Type name mismatch. Expected: '" + type +
@ -163,7 +164,10 @@ public class DeviceTypeManagementAdminServiceImpl implements DeviceTypeManagemen
}
@Override
public Response addDeviceTypePlatformConfig(String type, PlatformConfiguration platformConfiguration) {
@POST
@Path("/{type}/configs")
public Response addDeviceTypePlatformConfig(@PathParam("type") String type,
PlatformConfiguration platformConfiguration) {
boolean isSaved;
if (platformConfiguration.getType() == null || !platformConfiguration.getType().equals(type)) {
return Response.status(Response.Status.BAD_REQUEST).entity("Type name mismatch. Expected: '" + type +

@ -481,8 +481,7 @@ public class DeviceManagementServiceImplTest {
public void testDeleteDevice() {
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService"))
.toReturn(this.deviceManagementProviderService);
Response response = this.deviceManagementService.deleteDevice(TEST_DEVICE_TYPE, UUID.randomUUID().toString()
, false);
Response response = this.deviceManagementService.deleteDevice(TEST_DEVICE_TYPE, UUID.randomUUID().toString());
Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());
}
@ -492,8 +491,7 @@ public class DeviceManagementServiceImplTest {
.toReturn(this.deviceManagementProviderService);
Mockito.when(this.deviceManagementProviderService
.getDevice(Mockito.any(DeviceIdentifier.class), Mockito.anyBoolean())).thenReturn(null);
Response response = this.deviceManagementService.deleteDevice(TEST_DEVICE_TYPE, UUID.randomUUID().toString()
, false);
Response response = this.deviceManagementService.deleteDevice(TEST_DEVICE_TYPE, UUID.randomUUID().toString());
Assert.assertEquals(response.getStatus(), Response.Status.NOT_FOUND.getStatusCode());
Mockito.reset(this.deviceManagementProviderService);
}
@ -504,8 +502,7 @@ public class DeviceManagementServiceImplTest {
.toReturn(this.deviceManagementProviderService);
Mockito.when(this.deviceManagementProviderService.disenrollDevice(Mockito.any(DeviceIdentifier.class)))
.thenThrow(new DeviceManagementException());
Response response = this.deviceManagementService.deleteDevice(TEST_DEVICE_TYPE, UUID.randomUUID().toString()
, false);
Response response = this.deviceManagementService.deleteDevice(TEST_DEVICE_TYPE, UUID.randomUUID().toString());
Assert.assertEquals(response.getStatus(), Response.Status.BAD_REQUEST.getStatusCode());
Mockito.reset(this.deviceManagementProviderService);
}

@ -0,0 +1,43 @@
/*
* 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.
*/
package org.wso2.carbon.device.mgt.common;
/**
* Wrap application registration response payload
*/
public class AppRegistrationCredentials {
private String client_id;
private String client_secret;
public String getClient_id() {
return client_id;
}
public void setClient_id(String client_id) {
this.client_id = client_id;
}
public String getClient_secret() {
return client_secret;
}
public void setClient_secret(String client_secret) {
this.client_secret = client_secret;
}
}

@ -0,0 +1,65 @@
/*
* 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.
*/
package org.wso2.carbon.device.mgt.common;
import java.util.List;
/**
* This class is use to wrap and send
* Application registration data to the API publisher
* Use only for application registration doing inside the IoTs
*/
public class ApplicationRegistration {
private String applicationName;
private List<String> tags;
private boolean isAllowedToAllDomains;
private long validityPeriod;
public String getApplicationName() {
return applicationName;
}
public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
public List<String> getTags() {
return tags;
}
public void setTags(List<String> tags) {
this.tags = tags;
}
public boolean isAllowedToAllDomains() {
return isAllowedToAllDomains;
}
public void setAllowedToAllDomains(boolean allowedToAllDomains) {
isAllowedToAllDomains = allowedToAllDomains;
}
public long getValidityPeriod() {
return validityPeriod;
}
public void setValidityPeriod(long validityPeriod) {
this.validityPeriod = validityPeriod;
}
}

@ -0,0 +1,46 @@
/*
* 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.
*/
package org.wso2.carbon.device.mgt.common;
/**
* Throw this if any errors throw when the application registration API calling
*/
public class ApplicationRegistrationException extends Exception {
private static final long serialVersionUID = 4718132518977041928L;
public ApplicationRegistrationException(String msg, Exception nestedEx) {
super(msg, nestedEx);
}
public ApplicationRegistrationException(String message, Throwable cause) {
super(message, cause);
}
public ApplicationRegistrationException(String msg) {
super(msg);
}
public ApplicationRegistrationException() {
super();
}
public ApplicationRegistrationException(Throwable cause) {
super(cause);
}
}

@ -0,0 +1,46 @@
/*
* 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.
*/
package org.wso2.carbon.device.mgt.common;
/**
* Throws if any arguments send to an API is wrong or invalid
*/
public class InvalidArgumentException extends Exception {
private static final long serialVersionUID = -2365244687985953509L;
public InvalidArgumentException(String msg, Exception nestedEx) {
super(msg, nestedEx);
}
public InvalidArgumentException(String message, Throwable cause) {
super(message, cause);
}
public InvalidArgumentException(String msg) {
super(msg);
}
public InvalidArgumentException() {
super();
}
public InvalidArgumentException(Throwable cause) {
super(cause);
}
}

@ -0,0 +1,25 @@
package org.wso2.carbon.device.mgt.common.configuration.mgt;
public class AmbiguousConfigurationException extends Exception{
private static final long serialVersionUID = 7039039961721642766L;
public AmbiguousConfigurationException(String msg, Exception nestedEx) {
super(msg, nestedEx);
}
public AmbiguousConfigurationException(String message, Throwable cause) {
super(message, cause);
}
public AmbiguousConfigurationException(String msg) {
super(msg);
}
public AmbiguousConfigurationException() {
super();
}
public AmbiguousConfigurationException(Throwable cause) {
super(cause);
}
}

@ -0,0 +1,111 @@
/*
* 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.
*/
package org.wso2.carbon.device.mgt.common.configuration.mgt;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.List;
/**
* This class is use to wrap and send device configuration data
* to the device
*/
@ApiModel(value = "DeviceConfiguration", description = "This class carries all information related to " +
"Device configurations required to communicate with " +
"the server")
public class DeviceConfiguration {
@ApiModelProperty(name = "deviceId", value = "ID of the device", required = true)
private String deviceId;
@ApiModelProperty(name = "deviceType", value = "Type of the device", required = true)
private String deviceType;
@ApiModelProperty(name = "tenantDomain", value = "Tenant which the device owned")
private String tenantDomain;
@ApiModelProperty(name = "configurationEntries", value = "Platform Configurations", required = true)
private List<ConfigurationEntry> configurationEntries;
@ApiModelProperty(name = "accessToken", value = "Token that can be use to communicate with the server")
private String accessToken;
@ApiModelProperty(name = "refreshToken", value = "Token that can be use to communicate with the server")
private String refreshToken;
@ApiModelProperty(name = "deviceOwner", value = "Owner of the selected device", required = true)
private String deviceOwner;
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getDeviceType() {
return deviceType;
}
public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}
public String getTenantDomain() {
return tenantDomain;
}
public void setTenantDomain(String tenantDomain) {
this.tenantDomain = tenantDomain;
}
public List<ConfigurationEntry> getConfigurationEntries() {
return configurationEntries;
}
public void setConfigurationEntries(
List<ConfigurationEntry> configurationEntries) {
this.configurationEntries = configurationEntries;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public String getDeviceOwner() {
return deviceOwner;
}
public void setDeviceOwner(String deviceOwner) {
this.deviceOwner = deviceOwner;
}
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
}

@ -0,0 +1,63 @@
/*
* 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.
*/
package org.wso2.carbon.device.mgt.common.configuration.mgt;
/**
* This bean is use for retrieve and wrap device property info get from DB
*/
public class DevicePropertyInfo {
private String deviceIdentifier = "default";
private String deviceTypeName = "default";
private String tenantId = "default";
public String getDeviceIdentifier() {
return deviceIdentifier;
}
public void setDeviceIdentifier(String deviceIdentifier) {
this.deviceIdentifier = deviceIdentifier;
}
public String getTenantId() {
return tenantId;
}
public void setTenantId(String tenantId) {
this.tenantId = tenantId;
}
public String getDeviceTypeName() {
return deviceTypeName;
}
public void setDeviceTypeName(String deviceTypeName) {
this.deviceTypeName = deviceTypeName;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof DevicePropertyInfo) {
DevicePropertyInfo devicePropertyInfo = (DevicePropertyInfo)obj;
return devicePropertyInfo.getDeviceIdentifier().equals(this.deviceIdentifier)
&& devicePropertyInfo.getDeviceTypeName().equals(this.deviceTypeName)
&& devicePropertyInfo.getTenantId().equals(this.tenantId);
}
return false;
}
}

@ -27,6 +27,21 @@ public final class DeviceManagementConstants {
public static final String DEVICE_CACHE = "DEVICE_CACHE";
public static final String ENROLLMENT_NOTIFICATION_API_ENDPOINT = "/api/device-mgt/enrollment-notification";
public static final class ConfigurationManagement {
private ConfigurationManagement(){
throw new AssertionError();
}
public static final String ADMIN_CREDENTIALS = "admin:admin";
public static final String SCOPES_FOR_TOKEN = "perm:device:operations perm:device:publish-event";
public static final String IOT_GATEWAY_HOST = "iot.gateway.host";
public static final String IOT_GATEWAY_HTTPS_PORT = "iot.gateway.https.port";
public static final String MQTT_ENDPOINTS = "mqttEndpoints";
public static final String APPLICATION_REGISTRATION_API_ENDPOINT =
"/api-application-registration/register";
public static final String AUTHORIZATION_HEADER = "authorization";
public static final String BASIC_AUTH = "Basic";
}
public static final class Common {
private Common() {
throw new AssertionError();

@ -40,6 +40,7 @@ import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo.Status;
import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.configuration.mgt.DevicePropertyInfo;
import org.wso2.carbon.device.mgt.core.dto.DeviceType;
import org.wso2.carbon.device.mgt.core.geo.GeoCluster;
import org.wso2.carbon.device.mgt.core.geo.geoHash.GeoCoordinate;
@ -190,6 +191,15 @@ public interface DeviceDAO {
*/
List<Device> getDeviceBasedOnDeviceProperties(Map<String, String> deviceProps, int tenantId) throws DeviceManagementDAOException;
/**
* Retrieves a list of devices based on a given criteria of properties
* This will ignores the tenant and it will return devices registered under every tenants
* @param deviceProps properties by which devices need to be filtered
* @return list of devices with properties
* @throws DeviceManagementDAOException if the SQL query has failed to be executed
*/
List<DevicePropertyInfo> getDeviceBasedOnDeviceProperties(Map<String, String> deviceProps)
throws DeviceManagementDAOException;
/**
* Retrieves properties of given device identifier
@ -277,6 +287,17 @@ public interface DeviceDAO {
*/
List<Device> getDevices(PaginationRequest request, int tenantId) throws DeviceManagementDAOException;
/**
* This method is used to search for devices within a specific group.
*
* @param request PaginationRequest object holding the data for pagination
* @param tenantId tenant id.
* @return returns paginated list of devices.
* @throws DeviceManagementDAOException
*/
List<Device> searchDevicesInGroup(PaginationRequest request, int tenantId) throws DeviceManagementDAOException;
/**
* This method is used to retrieve all the devices of a given tenant and device type.
*
@ -498,7 +519,8 @@ public interface DeviceDAO {
* @throws DeviceManagementDAOException throws {@link DeviceManagementDAOException} if connections establishment
* fails.
*/
List<Device> getDevicesByIdentifiers(List<String> deviceIdentifiers, int tenantId) throws DeviceManagementDAOException;
List<Device> getDevicesByIdentifiers(List<String> deviceIdentifiers, int tenantId)
throws DeviceManagementDAOException;
/**
* This method is used to permanently delete the device and its related details
@ -508,4 +530,3 @@ public interface DeviceDAO {
*/
void deleteDevice(DeviceIdentifier deviceIdentifier, int tenantId) throws DeviceManagementDAOException;
}

@ -0,0 +1,28 @@
package org.wso2.carbon.device.mgt.core.dao;
/**
* Throws if the querying device is not found in the DB
*/
public class DeviceNotFoundDAOException extends Exception {
private static final long serialVersionUID = 2126172787830234694L;
public DeviceNotFoundDAOException(String msg, Exception nestedEx) {
super(msg, nestedEx);
}
public DeviceNotFoundDAOException(String message, Throwable cause) {
super(message, cause);
}
public DeviceNotFoundDAOException(String msg) {
super(msg);
}
public DeviceNotFoundDAOException() {
super();
}
public DeviceNotFoundDAOException(Throwable cause) {
super(cause);
}
}

@ -42,6 +42,7 @@ import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo.Status;
import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.configuration.mgt.DevicePropertyInfo;
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.DeviceManagementDAOFactory;
@ -62,6 +63,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import java.util.concurrent.atomic.AtomicInteger;
public abstract class AbstractDeviceDAOImpl implements DeviceDAO {
@ -71,6 +73,7 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO {
private static final String PROPERTY_VALUE_COLUMN_NAME = "PROPERTY_VALUE";
private static final String PROPERTY_DEVICE_TYPE_NAME = "DEVICE_TYPE_NAME";
private static final String PROPERTY_DEVICE_IDENTIFICATION = "DEVICE_IDENTIFICATION";
private static final String PROPERTY_TENANT_ID = "TENANT_ID";
@Override
public int addDevice(int typeId, Device device, int tenantId) throws DeviceManagementDAOException {
@ -330,6 +333,65 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO {
return devices;
}
@Override
public List<DevicePropertyInfo> getDeviceBasedOnDeviceProperties(Map<String, String> deviceProps)
throws DeviceManagementDAOException {
Connection conn;
PreparedStatement stmt = null;
ResultSet resultSet = null;
List<DevicePropertyInfo> deviceProperties = new ArrayList<>();
try {
conn = this.getConnection();
List<List<DevicePropertyInfo>> outputLists = new ArrayList<>();
String sql = "SELECT " +
"p.DEVICE_IDENTIFICATION, " +
"p.DEVICE_TYPE_NAME, " +
"p.TENANT_ID FROM " +
"DM_DEVICE_PROPERTIES p ";
String groupByClause = "GROUP BY " +
"p.DEVICE_IDENTIFICATION, " +
"p.DEVICE_TYPE_NAME, " +
"p.TENANT_ID";
int iterationCount = 0;
StringBuilder propertyQuery = new StringBuilder(" ");
for (Map.Entry<String, String> stringStringEntry : deviceProps.entrySet()) {
String tempTableId = "t".concat(Integer.toString(iterationCount++));
propertyQuery.append("JOIN DM_DEVICE_PROPERTIES ")
.append(tempTableId).append(" ").append("ON p.DEVICE_IDENTIFICATION = ")
.append(tempTableId).append(".DEVICE_IDENTIFICATION ")
.append("AND ")
.append(tempTableId).append(".PROPERTY_NAME = ? ")
.append("AND ")
.append(tempTableId).append(".PROPERTY_VALUE = ? ");
}
sql = sql.concat(propertyQuery.toString()).concat(groupByClause);
stmt = conn.prepareStatement(sql);
int index = 1;
for (Map.Entry<String, String> entry : deviceProps.entrySet()) {
stmt.setString(index++, entry.getKey());
stmt.setString(index++, entry.getValue());
}
resultSet = stmt.executeQuery();
while (resultSet.next()) {
DevicePropertyInfo devicePropertyInfo = new DevicePropertyInfo();
devicePropertyInfo
.setDeviceIdentifier(resultSet.getString(PROPERTY_DEVICE_IDENTIFICATION));
devicePropertyInfo.setTenantId(resultSet.getString(PROPERTY_TENANT_ID));
devicePropertyInfo.setDeviceTypeName(resultSet.getString(PROPERTY_DEVICE_TYPE_NAME));
deviceProperties.add(devicePropertyInfo);
}
return deviceProperties;
} catch (SQLException e) {
String msg = "Error occurred while fetching devices against criteria : '" + deviceProps;
log.error(msg, e);
throw new DeviceManagementDAOException(msg, e);
} finally {
DeviceManagementDAOUtil.cleanupResources(stmt, resultSet);
}
}
@Override
public Device getDeviceProps(String deviceId, int tenantId) throws DeviceManagementDAOException {
Connection conn = null;
@ -385,7 +447,6 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO {
return intersectedResult;
}
@Override
public Device getDevice(String deviceIdentifier, Date since, int tenantId)
throws DeviceManagementDAOException {
@ -1507,8 +1568,8 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO {
}
return devices;
} catch (SQLException e) {
throw new DeviceManagementDAOException("Error occurred while obtaining the DB connection when adding tags",
e);
throw new DeviceManagementDAOException("Error occurred while obtaining the DB connection to get devices for"
+ " given device identifiers.", e);
}
}

@ -369,7 +369,11 @@ public class EnrollmentDAOImpl implements EnrollmentDAO {
try {
Connection conn = this.getConnection();
boolean updateStatus = true;
String sql = "UPDATE DM_ENROLMENT SET OWNER = ? WHERE ID = ? AND TENANT_ID = ?";
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) {
@ -381,6 +385,7 @@ public class EnrollmentDAOImpl implements EnrollmentDAO {
for (int i : ps.executeBatch()) {
if (i == 0 || i == Statement.SUCCESS_NO_INFO || i == Statement.EXECUTE_FAILED) {
updateStatus = false;
break;
}
}
} else {
@ -390,14 +395,15 @@ public class EnrollmentDAOImpl implements EnrollmentDAO {
ps.setInt(3, tenantId);
if (ps.executeUpdate() == 0) {
updateStatus = false;
break;
}
}
}
}
return updateStatus;
} catch (SQLException e) {
throw new DeviceManagementDAOException("Error occurred while obtaining the DB connection when adding tags",
e);
throw new DeviceManagementDAOException("Error occurred while obtaining the DB connection to update the "
+ "owner of the device enrollment.", e);
}
}

@ -153,6 +153,137 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl {
return devices;
}
@Override
public List<Device> searchDevicesInGroup(PaginationRequest request, int tenantId)
throws DeviceManagementDAOException {
Connection conn;
PreparedStatement stmt = null;
ResultSet rs = null;
List<Device> devices = null;
int groupId = request.getGroupId();
String deviceType = request.getDeviceType();
boolean isDeviceTypeProvided = false;
String deviceName = request.getDeviceName();
boolean isDeviceNameProvided = false;
String owner = request.getOwner();
boolean isOwnerProvided = false;
String ownerPattern = request.getOwnerPattern();
boolean isOwnerPatternProvided = false;
String ownership = request.getOwnership();
boolean isOwnershipProvided = false;
String status = request.getStatus();
boolean isStatusProvided = false;
Date since = request.getSince();
boolean isSinceProvided = false;
try {
conn = this.getConnection();
String sql = "SELECT d1.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 gd.DEVICE_ID, gd.DESCRIPTION, gd.NAME, gd.DEVICE_IDENTIFICATION, t.NAME AS DEVICE_TYPE " +
"FROM (SELECT d.ID AS DEVICE_ID, d.DESCRIPTION, d.NAME, d.DEVICE_IDENTIFICATION, d.DEVICE_TYPE_ID " +
"FROM DM_DEVICE d, (SELECT dgm.DEVICE_ID FROM DM_DEVICE_GROUP_MAP dgm WHERE dgm.GROUP_ID = ?) dgm1 WHERE" +
" d.ID = dgm1.DEVICE_ID AND d.TENANT_ID = ?";
//Add the query for device-name
if (deviceName != null && !deviceName.isEmpty()) {
sql = sql + " AND d.NAME LIKE ?";
isDeviceNameProvided = true;
}
sql = sql + ") gd, DM_DEVICE_TYPE t";
if (since != null) {
sql = sql + ", DM_DEVICE_DETAIL dt";
isSinceProvided = true;
}
sql = sql + " WHERE gd.DEVICE_TYPE_ID = t.ID";
//Add query for last updated timestamp
if (isSinceProvided) {
sql = sql + " AND dt.DEVICE_ID = gd.DEVICE_ID AND dt.UPDATE_TIMESTAMP > ?";
}
//Add the query for device-type
if (deviceType != null && !deviceType.isEmpty()) {
sql = sql + " AND t.NAME = ?";
isDeviceTypeProvided = true;
}
sql = sql + " ) d1 WHERE d1.DEVICE_ID = e.DEVICE_ID AND TENANT_ID = ? ";
//Add the query for ownership
if (ownership != null && !ownership.isEmpty()) {
sql = sql + " AND e.OWNERSHIP = ?";
isOwnershipProvided = true;
}
//Add the query for owner
if (owner != null && !owner.isEmpty()) {
sql = sql + " AND e.OWNER = ?";
isOwnerProvided = true;
} else if (ownerPattern != null && !ownerPattern.isEmpty()) {
sql = sql + " AND e.OWNER LIKE ?";
isOwnerPatternProvided = true;
}
//Add the query for status
if (status != null && !status.isEmpty()) {
sql = sql + " AND e.STATUS = ?";
isStatusProvided = true;
}
sql = sql + " LIMIT ?,?";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, groupId);
stmt.setInt(2, tenantId);
int paramIdx = 3;
if (isDeviceNameProvided) {
stmt.setString(paramIdx++, deviceName + "%");
}
if (isSinceProvided) {
stmt.setLong(paramIdx++, since.getTime());
}
if (isDeviceTypeProvided) {
stmt.setString(paramIdx++, deviceType);
}
stmt.setInt(paramIdx++, tenantId);
if (isOwnershipProvided) {
stmt.setString(paramIdx++, ownership);
}
if (isOwnerProvided) {
stmt.setString(paramIdx++, owner);
} else if (isOwnerPatternProvided) {
stmt.setString(paramIdx++, ownerPattern + "%");
}
if (isStatusProvided) {
stmt.setString(paramIdx++, status);
}
stmt.setInt(paramIdx++, request.getStartIndex());
stmt.setInt(paramIdx, request.getRowCount());
rs = stmt.executeQuery();
devices = new ArrayList<>();
while (rs.next()) {
Device device = DeviceManagementDAOUtil.loadDevice(rs);
devices.add(device);
}
} catch (SQLException e) {
throw new DeviceManagementDAOException("Error occurred while retrieving information of" +
" devices belonging to group : " + groupId, e);
} finally {
DeviceManagementDAOUtil.cleanupResources(stmt, rs);
}
return devices;
}
@Override
public List<Device> getDevicesOfUser(PaginationRequest request, int tenantId)
throws DeviceManagementDAOException {

@ -159,6 +159,137 @@ public class OracleDeviceDAOImpl extends AbstractDeviceDAOImpl {
return devices;
}
@Override
public List<Device> searchDevicesInGroup(PaginationRequest request, int tenantId)
throws DeviceManagementDAOException {
Connection conn;
PreparedStatement stmt = null;
ResultSet rs = null;
List<Device> devices = null;
int groupId = request.getGroupId();
String deviceType = request.getDeviceType();
boolean isDeviceTypeProvided = false;
String deviceName = request.getDeviceName();
boolean isDeviceNameProvided = false;
String owner = request.getOwner();
boolean isOwnerProvided = false;
String ownerPattern = request.getOwnerPattern();
boolean isOwnerPatternProvided = false;
String ownership = request.getOwnership();
boolean isOwnershipProvided = false;
String status = request.getStatus();
boolean isStatusProvided = false;
Date since = request.getSince();
boolean isSinceProvided = false;
try {
conn = this.getConnection();
String sql = "SELECT d1.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 gd.DEVICE_ID, gd.DESCRIPTION, gd.NAME, gd.DEVICE_IDENTIFICATION, t.NAME AS DEVICE_TYPE " +
"FROM (SELECT d.ID AS DEVICE_ID, d.DESCRIPTION, d.NAME, d.DEVICE_IDENTIFICATION, d.DEVICE_TYPE_ID " +
"FROM DM_DEVICE d, (SELECT dgm.DEVICE_ID FROM DM_DEVICE_GROUP_MAP dgm WHERE dgm.GROUP_ID = ?) dgm1 WHERE" +
" d.ID = dgm1.DEVICE_ID AND d.TENANT_ID = ?";
//Add the query for device-name
if (deviceName != null && !deviceName.isEmpty()) {
sql = sql + " AND d.NAME LIKE ?";
isDeviceNameProvided = true;
}
sql = sql + ") gd, DM_DEVICE_TYPE t";
if (since != null) {
sql = sql + ", DM_DEVICE_DETAIL dt";
isSinceProvided = true;
}
sql = sql + " WHERE gd.DEVICE_TYPE_ID = t.ID";
//Add query for last updated timestamp
if (isSinceProvided) {
sql = sql + " AND dt.DEVICE_ID = gd.DEVICE_ID AND dt.UPDATE_TIMESTAMP > ?";
}
//Add the query for device-type
if (deviceType != null && !deviceType.isEmpty()) {
sql = sql + " AND t.NAME = ?";
isDeviceTypeProvided = true;
}
sql = sql + " ) d1 WHERE d1.DEVICE_ID = e.DEVICE_ID AND TENANT_ID = ? ";
//Add the query for ownership
if (ownership != null && !ownership.isEmpty()) {
sql = sql + " AND e.OWNERSHIP = ?";
isOwnershipProvided = true;
}
//Add the query for owner
if (owner != null && !owner.isEmpty()) {
sql = sql + " AND e.OWNER = ?";
isOwnerProvided = true;
} else if (ownerPattern != null && !ownerPattern.isEmpty()) {
sql = sql + " AND e.OWNER LIKE ?";
isOwnerPatternProvided = true;
}
//Add the query for status
if (status != null && !status.isEmpty()) {
sql = sql + " AND e.STATUS = ?";
isStatusProvided = true;
}
sql = sql + " ORDER BY ENROLMENT_ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, groupId);
stmt.setInt(2, tenantId);
int paramIdx = 3;
if (isDeviceNameProvided) {
stmt.setString(paramIdx++, deviceName + "%");
}
if (isSinceProvided) {
stmt.setLong(paramIdx++, since.getTime());
}
if (isDeviceTypeProvided) {
stmt.setString(paramIdx++, deviceType);
}
stmt.setInt(paramIdx++, tenantId);
if (isOwnershipProvided) {
stmt.setString(paramIdx++, ownership);
}
if (isOwnerProvided) {
stmt.setString(paramIdx++, owner);
} else if (isOwnerPatternProvided) {
stmt.setString(paramIdx++, ownerPattern + "%");
}
if (isStatusProvided) {
stmt.setString(paramIdx++, status);
}
stmt.setInt(paramIdx++, request.getStartIndex());
stmt.setInt(paramIdx, request.getRowCount());
rs = stmt.executeQuery();
devices = new ArrayList<>();
while (rs.next()) {
Device device = DeviceManagementDAOUtil.loadDevice(rs);
devices.add(device);
}
} catch (SQLException e) {
throw new DeviceManagementDAOException("Error occurred while retrieving information of" +
" devices belonging to group : " + groupId, e);
} finally {
DeviceManagementDAOUtil.cleanupResources(stmt, rs);
}
return devices;
}
@Override
public List<Device> getDevicesOfUser(PaginationRequest request, int tenantId)
throws DeviceManagementDAOException {

@ -140,6 +140,136 @@ public class PostgreSQLDeviceDAOImpl extends AbstractDeviceDAOImpl {
return devices;
}
@Override
public List<Device> searchDevicesInGroup(PaginationRequest request, int tenantId)
throws DeviceManagementDAOException {
Connection conn;
PreparedStatement stmt = null;
ResultSet rs = null;
List<Device> devices = null;
int groupId = request.getGroupId();
String deviceType = request.getDeviceType();
boolean isDeviceTypeProvided = false;
String deviceName = request.getDeviceName();
boolean isDeviceNameProvided = false;
String owner = request.getOwner();
boolean isOwnerProvided = false;
String ownerPattern = request.getOwnerPattern();
boolean isOwnerPatternProvided = false;
String ownership = request.getOwnership();
boolean isOwnershipProvided = false;
String status = request.getStatus();
boolean isStatusProvided = false;
Date since = request.getSince();
boolean isSinceProvided = false;
try {
conn = this.getConnection();
String sql = "SELECT d1.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 gd.DEVICE_ID, gd.DESCRIPTION, gd.NAME, gd.DEVICE_IDENTIFICATION, t.NAME AS DEVICE_TYPE " +
"FROM (SELECT d.ID AS DEVICE_ID, d.DESCRIPTION, d.NAME, d.DEVICE_IDENTIFICATION, d.DEVICE_TYPE_ID " +
"FROM DM_DEVICE d, (SELECT dgm.DEVICE_ID FROM DM_DEVICE_GROUP_MAP dgm WHERE dgm.GROUP_ID = ?) dgm1 WHERE" +
" d.ID = dgm1.DEVICE_ID AND d.TENANT_ID = ?";
//Add the query for device-name
if (deviceName != null && !deviceName.isEmpty()) {
sql = sql + " AND d.NAME LIKE ?";
isDeviceNameProvided = true;
}
sql = sql + ") gd, DM_DEVICE_TYPE t";
if (since != null) {
sql = sql + ", DM_DEVICE_DETAIL dt";
isSinceProvided = true;
}
sql = sql + " WHERE gd.DEVICE_TYPE_ID = t.ID";
//Add query for last updated timestamp
if (isSinceProvided) {
sql = sql + " AND dt.DEVICE_ID = gd.DEVICE_ID AND dt.UPDATE_TIMESTAMP > ?";
}
//Add the query for device-type
if (deviceType != null && !deviceType.isEmpty()) {
sql = sql + " AND t.NAME = ?";
isDeviceTypeProvided = true;
}
sql = sql + " ) d1 WHERE d1.DEVICE_ID = e.DEVICE_ID AND TENANT_ID = ? ";
//Add the query for ownership
if (ownership != null && !ownership.isEmpty()) {
sql = sql + " AND e.OWNERSHIP = ?";
isOwnershipProvided = true;
}
//Add the query for owner
if (owner != null && !owner.isEmpty()) {
sql = sql + " AND e.OWNER = ?";
isOwnerProvided = true;
} else if (ownerPattern != null && !ownerPattern.isEmpty()) {
sql = sql + " AND e.OWNER LIKE ?";
isOwnerPatternProvided = true;
}
//Add the query for status
if (status != null && !status.isEmpty()) {
sql = sql + " AND e.STATUS = ?";
isStatusProvided = true;
}
sql = sql + " LIMIT ? OFFSET ?";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, groupId);
stmt.setInt(2, tenantId);
int paramIdx = 3;
if (isDeviceNameProvided) {
stmt.setString(paramIdx++, deviceName + "%");
}
if (isSinceProvided) {
stmt.setLong(paramIdx++, since.getTime());
}
if (isDeviceTypeProvided) {
stmt.setString(paramIdx++, deviceType);
}
stmt.setInt(paramIdx++, tenantId);
if (isOwnershipProvided) {
stmt.setString(paramIdx++, ownership);
}
if (isOwnerProvided) {
stmt.setString(paramIdx++, owner);
} else if (isOwnerPatternProvided) {
stmt.setString(paramIdx++, ownerPattern + "%");
}
if (isStatusProvided) {
stmt.setString(paramIdx++, status);
}
stmt.setInt(paramIdx, request.getRowCount());
stmt.setInt(paramIdx++, request.getStartIndex());
rs = stmt.executeQuery();
devices = new ArrayList<>();
while (rs.next()) {
Device device = DeviceManagementDAOUtil.loadDevice(rs);
devices.add(device);
}
} catch (SQLException e) {
throw new DeviceManagementDAOException("Error occurred while retrieving information of" +
" devices belonging to group : " + groupId, e);
} finally {
DeviceManagementDAOUtil.cleanupResources(stmt, rs);
}
return devices;
}
@Override
public List<Device> getDevicesOfUser(PaginationRequest request, int tenantId)
throws DeviceManagementDAOException {

@ -156,6 +156,136 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl {
return devices;
}
@Override
public List<Device> searchDevicesInGroup(PaginationRequest request, int tenantId)
throws DeviceManagementDAOException {
Connection conn;
PreparedStatement stmt = null;
ResultSet rs = null;
List<Device> devices = null;
int groupId = request.getGroupId();
String deviceType = request.getDeviceType();
boolean isDeviceTypeProvided = false;
String deviceName = request.getDeviceName();
boolean isDeviceNameProvided = false;
String owner = request.getOwner();
boolean isOwnerProvided = false;
String ownerPattern = request.getOwnerPattern();
boolean isOwnerPatternProvided = false;
String ownership = request.getOwnership();
boolean isOwnershipProvided = false;
String status = request.getStatus();
boolean isStatusProvided = false;
Date since = request.getSince();
boolean isSinceProvided = false;
try {
conn = this.getConnection();
String sql = "SELECT d1.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 gd.DEVICE_ID, gd.DESCRIPTION, gd.NAME, gd.DEVICE_IDENTIFICATION, t.NAME AS DEVICE_TYPE " +
"FROM (SELECT d.ID AS DEVICE_ID, d.DESCRIPTION, d.NAME, d.DEVICE_IDENTIFICATION, d.DEVICE_TYPE_ID " +
"FROM DM_DEVICE d, (SELECT dgm.DEVICE_ID FROM DM_DEVICE_GROUP_MAP dgm WHERE dgm.GROUP_ID = ?) dgm1 WHERE" +
" d.ID = dgm1.DEVICE_ID AND d.TENANT_ID = ?";
//Add the query for device-name
if (deviceName != null && !deviceName.isEmpty()) {
sql = sql + " AND d.NAME LIKE ?";
isDeviceNameProvided = true;
}
sql = sql + ") gd, DM_DEVICE_TYPE t";
if (since != null) {
sql = sql + ", DM_DEVICE_DETAIL dt";
isSinceProvided = true;
}
sql = sql + " WHERE gd.DEVICE_TYPE_ID = t.ID";
//Add query for last updated timestamp
if (isSinceProvided) {
sql = sql + " AND dt.DEVICE_ID = gd.DEVICE_ID AND dt.UPDATE_TIMESTAMP > ?";
}
//Add the query for device-type
if (deviceType != null && !deviceType.isEmpty()) {
sql = sql + " AND t.NAME = ?";
isDeviceTypeProvided = true;
}
sql = sql + " ) d1 WHERE d1.DEVICE_ID = e.DEVICE_ID AND TENANT_ID = ? ";
//Add the query for ownership
if (ownership != null && !ownership.isEmpty()) {
sql = sql + " AND e.OWNERSHIP = ?";
isOwnershipProvided = true;
}
//Add the query for owner
if (owner != null && !owner.isEmpty()) {
sql = sql + " AND e.OWNER = ?";
isOwnerProvided = true;
} else if (ownerPattern != null && !ownerPattern.isEmpty()) {
sql = sql + " AND e.OWNER LIKE ?";
isOwnerPatternProvided = true;
}
//Add the query for status
if (status != null && !status.isEmpty()) {
sql = sql + " AND e.STATUS = ?";
isStatusProvided = true;
}
sql = sql + " ORDER BY ENROLMENT_ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, groupId);
stmt.setInt(2, tenantId);
int paramIdx = 3;
if (isDeviceNameProvided) {
stmt.setString(paramIdx++, deviceName + "%");
}
if (isSinceProvided) {
stmt.setLong(paramIdx++, since.getTime());
}
if (isDeviceTypeProvided) {
stmt.setString(paramIdx++, deviceType);
}
stmt.setInt(paramIdx++, tenantId);
if (isOwnershipProvided) {
stmt.setString(paramIdx++, ownership);
}
if (isOwnerProvided) {
stmt.setString(paramIdx++, owner);
} else if (isOwnerPatternProvided) {
stmt.setString(paramIdx++, ownerPattern + "%");
}
if (isStatusProvided) {
stmt.setString(paramIdx++, status);
}
stmt.setInt(paramIdx++, request.getStartIndex());
stmt.setInt(paramIdx, request.getRowCount());
rs = stmt.executeQuery();
devices = new ArrayList<>();
while (rs.next()) {
Device device = DeviceManagementDAOUtil.loadDevice(rs);
devices.add(device);
}
} catch (SQLException e) {
throw new DeviceManagementDAOException("Error occurred while retrieving information of" +
" devices belonging to group : " + groupId, e);
} finally {
DeviceManagementDAOUtil.cleanupResources(stmt, rs);
}
return devices;
}
@Override
public List<Device> getDevicesOfUser(PaginationRequest request, int tenantId)
throws DeviceManagementDAOException {

@ -237,6 +237,7 @@ public class OperationManagerImpl implements OperationManager {
}
int operationId = this.lookupOperationDAO(operation).addOperation(operationDto);
operation.setId(operationId);
boolean isScheduled = false;
NotificationStrategy notificationStrategy = getNotificationStrategy();

@ -79,6 +79,10 @@ public class OperationDAOUtil {
dtoOperation.setControl(Operation.Control.valueOf(operation.getControl().toString()));
}
if (operation.getInitiatedBy() != null) {
dtoOperation.setInitiatedBy(operation.getInitiatedBy());
}
return dtoOperation;
}

@ -38,17 +38,22 @@ package org.wso2.carbon.device.mgt.core.service;
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.DeviceNotFoundException;
import org.wso2.carbon.device.mgt.common.DeviceTypeNotFoundException;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.FeatureManager;
import org.wso2.carbon.device.mgt.common.InvalidArgumentException;
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.StartupOperationConfig;
import org.wso2.carbon.device.mgt.common.UnauthorizedDeviceAccessException;
import org.wso2.carbon.device.mgt.common.UserNotFoundException;
import org.wso2.carbon.device.mgt.common.configuration.mgt.AmbiguousConfigurationException;
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManagementException;
import org.wso2.carbon.device.mgt.common.configuration.mgt.DeviceConfiguration;
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration;
import org.wso2.carbon.device.mgt.common.license.mgt.License;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
@ -729,4 +734,19 @@ public interface DeviceManagementProviderService {
boolean updateEnrollment(String owner, List<String> deviceIdentifiers)
throws DeviceManagementException, UserNotFoundException, InvalidDeviceException;
/**
* Retrieves a list of configurations of a specific device
* using the device's properties
* @param propertyMap properties by which devices need to be drawn
* @return list of device configuration
* @throws DeviceManagementException if any service level or DAO level error occurs
* @throws DeviceNotFoundException if there is no any device can found for specified properties
* @throws UnauthorizedDeviceAccessException if the required token property is not found on
* @throws AmbiguousConfigurationException if configuration is ambiguous
* the property payload
*/
DeviceConfiguration getDeviceConfiguration(Map<String, String> propertyMap)
throws DeviceManagementException, DeviceNotFoundException, UnauthorizedDeviceAccessException,
AmbiguousConfigurationException;
}

@ -60,6 +60,7 @@ import org.wso2.carbon.device.mgt.common.DeviceTypeNotFoundException;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.FeatureManager;
import org.wso2.carbon.device.mgt.common.InitialOperationConfig;
import org.wso2.carbon.device.mgt.common.InvalidArgumentException;
import org.wso2.carbon.device.mgt.common.InvalidDeviceException;
import org.wso2.carbon.device.mgt.common.MonitoringOperation;
import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig;
@ -67,9 +68,14 @@ import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.PaginationResult;
import org.wso2.carbon.device.mgt.common.StartupOperationConfig;
import org.wso2.carbon.device.mgt.common.TransactionManagementException;
import org.wso2.carbon.device.mgt.common.UnauthorizedDeviceAccessException;
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.AmbiguousConfigurationException;
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry;
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManagementException;
import org.wso2.carbon.device.mgt.common.configuration.mgt.DeviceConfiguration;
import org.wso2.carbon.device.mgt.common.configuration.mgt.DevicePropertyInfo;
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration;
import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation;
@ -824,7 +830,11 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
} else {
try {
DeviceManagementDAOFactory.openConnection();
allDevices = deviceDAO.getDevices(request, tenantId);
if(request.getGroupId()!=0){
allDevices = deviceDAO.searchDevicesInGroup(request, tenantId);
} else{
allDevices = deviceDAO.getDevices(request, tenantId);
}
count = deviceDAO.getDeviceCount(request, tenantId);
} catch (DeviceManagementDAOException e) {
String msg = "Error occurred while retrieving device list pertaining to the current tenant";
@ -3086,12 +3096,12 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
DeviceManagementDAOFactory.rollbackTransaction();
return false;
} catch (TransactionManagementException e) {
String msg = "Error occurred while initiating transaction";
String msg = "Error occurred while initiating the 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);
log.error(msg, e);
throw new DeviceManagementException(msg, e);
} finally {
DeviceManagementDAOFactory.closeConnection();
@ -3114,7 +3124,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
return owner;
} catch (UserStoreException e) {
String msg = "Error occurred when checking whether owner is exist or not. Owner: " + owner;
log.error(msg);
log.error(msg, e);
throw new DeviceManagementException(msg, e);
}
}
@ -3269,4 +3279,86 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
+ "constructing is failed", e);
}
}
@Override
public DeviceConfiguration getDeviceConfiguration(Map<String, String> deviceProps)
throws DeviceManagementException, DeviceNotFoundException, UnauthorizedDeviceAccessException,
AmbiguousConfigurationException {
if (log.isDebugEnabled()) {
log.debug("Attempting to get device configurations based on properties.");
}
DevicePropertyInfo deviceProperties;
List<DevicePropertyInfo> devicePropertyList;
try {
DeviceManagementDAOFactory.openConnection();
devicePropertyList = deviceDAO.getDeviceBasedOnDeviceProperties(deviceProps);
if (devicePropertyList == null || devicePropertyList.isEmpty()) {
String msg = "Cannot find device for specified properties";
log.info(msg);
throw new DeviceNotFoundException(msg);
}
//In this service, there should be only one device for the specified property values
//If multiple values retrieved, It'll be marked as ambiguous.
if (devicePropertyList.size() > 1) {
String msg = "Device property list contains more than one element";
log.error(msg);
throw new AmbiguousConfigurationException(msg);
}
//Get the only existing value of the list
deviceProperties = devicePropertyList.get(0);
} catch (SQLException e) {
String msg = "Error occurred while opening a connection to the data source";
log.error(msg, e);
throw new DeviceManagementException(msg, e);
} catch (DeviceManagementDAOException e) {
String msg = "Devices configuration retrieval criteria cannot be null or empty.";
log.error(msg);
throw new DeviceManagementException(msg, e);
} finally {
DeviceManagementDAOFactory.closeConnection();
}
try {
Device device = this.getDevice(new DeviceIdentifier(deviceProperties.getDeviceIdentifier(),
deviceProperties.getDeviceTypeName()), false);
String owner = device.getEnrolmentInfo().getOwner();
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
ctx.setTenantId(Integer.parseInt(deviceProperties.getTenantId()), true);
PlatformConfiguration configuration = this.getConfiguration(device.getType());
List<ConfigurationEntry> configurationEntries = new ArrayList<>();
if (configuration != null) {
configurationEntries = configuration.getConfiguration();
}
return wrapConfigurations(device, ctx.getTenantDomain(), configurationEntries, owner);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
/**
* Wrap the device configuration data into DeviceConfiguration bean
* @param device Device queried using the properties
* @param tenantDomain tenant domain
* @param configurationEntries platformConfiguration list
* @param deviceOwner name of the device owner
* @return Wrapped {@link DeviceConfiguration} object with data
*/
private DeviceConfiguration wrapConfigurations(Device device,
String tenantDomain,
List<ConfigurationEntry> configurationEntries,
String deviceOwner) {
DeviceConfiguration deviceConfiguration = new DeviceConfiguration();
deviceConfiguration.setDeviceId(device.getDeviceIdentifier());
deviceConfiguration.setDeviceType(device.getType());
deviceConfiguration.setTenantDomain(tenantDomain);
deviceConfiguration.setConfigurationEntries(configurationEntries);
deviceConfiguration.setDeviceOwner(deviceOwner);
return deviceConfiguration;
}
}

@ -17,13 +17,25 @@
*/
package org.wso2.carbon.device.mgt.core.util;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HTTP;
import org.w3c.dom.Document;
import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.caching.impl.CacheImpl;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.analytics.data.publisher.service.EventsPublisherService;
import org.wso2.carbon.device.mgt.common.AppRegistrationCredentials;
import org.wso2.carbon.device.mgt.common.ApplicationRegistration;
import org.wso2.carbon.device.mgt.common.ApplicationRegistrationException;
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
@ -49,6 +61,10 @@ import org.wso2.carbon.device.mgt.core.dto.DeviceType;
import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder;
import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMgtConstants;
import org.wso2.carbon.device.mgt.core.operation.mgt.util.DeviceIDHolder;
import org.wso2.carbon.identity.jwt.client.extension.JWTClient;
import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo;
import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
import org.wso2.carbon.user.api.TenantManager;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.utils.CarbonUtils;
@ -63,9 +79,13 @@ import javax.sql.DataSource;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
@ -588,4 +608,102 @@ public final class DeviceManagerUtil {
}
return deviceCache;
}
/**
* Create an app and get app registration token from the application registration endpoint
*
* @return AppRegistrationToken object which contains access and refresh tokens
* @throws ApplicationRegistrationException when application fails to connect with the app registration
* endpoint
*/
@SuppressWarnings("PackageAccessibility")
public static AppRegistrationCredentials getApplicationRegistrationCredentials(String host, String port,
String credentials)
throws ApplicationRegistrationException {
if (host == null || port == null) {
String msg = "Required gatewayHost or gatewayPort system property is null";
log.error(msg);
throw new ApplicationRegistrationException(msg);
}
String internalServerAddr = "https://".concat(host).concat(":").concat(port);
try (CloseableHttpClient client = HttpClients.createDefault()) {
HttpPost apiEndpoint = new HttpPost(
internalServerAddr + DeviceManagementConstants.ConfigurationManagement
.APPLICATION_REGISTRATION_API_ENDPOINT);
apiEndpoint.setHeader(HTTP.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString());
apiEndpoint.setHeader(DeviceManagementConstants.ConfigurationManagement.AUTHORIZATION_HEADER,
DeviceManagementConstants.ConfigurationManagement.BASIC_AUTH.concat(" ")
.concat(getBase64EncodedCredentials(credentials)));
apiEndpoint.setEntity(constructApplicationRegistrationPayload());
HttpResponse response = client.execute(apiEndpoint);
if (response != null) {
log.info("Obtained client credentials: " + response.getStatusLine().getStatusCode());
BufferedReader rd = new BufferedReader(
new InputStreamReader(response.getEntity().getContent()));
StringBuilder result = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
result.append(line);
}
return new ObjectMapper().readValue(result.toString(), AppRegistrationCredentials.class);
} else {
String msg = "Response is 'NUll' for the Application Registration API call.";
log.error(msg);
throw new ApplicationRegistrationException(msg);
}
} catch (IOException e) {
throw new ApplicationRegistrationException(
"Error occurred when invoking API. API endpoint: "
+ internalServerAddr + DeviceManagementConstants.ConfigurationManagement
.APPLICATION_REGISTRATION_API_ENDPOINT, e);
}
}
/**
* Use default admin credentials and encode them in Base64
*
* @return Base64 encoded client credentials
*/
private static String getBase64EncodedCredentials(String credentials) {
return Base64.getEncoder().encodeToString(credentials.getBytes());
}
/**
* Create a JSON payload for application registration
*
* @return Generated JSON payload
*/
@SuppressWarnings("PackageAccessibility")
private static StringEntity constructApplicationRegistrationPayload() {
ApplicationRegistration applicationRegistration = new ApplicationRegistration();
applicationRegistration.setApplicationName("MyApp");
applicationRegistration.setAllowedToAllDomains(false);
List<String> tags = new ArrayList<>();
tags.add("device_management");
applicationRegistration.setTags(tags);
applicationRegistration.setValidityPeriod(3600);
Gson gson = new Gson();
String payload = gson.toJson(applicationRegistration);
return new StringEntity(payload, ContentType.APPLICATION_JSON);
}
/**
* Retrieves access token for a given device
* @param scopes scopes for token
* @param clientId clientId
* @param clientSecret clientSecret
* @param deviceOwner owner of the device that is going to generate token
* @return @{@link AccessTokenInfo} wrapped object of retrieved access token and refresh token
* @throws JWTClientException if an error occurs when the jwt client creation or token retrieval
*/
public static AccessTokenInfo getAccessTokenForDeviceOwner(String scopes, String clientId,
String clientSecret, String deviceOwner)
throws JWTClientException {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
JWTClientManagerService jwtClientManagerService = (JWTClientManagerService) ctx
.getOSGiService(JWTClientManagerService.class, null);
JWTClient jwtClient = jwtClientManagerService.getJWTClient();
return jwtClient.getAccessToken(clientId, clientSecret, deviceOwner, scopes);
}
}

@ -34,6 +34,7 @@
*/
package org.wso2.carbon.device.mgt.extensions.device.type.template;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
@ -58,10 +59,12 @@ import org.wso2.carbon.device.mgt.extensions.device.type.template.dao.DeviceDAOD
import org.wso2.carbon.device.mgt.extensions.device.type.template.dao.DeviceTypePluginDAOManager;
import org.wso2.carbon.device.mgt.extensions.device.type.template.exception.DeviceTypeDeployerPayloadException;
import org.wso2.carbon.device.mgt.extensions.device.type.template.exception.DeviceTypeMgtPluginException;
import org.wso2.carbon.device.mgt.extensions.device.type.template.exception.DeviceTypePluginExtensionException;
import org.wso2.carbon.device.mgt.extensions.device.type.template.feature.ConfigurationBasedFeatureManager;
import org.wso2.carbon.device.mgt.extensions.device.type.template.util.DeviceTypePluginConstants;
import org.wso2.carbon.device.mgt.extensions.device.type.template.util.DeviceTypeUtils;
import org.wso2.carbon.device.mgt.extensions.license.mgt.registry.RegistryBasedLicenseManager;
import org.wso2.carbon.device.mgt.extensions.spi.DeviceTypePluginExtensionService;
import org.wso2.carbon.registry.api.RegistryException;
import org.wso2.carbon.registry.api.Resource;
import org.wso2.carbon.utils.CarbonUtils;
@ -213,6 +216,35 @@ public class DeviceTypeManager implements DeviceManager {
}
}
}
setDeviceTypePluginManager();
}
/**
* Set device type plugin DAO manager of each device type in a HashMap which can then be used via individual
* device type plugin in working with its DAO components
*/
private void setDeviceTypePluginManager() {
if (StringUtils.isNotEmpty(deviceType)) {
if (deviceTypePluginDAOManager != null) {
DeviceTypePluginExtensionService deviceTypeManagerExtensionService =
new DeviceTypePluginExtensionServiceImpl();
try {
deviceTypeManagerExtensionService.addPluginDAOManager(deviceType, deviceTypePluginDAOManager);
} catch (DeviceTypePluginExtensionException e) {
String msg = "Error occurred while saving DeviceTypePluginDAOManager for device type: "
+ deviceType;
log.error(msg);
throw new DeviceTypeDeployerPayloadException(msg);
}
} else {
log.warn("Could not save DeviceTypePluginDAOManager for device type: " + deviceType +
" since DeviceTypePluginDAOManager is null.");
}
} else {
String msg = "Could not save DeviceTypePluginDAOManager since device type is null or empty.";
log.error(msg);
throw new DeviceTypeDeployerPayloadException(msg);
}
}
@Override
@ -307,15 +339,11 @@ public class DeviceTypeManager implements DeviceManager {
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().commitTransaction();
}
} catch (DeviceTypeMgtPluginException e) {
try {
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().rollbackTransaction();
} catch (DeviceTypeMgtPluginException ex) {
String msg = "Error occurred while roll back the device enrol transaction :" +
device.toString();
log.warn(msg, ex);
}
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().rollbackTransaction();
String msg = "Error while enrolling the " + deviceType + " device : " + device.getDeviceIdentifier();
throw new DeviceManagementException(msg, e);
} finally {
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().closeConnection();
}
return status;
}
@ -334,16 +362,12 @@ public class DeviceTypeManager implements DeviceManager {
status = deviceTypePluginDAOManager.getDeviceDAO().updateDevice(device);
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().commitTransaction();
} catch (DeviceTypeMgtPluginException e) {
try {
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().rollbackTransaction();
} catch (DeviceTypeMgtPluginException mobileDAOEx) {
String msg = "Error occurred while roll back the update device transaction :" +
device.toString();
log.warn(msg, mobileDAOEx);
}
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().rollbackTransaction();
String msg = "Error while updating the enrollment of the " + deviceType + " device : " +
device.getDeviceIdentifier();
throw new DeviceManagementException(msg, e);
} finally {
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().closeConnection();
}
return status;
}
@ -378,13 +402,7 @@ public class DeviceTypeManager implements DeviceManager {
deviceId.getId();
throw new DeviceManagementException(msg, e);
} finally {
try {
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().closeConnection();
} catch (DeviceTypeMgtPluginException e) {
String msg = "Error occurred while closing the transaction to check device " +
deviceId.getId() + " is enrolled.";
log.warn(msg, e);
}
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().closeConnection();
}
return isEnrolled;
}
@ -419,12 +437,7 @@ public class DeviceTypeManager implements DeviceManager {
throw new DeviceManagementException(
"Error occurred while fetching the " + deviceType + " device: '" + deviceId.getId() + "'", e);
} finally {
try {
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().closeConnection();
} catch (DeviceTypeMgtPluginException e) {
String msg = "Error occurred while closing the transaction to get device " + deviceId.getId();
log.warn(msg, e);
}
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().closeConnection();
}
return device;
}
@ -447,14 +460,11 @@ public class DeviceTypeManager implements DeviceManager {
status = deviceTypePluginDAOManager.getDeviceDAO().updateDevice(updatedDevice);
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().commitTransaction();
} catch (DeviceTypeMgtPluginException e) {
try {
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().rollbackTransaction();
} catch (DeviceTypeMgtPluginException transactionException) {
String msg = "Error occurred while rolling back transaction for device: " + deviceId.getId();
log.warn(msg, transactionException);
}
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().rollbackTransaction();
throw new DeviceManagementException(
"Error occurred while fetching the " + deviceType + " device: '" + deviceId.getId() + "'", e);
} finally {
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().closeConnection();
}
}
return status;
@ -544,15 +554,12 @@ public class DeviceTypeManager implements DeviceManager {
status = deviceTypePluginDAOManager.getDeviceDAO().updateDevice(existingDevice);
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().commitTransaction();
} catch (DeviceTypeMgtPluginException e) {
try {
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().rollbackTransaction();
} catch (DeviceTypeMgtPluginException e1) {
log.warn("Error occurred while roll back the update device info transaction : '" +
device.toString() + "'", e1);
}
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().rollbackTransaction();
throw new DeviceManagementException(
"Error occurred while updating the " + deviceType + " device: '" +
device.getDeviceIdentifier() + "'", e);
} finally {
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().closeConnection();
}
return status;
}
@ -572,12 +579,7 @@ public class DeviceTypeManager implements DeviceManager {
} catch (DeviceTypeMgtPluginException e) {
throw new DeviceManagementException("Error occurred while fetching all " + deviceType + " devices", e);
} finally {
try {
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().closeConnection();
} catch (DeviceTypeMgtPluginException e) {
String msg = "Error occurred while closing the transaction to get all devices.";
log.warn(msg, e);
}
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().closeConnection();
}
return devices;
}
@ -600,15 +602,12 @@ public class DeviceTypeManager implements DeviceManager {
status = deviceTypePluginDAOManager.getDeviceDAO().deleteDevice(existingDevice);
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().commitTransaction();
} catch (DeviceTypeMgtPluginException e) {
try {
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().rollbackTransaction();
} catch (DeviceTypeMgtPluginException e1) {
log.warn("Error occurred while roll back the delete device info transaction : '" +
device.toString() + "'", e1);
}
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().rollbackTransaction();
throw new DeviceManagementException(
"Error occurred while deleting the " + deviceType + " device: '" +
device.getDeviceIdentifier() + "'", e);
} finally {
deviceTypePluginDAOManager.getDeviceTypeDAOHandler().closeConnection();
}
return status;
}

@ -0,0 +1,71 @@
/*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (https://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.extensions.device.type.template;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.extensions.device.type.template.dao.DeviceTypePluginDAOManager;
import org.wso2.carbon.device.mgt.extensions.device.type.template.exception.DeviceTypePluginExtensionException;
import org.wso2.carbon.device.mgt.extensions.spi.DeviceTypePluginExtensionService;
import java.util.HashMap;
import java.util.Map;
public class DeviceTypePluginExtensionServiceImpl implements DeviceTypePluginExtensionService {
private static final Log log = LogFactory.getLog(DeviceTypePluginExtensionServiceImpl.class);
private static volatile Map<String, DeviceTypePluginDAOManager> pluginDAOManagers = new HashMap<>();
@Override
public void addPluginDAOManager(String deviceType, DeviceTypePluginDAOManager pluginDAOManager)
throws DeviceTypePluginExtensionException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
if (pluginDAOManager == null) {
String msg = "Cannot save DeviceTypePluginDAOManager against tenant id " + tenantId
+ " and device type: " + deviceType + " since DeviceTypePluginDAOManager is null";
log.error(msg);
throw new DeviceTypePluginExtensionException(msg);
}
if (!pluginDAOManagers.containsKey(tenantId + deviceType)) {
if (log.isDebugEnabled()) {
log.debug("Saving DeviceTypePluginDAOManager against tenant id " + tenantId +
" and device type: " + deviceType);
}
pluginDAOManagers.put(tenantId + deviceType, pluginDAOManager);
}
}
@Override
public DeviceTypePluginDAOManager getPluginDAOManager(String deviceType) throws DeviceTypePluginExtensionException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
if (pluginDAOManagers.containsKey(tenantId + deviceType)) {
if (log.isDebugEnabled()) {
log.debug("Retrieving DeviceTypePluginDAOManager against tenant id " + tenantId +
" and device type: " + deviceType);
}
return pluginDAOManagers.get(tenantId + deviceType);
} else {
String msg = "DeviceTypePluginDAOManager could not be found against tenant id " + tenantId +
" and device type: " + deviceType;
log.error(msg);
throw new DeviceTypePluginExtensionException(msg);
}
}
}

@ -1,7 +1,25 @@
/*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (https://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.extensions.device.type.template.dao;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.common.IllegalTransactionStateException;
import org.wso2.carbon.device.mgt.extensions.device.type.template.exception.DeviceTypeDeployerPayloadException;
import org.wso2.carbon.device.mgt.extensions.device.type.template.exception.DeviceTypeMgtPluginException;
@ -31,7 +49,26 @@ public class DeviceTypeDAOHandler {
Context ctx = new InitialContext();
dataSource = (DataSource) ctx.lookup(datasourceName);
} catch (NamingException e) {
throw new DeviceTypeDeployerPayloadException("Error while looking up the data source: " + datasourceName, e);
String msg = "Error while looking up the data source: " + datasourceName;
log.error(msg, e);
throw new DeviceTypeDeployerPayloadException(msg, e);
}
}
public void openConnection() throws DeviceTypeMgtPluginException {
try {
Connection conn = currentConnection.get();
if (conn != null) {
String msg = "Database connection has already been obtained.";
log.error(msg);
throw new IllegalTransactionStateException(msg);
}
conn = dataSource.getConnection();
currentConnection.set(conn);
} catch (SQLException e) {
String msg = "Failed to get a database connection.";
log.error(msg, e);
throw new DeviceTypeMgtPluginException(msg, e);
}
}
@ -41,7 +78,9 @@ public class DeviceTypeDAOHandler {
conn.setAutoCommit(false);
currentConnection.set(conn);
} catch (SQLException e) {
throw new DeviceTypeMgtPluginException("Error occurred while retrieving datasource connection", e);
String msg = "Error occurred while retrieving datasource connection";
log.error(msg, e);
throw new DeviceTypeMgtPluginException(msg, e);
}
}
@ -50,58 +89,58 @@ public class DeviceTypeDAOHandler {
try {
currentConnection.set(dataSource.getConnection());
} catch (SQLException e) {
throw new DeviceTypeMgtPluginException("Error occurred while retrieving data source connection", e);
String msg = "Error occurred while retrieving data source connection";
log.error(msg, e);
throw new DeviceTypeMgtPluginException(msg, e);
}
}
return currentConnection.get();
}
public void commitTransaction() throws DeviceTypeMgtPluginException {
public void commitTransaction() {
Connection conn = currentConnection.get();
if (conn == null) {
String msg = "No connection is associated with the current transaction. This might have ideally been " +
"caused by not properly initiating the transaction via " +
"'beginTransaction'/'openConnection' methods";
log.error(msg);
throw new IllegalStateException(msg);
}
try {
Connection conn = currentConnection.get();
if (conn != null) {
conn.commit();
} else {
if (log.isDebugEnabled()) {
log.debug("Datasource connection associated with the current thread is null, hence commit "
+ "has not been attempted");
}
}
conn.commit();
} catch (SQLException e) {
throw new DeviceTypeMgtPluginException("Error occurred while committing the transaction", e);
} finally {
closeConnection();
String msg = "Error occurred while committing the transaction.";
log.error(msg, e);
}
}
public void closeConnection() throws DeviceTypeMgtPluginException {
public void closeConnection() {
Connection con = currentConnection.get();
if (con != null) {
try {
con.close();
} catch (SQLException e) {
log.error("Error occurred while close the connection");
String msg = "Error occurred while close the connection";
log.error(msg, e);
}
}
currentConnection.remove();
}
public void rollbackTransaction() throws DeviceTypeMgtPluginException {
public void rollbackTransaction() {
Connection conn = currentConnection.get();
if (conn == null) {
String msg = "No connection is associated with the current transaction. This might have ideally been " +
"caused by not properly initiating the transaction via " +
"'beginTransaction'/'openConnection' methods";
log.error(msg);
throw new IllegalStateException(msg);
}
try {
Connection conn = currentConnection.get();
if (conn != null) {
conn.rollback();
} else {
if (log.isDebugEnabled()) {
log.debug("Datasource connection associated with the current thread is null, hence rollback "
+ "has not been attempted");
}
}
conn.rollback();
} catch (SQLException e) {
throw new DeviceTypeMgtPluginException("Error occurred while rollback the transaction", e);
} finally {
closeConnection();
String msg = "Error occurred while roll-backing the transaction.";
log.error(msg, e);
}
}
}

@ -0,0 +1,12 @@
package org.wso2.carbon.device.mgt.extensions.device.type.template.exception;
public class DeviceTypePluginExtensionException extends Exception {
public DeviceTypePluginExtensionException(String msg) {
super(msg);
}
public DeviceTypePluginExtensionException(String msg, Throwable cause) {
super(msg, cause);
}
}

@ -14,6 +14,23 @@
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (https://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.extensions.internal;
@ -23,6 +40,8 @@ import org.apache.commons.logging.LogFactory;
import org.osgi.service.component.ComponentContext;
import org.wso2.carbon.device.mgt.common.spi.DeviceTypeGeneratorService;
import org.wso2.carbon.device.mgt.extensions.device.type.template.DeviceTypeGeneratorServiceImpl;
import org.wso2.carbon.device.mgt.extensions.device.type.template.DeviceTypePluginExtensionServiceImpl;
import org.wso2.carbon.device.mgt.extensions.spi.DeviceTypePluginExtensionService;
import org.wso2.carbon.ndatasource.core.DataSourceService;
import org.wso2.carbon.registry.core.service.RegistryService;
@ -50,6 +69,8 @@ public class DeviceTypeExtensionServiceComponent {
}
ctx.getBundleContext()
.registerService(DeviceTypeGeneratorService.class, new DeviceTypeGeneratorServiceImpl(), null);
ctx.getBundleContext().registerService(DeviceTypePluginExtensionService.class,
new DeviceTypePluginExtensionServiceImpl(), null);
if (log.isDebugEnabled()) {
log.debug("Device Type Extension Service Component successfully activated");
}

@ -0,0 +1,45 @@
/*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (https://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.extensions.spi;
import org.wso2.carbon.device.mgt.extensions.device.type.template.dao.DeviceTypePluginDAOManager;
import org.wso2.carbon.device.mgt.extensions.device.type.template.exception.DeviceTypePluginExtensionException;
/**
* This represents the device type plugin extension service which can be used by any device type plugin implementation
* intended to use the same plugin DAO instances to be used with its plugin level DAO components
*/
public interface DeviceTypePluginExtensionService {
/**
* Save device type specific DeviceTypePluginDAOManager in a HashMap againast tenant ID and device type
* @param deviceType - Type of the device (i.e; android, ios, windows)
* @param pluginDAOManager - Device type plugin DAO manager instance to be saved against device type
* @throws DeviceTypePluginExtensionException when pluginDAOManager is null
*/
void addPluginDAOManager(String deviceType, DeviceTypePluginDAOManager pluginDAOManager)
throws DeviceTypePluginExtensionException;
/**
* Retrieve the DeviceTypePluginDAOManager instance against tenant ID and given device type
* @param deviceType - Type of the device (i.e; android, ios, windows)
* @return an Instance of {@link DeviceTypePluginDAOManager}
* @throws DeviceTypePluginExtensionException when pluginDAOManager cannot be found
*/
DeviceTypePluginDAOManager getPluginDAOManager(String deviceType) throws DeviceTypePluginExtensionException;
}

@ -327,15 +327,6 @@ deviceModule = function () {
return response;
};
publicMethods.getDeviceTypesConfig = function () {
var url = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] + "/device-types/config";
var response = privateMethods.callBackend(url, constants["HTTP_GET"]);
if (response.status == "success") {
response.content = parse(response.content);
}
return response;
};
/*
@Updated
*/

@ -506,7 +506,7 @@ function loadDevices(searchType, searchParam) {
$('#device-grid').datatables_extended_serverside_paging(
null,
serviceURL,
"/api/device-mgt/v1.0/devices/",
dataFilter,
columns,
fnCreatedRow,
@ -525,7 +525,8 @@ function loadDevices(searchType, searchParam) {
}, {
"placeholder": "Top-Device-Name-Search",
"searchKey": "namePattern"
"searchKey": "namePattern",
"groupId": groupId
}
);

@ -35,7 +35,7 @@ function onRequest(context) {
var deviceType = request.getParameter("type");
var serviceInvokers = require("/app/modules/oauth/token-protected-service-invokers.js")["invokers"];
var restAPIEndpoint = deviceMgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"]
+ "/device-types/config/" + deviceType;
+ "/device-types/" + deviceType;
displayData.name = deviceType;
serviceInvokers.XMLHttp.get(
restAPIEndpoint,

@ -210,7 +210,7 @@ $(document).ready(function () {
});
deviceType.deviceTypeMetaDefinition.features = features;
var addRoleAPI = apiBasePath + "/admin/device-types";
var addRoleAPI = apiBasePath + "/admin/device-types/" + deviceType.name;
invokerUtil.put(
addRoleAPI,

@ -76,6 +76,9 @@ $.fn.datatables_extended_serverside_paging = function (settings, url, dataFilter
searchParams[params.columns[i].data] = encodeURIComponent(params.columns[i].search.value);
}
if (options) {
if (options.groupId){
searchParams["groupId"] = options.groupId;
}
searchParams[options.searchKey] = encodeURIComponent(params.search.value);
}
params.filter = JSON.stringify(searchParams);

@ -42,7 +42,7 @@ function onRequest(context) {
var displayData = {};
var restAPIEndpoint = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"]
+ "/device-types/config/" + deviceType;
+ "/device-types/" + deviceType;
displayData.deviceType = deviceType;
displayData.tenantDomain = tenantDomain;
serviceInvokers.XMLHttp.get(

@ -32,7 +32,7 @@ function onRequest(context) {
return opts.inverse(this);
});
var restAPIEndpoint = deviceMgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"]
+ "/device-types/config/" + deviceType;
+ "/device-types/" + deviceType;
displayData.deviceType = deviceType;
displayData.tenantDomain = tenantDomain;
serviceInvokers.XMLHttp.get(

@ -2401,7 +2401,7 @@ a.list-group-item:hover {
}
.tree-view li > .icon {
font-family: "font-wso2";
font-family: "font-entgra";
font-style: normal;
background: #2c313b;
color: #ffffff;
@ -2686,7 +2686,7 @@ a.list-group-item:hover {
text-align: center;
background: #2c313b;
color: #fff;
font-family: font-wso2;
font-family: font-entgra;
}
.checkbox > input[type=checkbox]:not(:checked) + .helper:after {
@ -4433,7 +4433,7 @@ a.wr-side-panel-toggle-btn.selected {
text-align: center;
background: #008cc4;
color: #fff;
font-family: font-wso2;
font-family: font-entgra;
}
.wr-input-control.checkbox input[type="checkbox"]:not(:checked) + .helper:after {
@ -6624,7 +6624,7 @@ ul.tiles .icon {
}
.tree-view li > .icon {
font-family: 'font-wso2';
font-family: 'font-entgra';
font-style: normal;
background: #2c313b;
color: #ffffff;

@ -8053,7 +8053,7 @@ a.list-group-item:hover {
}
.tree-view li > .icon {
font-family: "font-wso2";
font-family: "font-entgra";
font-style: normal;
background: #008cc4;
color: #ffffff;
@ -8295,7 +8295,7 @@ a.list-group-item:hover {
text-align: center;
background: #004675;
color: #fff;
font-family: font-wso2;
font-family: font-entgra;
}
.checkbox > input[type=checkbox]:not(:checked) + .helper:after {
display: none;

@ -1,5 +1,5 @@
/*!
~ Copyright (c) WSO2 Inc. (http://wso2.com) All Rights Reserved.
~ Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
@ -16,20 +16,20 @@
@font-face {
font-family:"font-wso2";
src:local("font-wso2"), url("../fonts/font-wso2.eot?6563fa91278f239ef8c827d90a165223");
src:local("font-wso2"),
url("../fonts/font-wso2.eot?#iefix") format("embedded-opentype"),
url("../fonts/font-wso2.woff2?6563fa91278f239ef8c827d90a165223") format("woff2"),
url("../fonts/font-wso2.woff?6563fa91278f239ef8c827d90a165223") format("woff"),
url("../fonts/font-wso2.ttf?6563fa91278f239ef8c827d90a165223") format("truetype"),
url("../fonts/font-wso2.svg?6563fa91278f239ef8c827d90a165223#font-wso2") format("svg");
font-family:"font-entgra";
src:local("font-entgra"), url("../fonts/font-entgra.eot?3990d6a2bf7b820a842f9dc0774c990e");
src:local("font-entgra"),
url("../fonts/font-entgra.eot?3990d6a2bf7b820a842f9dc0774c990e#iefix") format("embedded-opentype"),
url("../fonts/font-entgra.woff2?3990d6a2bf7b820a842f9dc0774c990e") format("woff2"),
url("../fonts/font-entgra.woff?3990d6a2bf7b820a842f9dc0774c990e") format("woff"),
url("../fonts/font-entgra.ttf?3990d6a2bf7b820a842f9dc0774c990e") format("truetype"),
url("../fonts/font-entgra.svg?3990d6a2bf7b820a842f9dc0774c990e#font-entgra") format("svg");
font-weight:normal;
font-style:normal;
}
.fw, [class^="fw-"], [class*=" fw-"] {
font: normal normal normal 14px/1 font-wso2;
font: normal normal normal 14px/1 font-entgra;
display: inline-block;
font-weight: normal;
font-style: normal;
@ -304,10 +304,18 @@
content:"\e6cf";
}
.fw-activesync:before {
content:"\e745";
}
.fw-add:before {
content:"\e615";
}
.fw-aggregate:before {
content:"\e742";
}
.fw-airplay:before {
content:"\e600";
}
@ -348,7 +356,7 @@
content:"\e602";
}
.fw-ios:before {
.fw-apple:before {
content:"\e604";
}
@ -380,6 +388,10 @@
content:"\e60a";
}
.fw-bean:before {
content:"\e743";
}
.fw-blank-document:before {
content:"\e60c";
}
@ -416,6 +428,10 @@
content:"\e612";
}
.fw-call-mediator:before {
content:"\e736";
}
.fw-camera:before {
content:"\e613";
}
@ -480,7 +496,7 @@
content:"\e653";
}
.fw-configarations:before {
.fw-configurations:before {
content:"\e609";
}
@ -500,6 +516,10 @@
content:"\e620";
}
.fw-continue:before {
content:"\e73e";
}
.fw-contract:before {
content:"\e614";
}
@ -516,6 +536,10 @@
content:"\e622";
}
.fw-data-mapper:before {
content:"\e735";
}
.fw-database:before {
content:"\e623";
}
@ -628,6 +652,10 @@
content:"\e628";
}
.fw-dollar:before {
content:"\e741";
}
.fw-down-arrow:before {
content:"\e689";
}
@ -672,6 +700,10 @@
content:"\e6e3";
}
.fw-event-simulator:before {
content:"\e744";
}
.fw-expand:before {
content:"\e61c";
}
@ -716,6 +748,10 @@
content:"\e62e";
}
.fw-foreach:before {
content:"\e73ab";
}
.fw-fork-join:before {
content:"\e720";
}
@ -764,6 +800,10 @@
content:"\e6da";
}
.fw-google-glass:before {
content:"\e732";
}
.fw-google-plus:before {
content:"\e6d9";
}
@ -800,6 +840,10 @@
content:"\e639";
}
.fw-header:before {
content:"\e734";
}
.fw-heart:before {
content:"\e6c3";
}
@ -832,6 +876,10 @@
content:"\e63c";
}
.fw-in-sequence:before {
content:"\e739";
}
.fw-incoming-call:before {
content:"\e63d";
}
@ -844,6 +892,10 @@
content:"\e6db";
}
.fw-integration:before {
content:"\e73f";
}
.fw-invitation:before {
content:"\e63f";
}
@ -896,6 +948,10 @@
content:"\e647";
}
.fw-kiosk:before {
content:"\e746";
}
.fw-laptop:before {
content:"\e648";
}
@ -960,6 +1016,10 @@
content:"\e64e";
}
.fw-log:before {
content:"\e738";
}
.fw-logical:before {
content:"\e702";
}
@ -976,6 +1036,10 @@
content:"\e650";
}
.fw-mapping:before {
content:"\e73c";
}
.fw-menu:before {
content:"\e651";
}
@ -1004,6 +1068,10 @@
content:"\e655";
}
.fw-namespace:before {
content:"\e740";
}
.fw-nodejs:before {
content:"\e656";
}
@ -1016,6 +1084,10 @@
content:"\e6ac";
}
.fw-out-sequence:before {
content:"\e73a";
}
.fw-own:before {
content:"\e6c8";
}
@ -1032,6 +1104,10 @@
content:"\e658";
}
.fw-payload-factory:before {
content:"\e733";
}
.fw-pdf:before {
content:"\e659";
}
@ -1060,6 +1136,10 @@
content:"\e70d";
}
.fw-property:before {
content:"\e737";
}
.fw-prototype:before {
content:"\e6cc";
}
@ -1088,6 +1168,10 @@
content:"\e65d";
}
.fw-reduce:before {
content:"\e73d";
}
.fw-refresh:before {
content:"\e692";
}

@ -21,7 +21,7 @@
@font-face {.font( 'Roboto'; 300; 'normal'; 'Roboto Light'; 'Roboto-Light-webfont'; '../fonts' )}
@font-default: 'Roboto Light', Arial, Helvetica, sans-serif;
@font-icons: 'font-wso2';
@font-icons: 'font-entgra';
@font-default-weight: 300;
@border-radius-default: 0;
@box-shadow-default: none;

@ -23,7 +23,7 @@
<!-- Font Awesome CSS -->
{{~css "lib/font-awesome_4.3.0/css/font-awesome.min.css" combine=false}}
<!-- Font WSO2 CSS -->
{{~css "lib/font-wso2-1.3.0/css/font-wso2.css" combine=false}}
{{~css "lib/font-entgra-1.4.0/css/font-entgra.css" combine=false}}
<!-- Theme LESS -->
{{~css "less/theme.less" combine=false}}
{{~css "css/theme-wso2.css" combine=false}}

@ -147,6 +147,7 @@ import java.util.List;
key = "perm:get-activity",
permissions = {"/device-mgt/devices/owning-device/view"}
)
}
)
@Path("/users")

@ -97,24 +97,24 @@ public class DeviceManagementAdminServiceImpl implements DeviceManagementAdminSe
@QueryParam("owner") String owner,
List<String> deviceIdentifiers){
try {
if (DeviceMgtAPIUtils.getDeviceManagementService().updateEnrollment(owner, deviceIdentifiers)){
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){
} catch (InvalidDeviceException e) {
String msg = "Invalid device identifiers are found with the request.";
log.error(msg);
log.error(msg, e);
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
}catch (DeviceManagementException e) {
} catch (DeviceManagementException e) {
String msg = "Error occurred when updating the device owner.";
log.error(msg);
log.error(msg, e);
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);
log.error(msg, e);
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
}
}

@ -42,6 +42,7 @@
<module>org.wso2.carbon.device.mgt.analytics.data.publisher</module>
<module>org.wso2.carbon.device.mgt.url.printer</module>
<module>org.wso2.carbon.device.mgt.analytics.wsproxy</module>
<module>io.entgra.carbon.device.mgt.config.api</module>
</modules>
</project>

@ -232,7 +232,11 @@
<artifactId>powermock-module-testng</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.identity.jwt.client.extension</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

@ -85,6 +85,29 @@
</artifactItems>
</configuration>
</execution>
<execution>
<id>copy config api</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>io.entgra.carbon.device.mgt.config.api
</artifactId>
<version>${project.version}</version>
<type>war</type>
<overWrite>true</overWrite>
<outputDirectory>
${project.build.directory}/maven-shared-archive-resources/webapps
</outputDirectory>
<destFileName>api#device-mgt-config#v1.0.war</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>

@ -1,4 +1,5 @@
instructions.configure = \
org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../deployment/server/webapps/);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.api_${feature.version}/webapps/api#device-mgt#v1.0.war,target:${installFolder}/../../deployment/server/webapps/api#device-mgt#v1.0.war,overwrite:true);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.api_${feature.version}/webapps/api#device-mgt#v0.9.war,target:${installFolder}/../../deployment/server/webapps/api#device-mgt#v0.9.war,overwrite:true);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.api_${feature.version}/webapps/api#device-mgt#v0.9.war,target:${installFolder}/../../deployment/server/webapps/api#device-mgt#v0.9.war,overwrite:true);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.api_${feature.version}/webapps/api#device-mgt-config#v1.0.war,target:${installFolder}/../../deployment/server/webapps/api#device-mgt-config#v1.0.war,overwrite:true);\
Loading…
Cancel
Save