merged with origin

revert-70aa11f8
ayyoob 7 years ago
commit fbb5f5ae88

@ -1,6 +1,8 @@
# carbon-device-mgt
<a href='https://wso2.org/jenkins/job/platform-builds/job/carbon-device-mgt/'><img src='https://wso2.org/jenkins/job/platform-builds/job/carbon-device-mgt/badge/icon'></a>
<a href='https://opensource.org/licenses/Apache-2.0'><img src='https://img.shields.io/badge/License-Apache%202.0-blue.svg'></a><br/>
<a href='https://wso2.org/jenkins/job/platform-builds/job/carbon-device-mgt/'><img src='https://wso2.org/jenkins/job/platform-builds/job/carbon-device-mgt/badge/icon'></a> - Java7<br/>
<a href='https://wso2.org/jenkins/job/platform-builds/job/carbon-device-mgt__java8/'><img src='https://wso2.org/jenkins/job/platform-builds/job/carbon-device-mgt__java8/badge/icon'></a> - Java8
WSO2 CONNECTED DEVICE MANAGEMENT COMPONENTS

@ -22,13 +22,13 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.apimgt.annotations</artifactId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>WSO2 Carbon - API Management Annotations</name>
<description>WSO2 Carbon - API Management Custom Annotation Module</description>

@ -21,12 +21,12 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<artifactId>org.wso2.carbon.apimgt.application.extension.api</artifactId>
<packaging>war</packaging>
<name>WSO2 Carbon - API Application Management API</name>

@ -47,6 +47,7 @@ public class ApiPermissionFilter implements Filter {
private static final String PERMISSION_PREFIX = "/permission/admin";
private static List<Permission> permissions;
private static final String WEBAPP_CONTEXT = "/api-application-registration";
private static final String DEFAULT_ADMIN_ROLE = "admin";
@Override
public void init(FilterConfig filterConfig) throws ServletException {
InputStream permissionStream = filterConfig.getServletContext().getResourceAsStream(PERMISSION_CONFIG_PATH);
@ -122,7 +123,17 @@ public class ApiPermissionFilter implements Filter {
UserRealm userRealm = APIUtil.getRealmService().getTenantUserRealm(PrivilegedCarbonContext
.getThreadLocalCarbonContext().getTenantId());
String tenantAwareUsername = MultitenantUtils.getTenantAwareUsername(username);
return userRealm.getAuthorizationManager().isUserAuthorized(tenantAwareUsername, permission, action);
boolean status = userRealm.getAuthorizationManager()
.isUserAuthorized(tenantAwareUsername, permission, action);
if (!status) {
String[] roles = userRealm.getUserStoreManager().getRoleListOfUser(tenantAwareUsername);
for (String role : roles) {
if (role.equals(DEFAULT_ADMIN_ROLE)) {
return true;
}
}
}
return status;
} catch (UserStoreException e) {
String errorMsg = String.format("Unable to authorize the user : %s", username);
log.error(errorMsg, e);

@ -59,6 +59,43 @@
<filter-name>ApiPermissionFilter</filter-name>
<filter-class>org.wso2.carbon.apimgt.application.extension.api.filter.ApiPermissionFilter</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>ApiPermissionFilter</filter-name>
<url-pattern>/*</url-pattern>

@ -22,12 +22,12 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<artifactId>org.wso2.carbon.apimgt.application.extension</artifactId>
<packaging>bundle</packaging>
<name>WSO2 Carbon - API Application Management</name>

@ -26,6 +26,12 @@ import org.wso2.carbon.apimgt.application.extension.exception.APIManagerExceptio
*/
public interface APIManagementProviderService {
/**
* Check whether the tier is loaded for the tenant.
* @return
*/
boolean isTierLoaded();
/**
* Generate and retreive application keys. if the application does exist then
* create it and subscribe to apis that are grouped with the tags.

@ -45,8 +45,22 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe
private static final String CONTENT_TYPE = "application/json";
private static final int MAX_API_PER_TAG = 200;
private static final String APP_TIER_TYPE = "application";
private static final Map<String, String> tiersMap = new HashMap<>();
private static final int MAX_ATTEMPTS = 20;
public boolean isTierLoaded() {
StoreClient storeClient = APIApplicationManagerExtensionDataHolder.getInstance().getIntegrationClientService()
.getStoreClient();
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext()
.getTenantDomain();
try {
storeClient.getIndividualTier().tiersTierLevelTierNameGet(ApiApplicationConstants.DEFAULT_TIER,
APP_TIER_TYPE,
tenantDomain, CONTENT_TYPE, null, null);
return true;
} catch (FeignException e) {
return false;
}
}
@Override
public void removeAPIApplication(String applicationName, String username) throws APIManagerException {
@ -72,31 +86,8 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe
throws APIManagerException {
StoreClient storeClient = APIApplicationManagerExtensionDataHolder.getInstance().getIntegrationClientService()
.getStoreClient();
//This is a fix to avoid race condition and trying to load tenant related tiers before invocation.
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext()
.getTenantDomain();
String tiersLoadedForTenant = tiersMap.get(tenantDomain);
if (tiersLoadedForTenant == null) {
boolean tierLoaded = false;
int attempts = 0;
do {
try {
storeClient.getIndividualTier()
.tiersTierLevelTierNameGet(ApiApplicationConstants.DEFAULT_TIER, APP_TIER_TYPE,
tenantDomain, CONTENT_TYPE, null, null);
tiersMap.put(tenantDomain, "exist");
tierLoaded = true;
} catch (FeignException e) {
attempts++;
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
log.warn("Interrupted the waiting for tier availability.");
}
}
} while ((!tierLoaded) && attempts < MAX_ATTEMPTS);
}
ApplicationList applicationList = storeClient.getApplications()
.applicationsGet("", applicationName, 1, 0, CONTENT_TYPE, null);

@ -21,13 +21,13 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.apimgt.handlers</artifactId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>WSO2 Carbon - API Security Handler Component</name>
<description>WSO2 Carbon - API Management Security Handler Module</description>
@ -76,6 +76,7 @@
<Bundle-Description>WSO2 Carbon - API Security Handler Component</Bundle-Description>
<Import-Package>
org.apache.axiom.*,
javax.security.cert.*,
javax.xml.parsers;version="${javax.xml.parsers.import.pkg.version}";resolution:=optional,
javax.xml.*,
org.apache.axis2.*,
@ -90,7 +91,8 @@
org.w3c.dom,
org.apache.synapse,
org.apache.synapse.core.axis2,
org.apache.synapse.rest
org.apache.synapse.rest,
org.wso2.carbon.certificate.mgt.core.impl
</Import-Package>
</instructions>
</configuration>

@ -31,11 +31,17 @@ import org.wso2.carbon.apimgt.handlers.invoker.RESTInvoker;
import org.wso2.carbon.apimgt.handlers.invoker.RESTResponse;
import org.wso2.carbon.apimgt.handlers.utils.AuthConstants;
import org.wso2.carbon.apimgt.handlers.utils.Utils;
import org.wso2.carbon.certificate.mgt.core.impl.CertificateGenerator;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import javax.security.cert.CertificateEncodingException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
@ -140,6 +146,21 @@ public class AuthenticationHandler extends AbstractHandler {
if (log.isDebugEnabled()) {
log.debug("Verify response:" + response.getContent());
}
} else if (headers.containsKey(AuthConstants.MUTUAL_AUTH_HEADER)) {
javax.security.cert.X509Certificate[] certs =
(javax.security.cert.X509Certificate[]) axisMC.getProperty(AuthConstants.CLIENT_CERTIFICATE);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
ByteArrayInputStream bais = new ByteArrayInputStream(certs[0].getEncoded());
X509Certificate x509 = (X509Certificate) cf.generateCertificate(bais);
if (bais != null) {
bais.close();
}
if (x509 != null) {
headers.put(AuthConstants.PROXY_MUTUAL_AUTH_HEADER, CertificateGenerator.getCommonName(x509));
return true;
} else {
response = null;
}
} else if (headers.containsKey(AuthConstants.ENCODED_PEM)) {
String encodedPem = headers.get(AuthConstants.ENCODED_PEM).toString();
if (log.isDebugEnabled()) {
@ -178,8 +199,13 @@ public class AuthenticationHandler extends AbstractHandler {
} 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;
} catch (CertificateEncodingException e) {
log.error("Error while attempting to encode certificate.", e);
return false;
}
}
@Override
@ -205,4 +231,4 @@ public class AuthenticationHandler extends AbstractHandler {
map.put(CONTENT_TYPE, "application/json");
return map;
}
}
}

@ -35,6 +35,7 @@ public class AuthConstants {
// public static final String ANDROID_VERIFY_ENDPOINT = "android-verify-endpoint";
public static final String MDM_SIGNATURE = "mdm-signature";
public static final String PROXY_MUTUAL_AUTH_HEADER = "proxy-mutual-auth-header";
public static final String MUTUAL_AUTH_HEADER = "mutual-auth-header";
public static final String ENCODED_PEM = "encoded-pem";
public static final String CALLBACK_URL = "";
public static final String CLIENT_NAME = "IOT-API-MANAGER";
@ -46,4 +47,5 @@ public class AuthConstants {
public static final String BASIC_AUTH_PREFIX = "Basic ";
public static final String CLIENT_ID = "clientId";
public static final String CLIENT_SECRET = "clientSecret";
public static final String CLIENT_CERTIFICATE = "ssl.client.auth.cert.X509";
}

@ -13,13 +13,13 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.apimgt.integration.client</artifactId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>WSO2 Carbon - API Management Integration Client</name>
<description>WSO2 Carbon - API Management Integration Client</description>

@ -19,7 +19,9 @@ package org.wso2.carbon.apimgt.integration.client.store;
import feign.Feign;
import feign.Logger;
import feign.Request;
import feign.RequestInterceptor;
import feign.Retryer;
import feign.gson.GsonDecoder;
import feign.gson.GsonEncoder;
import feign.slf4j.Slf4jLogger;
@ -28,6 +30,8 @@ import org.wso2.carbon.apimgt.integration.client.configs.APIMConfigReader;
import org.wso2.carbon.apimgt.integration.generated.client.store.api.*;
import org.wso2.carbon.core.util.Utils;
import java.util.concurrent.TimeUnit;
/**
* API Store client, created using swagger gen.
*/
@ -62,8 +66,10 @@ public class StoreClient {
individualSubscription = builder.target(SubscriptionIndividualApi.class, basePath);
subscriptionMultitpleApi = builder.target(SubscriptionMultitpleApi.class, basePath);
tags = builder.target(TagCollectionApi.class, basePath);
tiers = builder.target(ThrottlingTierCollectionApi.class, basePath);
individualTier = builder.target(ThrottlingTierIndividualApi.class, basePath);
tiers = builder.retryer(new Retryer.Default(100L, TimeUnit.SECONDS.toMillis(1L), 1))
.options(new Request.Options(10000, 5000))
.target(ThrottlingTierCollectionApi.class, basePath);
}

@ -13,13 +13,13 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.apimgt.integration.generated.client</artifactId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>WSO2 Carbon - API Management Integration Generated Client</name>
<description>WSO2 Carbon - API Management Integration Client</description>

@ -22,13 +22,13 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.apimgt.webapp.publisher</artifactId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>WSO2 Carbon - API Management Webapp Publisher</name>
<description>WSO2 Carbon - API Management Webapp Publisher</description>

@ -22,13 +22,13 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>carbon-devicemgt</artifactId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apimgt-extensions</artifactId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<packaging>pom</packaging>
<name>WSO2 Carbon - API Management Extensions Component</name>
<url>http://wso2.org</url>

@ -22,7 +22,7 @@
<parent>
<artifactId>certificate-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -52,4 +52,40 @@
<param-value>true</param-value>
</context-param>
<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>
</web-app>

@ -22,7 +22,7 @@
<parent>
<artifactId>certificate-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -1,3 +1,21 @@
/*
* Copyright (c) 2016-2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.certificate.mgt.cert.jaxrs.api.impl;
import org.apache.commons.logging.Log;
@ -6,12 +24,13 @@ import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.CertificateManagementAdmin
import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.CertificateList;
import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.EnrollmentCertificate;
import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.ErrorResponse;
import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.ValidationResponce;
import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.ValidationResponse;
import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.util.CertificateMgtAPIUtils;
import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.util.RequestValidationUtil;
import org.wso2.carbon.certificate.mgt.core.dto.CertificateResponse;
import org.wso2.carbon.certificate.mgt.core.exception.CertificateManagementException;
import org.wso2.carbon.certificate.mgt.core.exception.KeystoreException;
import org.wso2.carbon.certificate.mgt.core.impl.CertificateGenerator;
import org.wso2.carbon.certificate.mgt.core.scep.SCEPException;
import org.wso2.carbon.certificate.mgt.core.scep.SCEPManager;
import org.wso2.carbon.certificate.mgt.core.scep.TenantedDeviceWrapper;
@ -232,30 +251,41 @@ public class CertificateManagementAdminServiceImpl implements CertificateManagem
deviceIdentifier.setId(challengeToken);
deviceIdentifier.setType(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_IOS);
TenantedDeviceWrapper tenantedDeviceWrapper = scepManager.getValidatedDevice(deviceIdentifier);
//
// var claims = {"http://wso2.org/claims/enduserTenantId": adminUserTenantId,
// "http://wso2.org/claims/enduser": adminUsername};
Map<String, String> claims = new HashMap<>();
claims.put("http://wso2.org/claims/enduserTenantId", String.valueOf(tenantedDeviceWrapper.getTenantId()));
claims.put("http://wso2.org/claims/enduser", tenantedDeviceWrapper.getDevice().getEnrolmentInfo().getOwner());
claims.put("http://wso2.org/claims/deviceIdentifier", tenantedDeviceWrapper.getDevice().getDeviceIdentifier());
claims.put("http://wso2.org/claims/enduserTenantId",
String.valueOf(tenantedDeviceWrapper.getTenantId()));
claims.put("http://wso2.org/claims/enduser",
tenantedDeviceWrapper.getDevice().getEnrolmentInfo().getOwner() + "@"
+ tenantedDeviceWrapper.getTenantDomain());
claims.put("http://wso2.org/claims/deviceIdentifier",
tenantedDeviceWrapper.getDevice().getDeviceIdentifier());
claims.put("http://wso2.org/claims/deviceIdType", tenantedDeviceWrapper.getDevice().getType());
JWTClientManagerService jwtClientManagerService = CertificateMgtAPIUtils.getJwtClientManagerService();
String jwdToken = jwtClientManagerService.getJWTClient().getJwtToken(
tenantedDeviceWrapper.getDevice().getEnrolmentInfo().getOwner(), claims);
String jwdToken;
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext()
.setTenantId(tenantedDeviceWrapper.getTenantId());
PrivilegedCarbonContext.getThreadLocalCarbonContext()
.setTenantDomain(tenantedDeviceWrapper.getTenantDomain());
JWTClientManagerService jwtClientManagerService = CertificateMgtAPIUtils
.getJwtClientManagerService();
jwdToken = jwtClientManagerService.getJWTClient()
.getJwtToken(tenantedDeviceWrapper.getDevice().getEnrolmentInfo().getOwner(), claims,
true);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
ValidationResponce validationResponce = new ValidationResponce();
validationResponce.setDeviceId(challengeToken);
validationResponce.setDeviceType(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_IOS);
validationResponce.setJWTToken(jwdToken);
validationResponce.setTenantId(tenantedDeviceWrapper.getTenantId());
ValidationResponse validationResponse = new ValidationResponse();
validationResponse.setDeviceId(challengeToken);
validationResponse.setDeviceType(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_IOS);
validationResponse.setJWTToken(jwdToken);
validationResponse.setTenantId(tenantedDeviceWrapper.getTenantId());
if (tenantedDeviceWrapper != null) {
return Response.status(Response.Status.OK).entity(validationResponce).build();
}
return Response.status(Response.Status.OK).entity(validationResponse).build();
}
}

@ -16,7 +16,9 @@
~ 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">
<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>Certificate-Webapp</display-name>
<servlet>
<description>JAX-WS/JAX-RS Certificate Management Endpoint</description>
@ -52,10 +54,10 @@
<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>
<context-param>
<param-name>isSharedWithAllTenants</param-name>
<param-value>true</param-value>
</context-param>
<security-constraint>
<web-resource-collection>
@ -71,6 +73,43 @@
<filter-name>ApiOriginFilter</filter-name>
<filter-class>org.wso2.carbon.certificate.mgt.cert.jaxrs.api.util.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>

@ -21,13 +21,13 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>certificate-mgt</artifactId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.certificate.mgt.core</artifactId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>WSO2 Carbon - Certificate Management Core</name>
<description>WSO2 Carbon - Certificate Management Core</description>

@ -22,14 +22,14 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>carbon-devicemgt</artifactId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>certificate-mgt</artifactId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<packaging>pom</packaging>
<name>WSO2 Carbon - Certificate Management Component</name>
<url>http://wso2.org</url>

@ -22,7 +22,7 @@
<parent>
<artifactId>device-mgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -59,6 +59,8 @@ public class PushNotificationProvider {
protected ConfigProperties configProperties;
@XmlAttribute(name = "type")
protected String type;
@XmlAttribute(name = "isScheduled")
protected boolean isScheduled;
/**
* Gets the value of the fileBasedProperties property.
@ -124,4 +126,30 @@ public class PushNotificationProvider {
this.type = value;
}
/**
* Gets the value of the isScheduled property.
* This property will be used to determine whether to use scheduler task to send push notification
* If true push notification will be sent using scheduler task
* If false push notifications will be sent immediately.
*
* @return
* possible object is
* {@link Boolean }
*
*/
public boolean isScheduled() {
return isScheduled;
}
/**
* Sets the value of the isScheduled property.
*
* @return
* possible object is
* {@link Boolean }
*
*/
public void setScheduled(boolean scheduled) {
isScheduled = scheduled;
}
}

@ -20,6 +20,7 @@ package org.wso2.carbon.device.mgt.extensions.device.type.deployer.template;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
@ -42,12 +43,14 @@ import org.wso2.carbon.device.mgt.extensions.device.type.deployer.template.util.
import org.wso2.carbon.device.mgt.extensions.license.mgt.registry.RegistryBasedLicenseManager;
import org.wso2.carbon.registry.api.RegistryException;
import org.wso2.carbon.registry.api.Resource;
import org.wso2.carbon.utils.CarbonUtils;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.charset.Charset;
@ -63,10 +66,15 @@ public class DeviceTypeManager implements DeviceManager {
private String deviceType;
private DeviceTypePluginDAOManager deviceTypePluginDAOManager;
private LicenseManager licenseManager;
private PlatformConfiguration defaultPlatformConfiguration;
private boolean propertiesExist;
private boolean requiredDeviceTypeAuthorization;
private boolean claimable;
private static final String PATH_MOBILE_PLUGIN_CONF_DIR =
CarbonUtils.getEtcCarbonConfigDirPath() + File.separator + "device-mgt-plugin-configs" + File.separator
+ "mobile";
private FeatureManager featureManager;
public DeviceTypeManager(DeviceTypeConfigIdentifier deviceTypeConfigIdentifier,
@ -107,6 +115,14 @@ public class DeviceTypeManager implements DeviceManager {
claimable = deviceTypeConfiguration.getClaimable().isEnabled();
}
// Loading default platform configuration
try {
defaultPlatformConfiguration = this.getDefaultConfiguration();
} catch (DeviceManagementException e) {
String msg = "Error occurred while default platform configuration";
throw new DeviceTypeDeployerFileException(msg, e);
}
DeviceDetails deviceDetails = deviceTypeConfiguration.getDeviceDetails();
if (deviceDetails != null) {
@ -210,6 +226,8 @@ public class DeviceTypeManager implements DeviceManager {
return (PlatformConfiguration) unmarshaller.unmarshal(
new StringReader(new String((byte[]) resource.getContent(), Charset.
forName(DeviceTypePluginConstants.CHARSET_UTF8))));
} else if (defaultPlatformConfiguration != null) {
return defaultPlatformConfiguration;
}
return null;
} catch (DeviceTypeMgtPluginException e) {
@ -376,6 +394,39 @@ public class DeviceTypeManager implements DeviceManager {
return requiredDeviceTypeAuthorization;
}
@Override
public PlatformConfiguration getDefaultConfiguration() throws DeviceManagementException {
if (log.isDebugEnabled()) {
log.debug("Loading default " + deviceType + " platform configuration from " + deviceType +
"-default-platform-configuration.xml");
}
try {
String platformConfigurationPath =
PATH_MOBILE_PLUGIN_CONF_DIR + File.separator + deviceType + "-default-platform-configuration.xml";
File platformConfig = new File(platformConfigurationPath);
if (platformConfig.exists()) {
Document doc = DeviceTypeUtils.convertToDocument(platformConfig);
JAXBContext context = JAXBContext.newInstance(PlatformConfiguration.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
return (PlatformConfiguration) unmarshaller.unmarshal(doc);
} else {
log.warn(deviceType + "-default-platform-configuration.xml is not available, hence default " +
deviceType + "platform configuration cannot be loaded.");
}
return null;
} catch (JAXBException e) {
throw new DeviceManagementException(
"Error occurred while parsing the " + deviceType + " default platform configuration : " + e
.getMessage(), e);
} catch (DeviceTypeMgtPluginException e) {
throw new DeviceManagementException(
"Error occurred while parsing the " + deviceType + " default platform configuration : " + e
.getMessage(), e);
}
}
@Override
public boolean updateDeviceInfo(DeviceIdentifier deviceIdentifier, Device device)
throws DeviceManagementException {

@ -20,13 +20,19 @@ package org.wso2.carbon.device.mgt.extensions.device.type.deployer.template;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.common.*;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.DeviceManager;
import org.wso2.carbon.device.mgt.common.InitialOperationConfig;
import org.wso2.carbon.device.mgt.common.MonitoringOperation;
import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig;
import org.wso2.carbon.device.mgt.common.ProvisioningConfig;
import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManager;
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry;
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration;
import org.wso2.carbon.device.mgt.common.policy.mgt.PolicyMonitoringManager;
import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationConfig;
import org.wso2.carbon.device.mgt.common.spi.DeviceManagementService;
import org.wso2.carbon.device.mgt.extensions.device.type.deployer.config.ConfigProperties;
import org.wso2.carbon.device.mgt.extensions.device.type.deployer.config.DeviceTypeConfiguration;
import org.wso2.carbon.device.mgt.extensions.device.type.deployer.config.Property;
import org.wso2.carbon.device.mgt.extensions.device.type.deployer.config.PushNotificationProvider;
@ -54,7 +60,6 @@ public class DeviceTypeManagerService implements DeviceManagementService {
private List<MonitoringOperation> monitoringOperations;
private PolicyMonitoringManager policyMonitoringManager;
private InitialOperationConfig initialOperationConfig;
private List<String> operations;
public DeviceTypeManagerService(DeviceTypeConfigIdentifier deviceTypeConfigIdentifier,
DeviceTypeConfiguration deviceTypeConfiguration) {
@ -64,6 +69,7 @@ public class DeviceTypeManagerService implements DeviceManagementService {
this.populatePushNotificationConfig(deviceTypeConfiguration.getPushNotificationProvider());
this.operationMonitoringConfigs = new OperationMonitoringTaskConfig();
this.setOperationMonitoringConfig(deviceTypeConfiguration);
this.initialOperationConfig = new InitialOperationConfig();
this.setInitialOperationConfig(deviceTypeConfiguration);
if (deviceTypeConfiguration.getPolicyMonitoring() != null ) {
this.policyMonitoringManager = new DefaultPolicyMonitoringManager();
@ -108,10 +114,17 @@ public class DeviceTypeManagerService implements DeviceManagementService {
if (pushNotificationProvider != null) {
if (pushNotificationProvider.isFileBasedProperties()) {
Map<String, String> staticProps = new HashMap<>();
for (Property property : pushNotificationProvider.getConfigProperties().getProperty()) {
staticProps.put(property.getName(), property.getValue());
ConfigProperties configProperties = pushNotificationProvider.getConfigProperties();
if (configProperties != null) {
List<Property> properties = configProperties.getProperty();
if (properties != null && properties.size() > 0) {
for (Property property : properties) {
staticProps.put(property.getName(), property.getValue());
}
}
}
pushNotificationConfig = new PushNotificationConfig(pushNotificationProvider.getType(), staticProps);
pushNotificationConfig = new PushNotificationConfig(pushNotificationProvider.getType(),
pushNotificationProvider.isScheduled(), staticProps);
} else {
try {
PlatformConfiguration deviceTypeConfig = deviceManager.getConfiguration();
@ -120,7 +133,8 @@ public class DeviceTypeManagerService implements DeviceManagementService {
if (configuration.size() > 0) {
Map<String, String> properties = this.getConfigProperty(configuration);
pushNotificationConfig = new PushNotificationConfig(
pushNotificationProvider.getType(), properties);
pushNotificationProvider.getType(), pushNotificationProvider.isScheduled(),
properties);
}
}
} catch (DeviceManagementException e) {

@ -20,6 +20,7 @@ package org.wso2.carbon.device.mgt.extensions.device.type.deployer.template.util
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.extensions.device.type.deployer.exception.DeviceTypeMgtPluginException;
import org.wso2.carbon.device.mgt.extensions.device.type.deployer.internal.DeviceTypeManagementDataHolder;
@ -30,6 +31,10 @@ import org.wso2.carbon.registry.core.Registry;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@ -128,4 +133,18 @@ public class DeviceTypeUtils {
}
}
public static Document convertToDocument(File file) throws DeviceTypeMgtPluginException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
try {
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
DocumentBuilder docBuilder = factory.newDocumentBuilder();
return docBuilder.parse(file);
} catch (Exception e) {
throw new DeviceTypeMgtPluginException("Error occurred while parsing file '" + file.getName() + "' to" +
" a org.w3c.dom.Document", e);
}
}
}

@ -22,7 +22,7 @@
<parent>
<artifactId>device-mgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -42,7 +42,7 @@ public class FCMNotificationStrategy implements NotificationStrategy {
private static final String FCM_API_KEY = "fcmAPIKey";
private static final int TIME_TO_LIVE = 60;
private static final int HTTP_STATUS_CODE_OK = 200;
private PushNotificationConfig config;
private final PushNotificationConfig config;
public FCMNotificationStrategy(PushNotificationConfig config) {
this.config = config;
@ -133,4 +133,9 @@ public class FCMNotificationStrategy implements NotificationStrategy {
return fcmToken;
}
@Override
public PushNotificationConfig getConfig() {
return config;
}
}

@ -22,7 +22,7 @@
<parent>
<artifactId>device-mgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -44,35 +44,53 @@ public class MQTTNotificationStrategy implements NotificationStrategy {
private static final String MQTT_ADAPTER_TOPIC = "mqtt.adapter.topic";
private String mqttAdapterName;
private static final Log log = LogFactory.getLog(MQTTNotificationStrategy.class);
private final PushNotificationConfig config;
private final String providerTenantDomain;
private static final Object lockObj = new Object();
public MQTTNotificationStrategy(PushNotificationConfig config) {
this.config = config;
OutputEventAdapterConfiguration adapterConfig = new OutputEventAdapterConfiguration();
adapterConfig.setType(MQTTAdapterConstants.MQTT_ADAPTER_TYPE);
mqttAdapterName = config.getProperty(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_NAME);
adapterConfig.setName(mqttAdapterName);
adapterConfig.setMessageFormat(MessageType.TEXT);
Map<String, String> configProperties = new HashMap<String, String>();
String brokerUrl = config.getProperty(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_BROKER_URL);
if (brokerUrl != null && !brokerUrl.isEmpty()) {
configProperties.put(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_BROKER_URL, brokerUrl);
if (config.getProperties() != null && config.getProperties().size() > 0) {
String brokerUrl = config.getProperty(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_BROKER_URL);
if (brokerUrl != null && !brokerUrl.isEmpty()) {
configProperties.put(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_BROKER_URL, brokerUrl);
}
mqttAdapterName = config.getProperty(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_NAME);
configProperties.put(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_USERNAME,
config.getProperty(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_USERNAME));
configProperties.put(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_PASSWORD,
config.getProperty(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_PASSWORD));
configProperties.put(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_CLEAR_SESSION,
config.getProperty(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_CLEAR_SESSION));
configProperties.put(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_SCOPES,
config.getProperty(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_SCOPES));
configProperties.put(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_MESSAGE_QOS,
config.getProperty(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_MESSAGE_QOS));
} else {
mqttAdapterName = "mqtt.adapter." + PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain()
.toLowerCase();
}
configProperties.put(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_USERNAME,
config.getProperty(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_USERNAME));
configProperties.put(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_PASSWORD,
config.getProperty(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_PASSWORD));
configProperties.put(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_CLEAR_SESSION,
config.getProperty(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_CLEAR_SESSION));
configProperties.put(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_SCOPES,
config.getProperty(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_SCOPES));
configProperties.put(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_MESSAGE_QOS,
config.getProperty(MQTTAdapterConstants.MQTT_ADAPTER_PROPERTY_MESSAGE_QOS));
adapterConfig.setName(mqttAdapterName);
adapterConfig.setStaticProperties(configProperties);
try {
MQTTDataHolder.getInstance().getOutputEventAdapterService().create(adapterConfig);
synchronized (lockObj) {
try {
MQTTDataHolder.getInstance().getOutputEventAdapterService().isPolled(mqttAdapterName);
} catch (OutputEventAdapterException e) {
//event adapter not created
MQTTDataHolder.getInstance().getOutputEventAdapterService().create(adapterConfig);
}
}
} catch (OutputEventAdapterException e) {
throw new InvalidConfigurationException("Error occurred while initializing MQTT output event adapter", e);
}
providerTenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain()
.toLowerCase();
}
@Override
@ -82,19 +100,47 @@ public class MQTTNotificationStrategy implements NotificationStrategy {
@Override
public void execute(NotificationContext ctx) throws PushNotificationExecutionFailedException {
String adapterName = mqttAdapterName;
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(true);
if (!providerTenantDomain.equals(tenantDomain)) {
//this is to handle the device type shared with all tenant mode.
adapterName = "mqtt.adapter." + PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain()
.toLowerCase();
try {
MQTTDataHolder.getInstance().getOutputEventAdapterService().isPolled(adapterName);
} catch (OutputEventAdapterException e) {
//event adapter not created
synchronized (lockObj) {
OutputEventAdapterConfiguration adapterConfig = new OutputEventAdapterConfiguration();
adapterConfig.setType(MQTTAdapterConstants.MQTT_ADAPTER_TYPE);
adapterConfig.setMessageFormat(MessageType.TEXT);
adapterConfig.setName(adapterName);
Map<String, String> configProperties = new HashMap<String, String>();
adapterConfig.setStaticProperties(configProperties);
try {
MQTTDataHolder.getInstance().getOutputEventAdapterService().create(adapterConfig);
} catch (OutputEventAdapterException e1) {
throw new PushNotificationExecutionFailedException
("Error occurred while initializing MQTT output event adapter for shared tenant: "
+ tenantDomain, e);
}
}
}
}
Operation operation = ctx.getOperation();
Properties properties = operation.getProperties();
if (properties != null && properties.get(MQTT_ADAPTER_TOPIC) != null) {
Map<String, String> dynamicProperties = new HashMap<>();
dynamicProperties.put("topic", (String) properties.get(MQTT_ADAPTER_TOPIC));
MQTTDataHolder.getInstance().getOutputEventAdapterService().publish(mqttAdapterName, dynamicProperties,
MQTTDataHolder.getInstance().getOutputEventAdapterService().publish(adapterName, dynamicProperties,
operation.getPayLoad());
} else {
if (PolicyOperation.POLICY_OPERATION_CODE.equals(operation.getCode())) {
PolicyOperation policyOperation = (PolicyOperation) operation;
List<ProfileOperation> profileOperations = policyOperation.getProfileOperations();
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(true);
String deviceType = ctx.getDeviceId().getType();
String deviceId = ctx.getDeviceId().getId();
for (ProfileOperation profileOperation : profileOperations) {
@ -103,7 +149,7 @@ public class MQTTNotificationStrategy implements NotificationStrategy {
+ deviceType + "/" + deviceId + "/operation/" + profileOperation.getType()
.toString().toLowerCase() + "/" + profileOperation.getCode().toLowerCase();
dynamicProperties.put("topic", topic);
MQTTDataHolder.getInstance().getOutputEventAdapterService().publish(mqttAdapterName, dynamicProperties,
MQTTDataHolder.getInstance().getOutputEventAdapterService().publish(adapterName, dynamicProperties,
profileOperation.getPayLoad());
}
@ -116,7 +162,7 @@ public class MQTTNotificationStrategy implements NotificationStrategy {
if (operation.getPayLoad() == null) {
operation.setPayLoad(operation.getCode());
}
MQTTDataHolder.getInstance().getOutputEventAdapterService().publish(mqttAdapterName, dynamicProperties,
MQTTDataHolder.getInstance().getOutputEventAdapterService().publish(adapterName, dynamicProperties,
operation.getPayLoad());
}
@ -136,5 +182,10 @@ public class MQTTNotificationStrategy implements NotificationStrategy {
MQTTDataHolder.getInstance().getOutputEventAdapterService().destroy(mqttAdapterName);
}
@Override
public PushNotificationConfig getConfig() {
return config;
}
}

@ -22,7 +22,7 @@
<parent>
<artifactId>device-mgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -45,10 +45,12 @@ public class XMPPNotificationStrategy implements NotificationStrategy {
private String xmppAdapterName;
private static final Log log = LogFactory.getLog(XMPPNotificationStrategy.class);
private String subDomain;
private final PushNotificationConfig config;
public XMPPNotificationStrategy(PushNotificationConfig config) {
this.config = config;
OutputEventAdapterConfiguration outputEventAdapterConfiguration = new OutputEventAdapterConfiguration();
xmppAdapterName = config.getProperty(XMPPAdapterConstants.XMPP_ADAPTER_PROPERTY_NAME);
outputEventAdapterConfiguration.setName(xmppAdapterName);
@ -106,4 +108,8 @@ public class XMPPNotificationStrategy implements NotificationStrategy {
XMPPDataHolder.getInstance().getOutputEventAdapterService().destroy(xmppAdapterName);
}
@Override
public PushNotificationConfig getConfig() {
return config;
}
}

@ -22,7 +22,7 @@
<parent>
<artifactId>carbon-devicemgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -3,7 +3,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>device-mgt</artifactId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>device-mgt</artifactId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>device-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -115,4 +115,43 @@ public interface DeviceAccessAuthorizationAdminService {
response = ErrorResponse.class)
})
Response isAuthorized(AuthorizationRequest authorizationRequest);
@POST
@Path("/stat")
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON,
httpMethod = "POST",
value = "Check for device access authorization for stat\n",
notes = "This is an internal API that can be used to check for authorization.",
response = DeviceAuthorizationResult.class,
tags = "Authorization Administrative Service",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:authorization:verify")
})
})
@ApiResponses(value = {
@ApiResponse(
code = 200,
message = "OK. \n Authorized device list will be delivered to the requested services",
response = DeviceAuthorizationResult.class),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error.",
response = ErrorResponse.class),
@ApiResponse(
code = 404,
message = "Not Found. \n The specified resource does not exist."),
@ApiResponse(
code = 415,
message = "Unsupported media type. \n The entity of the request was in a not supported format."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Server error occurred while checking the authorization" +
" for a specified set of devices.",
response = ErrorResponse.class)
})
Response isAuthorizedForStat(AuthorizationRequest authorizationRequest);
}

@ -38,7 +38,7 @@ import javax.ws.rs.core.Response;
title = "",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = "name", value = "DeviceTypePublisherAdminService"),
@ExtensionProperty(name = "name", value = "DeviceAnalyticsArtifactUploaderAdminService"),
@ExtensionProperty(name = "context", value = "/api/device-mgt/v1.0/admin/devicetype"),
})
}
@ -62,7 +62,7 @@ import javax.ws.rs.core.Response;
}
)
public interface DeviceTypePublisherAdminService {
public interface DeviceAnalyticsArtifactUploaderAdminService {
@POST
@Path("/deploy/{type}")
@ -107,42 +107,4 @@ public interface DeviceTypePublisherAdminService {
required = true)
@PathParam("type") String type);
@GET
@Path("/deploy/{type}/status")
@ApiOperation(
httpMethod = "GET",
value = "Check the status of device type artifact\n",
notes = "This is an API that can be used to check the status of the artifact",
response = Response.class,
tags = "Devicetype Status Service",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:devicetype:deployment")
})
})
@ApiResponses(value = {
@ApiResponse(
code = 201,
message = "OK. \n Successfully deployed the artifacts.",
response = Response.class),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error.",
response = ErrorResponse.class),
@ApiResponse(
code = 404,
message = "Not Found. \n The specified resource does not exist."),
@ApiResponse(
code = 415,
message = "Unsupported media type. \n The entity of the request was in a not supported format."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Server error occurred while checking the authorization" +
" for a specified set of devices.",
response = ErrorResponse.class)
})
Response getStatus(@PathParam("type") String deviceType);
}

@ -674,7 +674,6 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
if (policy == null) {
deviceCompliance.setDeviceID(id);
deviceCompliance.setComplianceData(null);
//deviceCompliance.setCode(0001l); //code 0001 means no compliance data related to the device
return Response.status(Response.Status.OK).entity(deviceCompliance).build();
} else {
try {
@ -683,7 +682,6 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
new DeviceIdentifier(id, type));
deviceCompliance.setDeviceID(id);
deviceCompliance.setComplianceData(complianceData);
//deviceCompliance.setCode(0002l); //code 0002 means there are compliance data related to the device
return Response.status(Response.Status.OK).entity(deviceCompliance).build();
} catch (PolicyComplianceException e) {
String error = "Error occurred while getting the compliance data.";

@ -36,6 +36,8 @@ import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.List;
@Path("/admin/authorization")
@Produces(MediaType.APPLICATION_JSON)
@ -43,6 +45,7 @@ import javax.ws.rs.core.Response;
public class DeviceAccessAuthorizationAdminServiceImpl implements DeviceAccessAuthorizationAdminService {
private static final Log log = LogFactory.getLog(DeviceAccessAuthorizationAdminServiceImpl.class);
private static final String DEFAULT_STAT_PERMISSION = "/permission/admin/device-mgt/device/realtime_analytics";
@POST
@Override
@ -90,4 +93,14 @@ public class DeviceAccessAuthorizationAdminServiceImpl implements DeviceAccessAu
}
}
@POST
@Path("/stat")
@Override
public Response isAuthorizedForStat(AuthorizationRequest authorizationRequest) {
List<String> permissions = new ArrayList<>();
permissions.add(DEFAULT_STAT_PERMISSION);
authorizationRequest.setPermissions(permissions);
return isAuthorized(authorizationRequest);
}
}

@ -20,6 +20,7 @@ package org.wso2.carbon.device.mgt.jaxrs.service.impl.admin;
import org.apache.axis2.AxisFault;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.Stub;
import org.apache.axis2.java.security.SSLProtocolSocketFactory;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.commons.codec.binary.Base64;
@ -36,13 +37,10 @@ import org.wso2.carbon.application.mgt.stub.upload.types.carbon.UploadedFileItem
import org.wso2.carbon.base.ServerConfiguration;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.core.util.Utils;
import org.wso2.carbon.device.mgt.jaxrs.service.api.admin.DeviceTypePublisherAdminService;
import org.wso2.carbon.device.mgt.jaxrs.service.api.admin.DeviceAnalyticsArtifactUploaderAdminService;
import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils;
import org.wso2.carbon.identity.jwt.client.extension.JWTClient;
import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
import org.wso2.carbon.registry.core.Registry;
import org.wso2.carbon.registry.core.Resource;
import org.wso2.carbon.registry.core.ResourceImpl;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.utils.CarbonUtils;
@ -54,7 +52,6 @@ import javax.activation.DataHandler;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
@ -72,7 +69,7 @@ import java.util.ArrayList;
import java.util.List;
@Path("/admin/devicetype")
public class DeviceTypePublisherAdminServiceImpl implements DeviceTypePublisherAdminService {
public class DeviceAnalyticsArtifactUploaderAdminServiceImpl implements DeviceAnalyticsArtifactUploaderAdminService {
/**
* required soap header for authorization
@ -109,7 +106,7 @@ public class DeviceTypePublisherAdminServiceImpl implements DeviceTypePublisherA
private String tenantDomain;
private static final Log log = LogFactory.getLog(DeviceTypePublisherAdminServiceImpl.class);
private static final Log log = LogFactory.getLog(DeviceAnalyticsArtifactUploaderAdminServiceImpl.class);
private static final String DEFAULT_RESOURCE_LOCATION = "/resources/devicetypes";
private static final String CAR_FILE_LOCATION = CarbonUtils.getCarbonHome() + File.separator + "repository" +
File.separator + "resources" + File.separator + "devicetypes";
@ -119,12 +116,14 @@ public class DeviceTypePublisherAdminServiceImpl implements DeviceTypePublisherA
private static final String IOT_MGT_PORT = "${iot.manager.https.port}";
private static final String IOT_MGT_HOST_NAME = "${iot.manager.host}";
private static final String DAS_URL = DEFAULT_HTTP_PROTOCOL + "://" + DAS_HOST_NAME
+ ":" + DAS_PORT + "/services/CarbonAppUploader" + "/";
+ ":" + DAS_PORT + "/services/CarbonAppUploader/";
private static final String DAS_EVENT_RECEIVER_EP = DEFAULT_HTTP_PROTOCOL + "://" + DAS_HOST_NAME
+ ":" + DAS_PORT + "/services/EventReceiverAdminService" + "/";
+ ":" + DAS_PORT + "/services/EventReceiverAdminService/";
private static final String DAS_EVENT_STREAM_EP = DEFAULT_HTTP_PROTOCOL + "://" + DAS_HOST_NAME
+ ":" + DAS_PORT + "/services/EventStreamAdminService/";
private static final String IOT_MGT_URL = DEFAULT_HTTP_PROTOCOL + "://" + IOT_MGT_HOST_NAME
+ ":" + IOT_MGT_PORT + "/services/CarbonAppUploader" + "/";
+ ":" + IOT_MGT_PORT + "/services/CarbonAppUploader/";
private static final String MEDIA_TYPE_XML = "application/xml";
private static final String DEVICE_MANAGEMENT_TYPE = "device_management";
private static final String TENANT_DOMAIN_PROPERTY = "\\$\\{tenant-domain\\}";
@ -134,7 +133,6 @@ public class DeviceTypePublisherAdminServiceImpl implements DeviceTypePublisherA
@POST
@Path("/deploy/{type}")
public Response doPublish(@PathParam("type") String type) {
try {
//Getting the tenant Domain
tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
@ -159,33 +157,86 @@ public class DeviceTypePublisherAdminServiceImpl implements DeviceTypePublisherA
String authValue = AUTHORIZATION_HEADER_VALUE + " " + new String(Base64.encodeBase64(
jwtClient.getJwtToken(tenantAdminUser).getBytes()));
List<Header> list = new ArrayList<Header>();
List<Header> list = new ArrayList<>();
Header httpHeader = new Header();
httpHeader.setName(AUTHORIZATION_HEADER);
httpHeader.setValue(authValue);
list.add(httpHeader);//"https"
List<String> streamFileList = getStreamsList(type);
List<String> receiverFileList = getReceiversList(type);
if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) {
if (streamFileList != null) {
publishDynamicEventStream(type, MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, streamFileList);
}
if (receiverFileList != null) {
publishDynamicEventReceivers(type, MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, receiverFileList);
}
}
if (streamFileList != null) {
publishDynamicEventStream(type, tenantDomain, streamFileList);
}
if (deployAnalyticsCapp(type, list)){
return Response.status(Response.Status.BAD_REQUEST)
.entity("\"Error, Artifact does not exist.\"").build();
}
if (receiverFileList != null) {
publishDynamicEventReceivers(type, tenantDomain, receiverFileList);
}
return Response.status(Response.Status.CREATED).entity("\"OK. \\n Successfully uploaded the artifacts.\"")
.build();
} catch (AxisFault e) {
log.error("failed to publish event definitions for tenantDomain:" + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (RemoteException e) {
log.error("Failed to connect with the remote services:" + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (JWTClientException e) {
log.error("Failed to generate jwt token for tenantDomain:" + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (UserStoreException e) {
log.error("Failed to connect with the user store, tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (CertificateException | UnrecoverableKeyException | KeyStoreException |
KeyManagementException | IOException | NoSuchAlgorithmException e) {
log.error("Failed to access keystore for, tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (RegistryException e) {
log.error("Failed to load tenant, tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (ParseException e) {
log.error("Invalid stream definition for device type" + type + " for tenant, tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
}
private boolean deployAnalyticsCapp(@PathParam("type") String type, List<Header> list) throws IOException, RegistryException {
CarbonAppUploaderStub carbonAppUploaderStub = null;
try {
File directory = new File(CAR_FILE_LOCATION + File.separator + type);
if (directory.isDirectory() && directory.exists()) {
UploadedFileItem[] uploadedFileItems = loadCappFromFileSystem(type);
if (uploadedFileItems.length > 0) {
CarbonAppUploaderStub carbonAppUploaderStub = new CarbonAppUploaderStub(Utils.replaceSystemProperty(
IOT_MGT_URL));
Options appUploaderOptions = carbonAppUploaderStub._getServiceClient().getOptions();
if (appUploaderOptions == null) {
appUploaderOptions = new Options();
}
appUploaderOptions.setProperty(HTTPConstants.HTTP_HEADERS, list);
appUploaderOptions.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER
, new Protocol(DEFAULT_HTTP_PROTOCOL, (ProtocolSocketFactory) new SSLProtocolSocketFactory
(sslContext), Integer.parseInt(Utils.replaceSystemProperty(IOT_MGT_PORT))));
carbonAppUploaderStub._getServiceClient().setOptions(appUploaderOptions);
carbonAppUploaderStub.uploadApp(uploadedFileItems);
if (DEVICE_MANAGEMENT_TYPE.equals(type.toLowerCase())) {
carbonAppUploaderStub = new CarbonAppUploaderStub(Utils.replaceSystemProperty(
IOT_MGT_URL));
Options appUploaderOptions = carbonAppUploaderStub._getServiceClient().getOptions();
if (appUploaderOptions == null) {
appUploaderOptions = new Options();
}
appUploaderOptions.setProperty(HTTPConstants.HTTP_HEADERS, list);
appUploaderOptions.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER
, new Protocol(DEFAULT_HTTP_PROTOCOL,
(ProtocolSocketFactory) new SSLProtocolSocketFactory
(sslContext), Integer.parseInt(Utils.replaceSystemProperty(
IOT_MGT_PORT))));
if (!DEVICE_MANAGEMENT_TYPE.equals(type.toLowerCase())) {
carbonAppUploaderStub._getServiceClient().setOptions(appUploaderOptions);
carbonAppUploaderStub.uploadApp(uploadedFileItems);
} else {
carbonAppUploaderStub = new CarbonAppUploaderStub(Utils.replaceSystemProperty(DAS_URL));
appUploaderOptions = carbonAppUploaderStub._getServiceClient().getOptions();
Options appUploaderOptions = carbonAppUploaderStub._getServiceClient().getOptions();
if (appUploaderOptions == null) {
appUploaderOptions = new Options();
}
@ -198,72 +249,30 @@ public class DeviceTypePublisherAdminServiceImpl implements DeviceTypePublisherA
carbonAppUploaderStub._getServiceClient().setOptions(appUploaderOptions);
carbonAppUploaderStub.uploadApp(uploadedFileItems);
}
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
Registry registry = DeviceMgtAPIUtils.getRegistryService().getConfigSystemRegistry(tenantId);
if (!registry.resourceExists(DEFAULT_RESOURCE_LOCATION + type + ".exist")) {
Resource resource = new ResourceImpl();
resource.setContent("</exist>");
resource.setMediaType(MEDIA_TYPE_XML);
registry.put(DEFAULT_RESOURCE_LOCATION + type + ".exist", resource);
}
}
if(!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) {
publishDynamicEventReceivers(type, tenantDomain);
}
publishDynamicEventReceivers(type,MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);
publishDynamicEventStream(type,MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);
} else {
return Response.status(Response.Status.BAD_REQUEST)
.entity("\"Error, Artifact does not exist.\"").build();
}
} catch (Exception e) {
log.error("Capp deployment failed due to " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
"\"Error, Artifact deployment has failed\"").build();
}
return Response.status(Response.Status.CREATED).entity("\"OK. \\n Successfully uploaded the artifacts.\"")
.build();
}
@GET
@Path("/deploy/{type}/status")
@Override
public Response getStatus(@PathParam("type") String deviceType) {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
Registry registry = null;
try {
registry = DeviceMgtAPIUtils.getRegistryService().getConfigSystemRegistry(tenantId);
if (registry.resourceExists(DEFAULT_RESOURCE_LOCATION + deviceType + ".exist")) {
return Response.status(Response.Status.OK).entity("Exist").build();
} else {
return Response.status(Response.Status.NO_CONTENT).entity("Does not Exist").build();
return true;
}
} catch (RegistryException e) {
log.error("Registry failed to load." + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
"\"Error, Artifact status check has failed\"").build();
return false;
} finally {
cleanup(carbonAppUploaderStub);
}
}
private void publishDynamicEventReceivers(String deviceType, String tenantDomain, List<String> receiversList)
throws IOException, UserStoreException, JWTClientException {
private void publishDynamicEventReceivers(String deviceType, String tenantDomain){
PrivilegedCarbonContext.getThreadLocalCarbonContext().startTenantFlow();
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true);
EventReceiverAdminServiceStub receiverAdminServiceStub = null;
try {
EventReceiverAdminServiceStub receiverAdminServiceStub = new EventReceiverAdminServiceStub(Utils.replaceSystemProperty(DAS_EVENT_RECEIVER_EP));
receiverAdminServiceStub = new EventReceiverAdminServiceStub
(Utils.replaceSystemProperty(DAS_EVENT_RECEIVER_EP));
Options eventReciverOptions = receiverAdminServiceStub._getServiceClient().getOptions();
if (eventReciverOptions == null) {
eventReciverOptions = new Options();
}
String username=null;
String username;
if(!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) {
username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
.getRealmConfiguration().getAdminUserName()+"@"+tenantDomain;
@ -278,7 +287,7 @@ public class DeviceTypePublisherAdminServiceImpl implements DeviceTypePublisherA
String authValue = AUTHORIZATION_HEADER_VALUE + " " + new String(Base64.encodeBase64(
jwtClient.getJwtToken(username).getBytes()));
List<Header> list = new ArrayList<Header>();
List<Header> list = new ArrayList<>();
Header httpHeader = new Header();
httpHeader.setName(AUTHORIZATION_HEADER);
httpHeader.setValue(authValue);
@ -287,40 +296,28 @@ public class DeviceTypePublisherAdminServiceImpl implements DeviceTypePublisherA
eventReciverOptions.setProperty(HTTPConstants.HTTP_HEADERS, list);
eventReciverOptions.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER
, new Protocol(DEFAULT_HTTP_PROTOCOL
, (ProtocolSocketFactory) new SSLProtocolSocketFactory(sslContext)
, Integer.parseInt(Utils.replaceSystemProperty(DAS_PORT))));
, (ProtocolSocketFactory) new SSLProtocolSocketFactory(sslContext)
, Integer.parseInt(Utils.replaceSystemProperty(DAS_PORT))));
receiverAdminServiceStub._getServiceClient().setOptions(eventReciverOptions);
List<String> receiversList = getReceiversList(deviceType);
for (String receiverContent:receiversList) {
receiverAdminServiceStub.deployEventReceiverConfiguration(receiverContent);
}
} catch (AxisFault e) {
log.error("publishing dynamic event receiver is failed due to " + e.getMessage(), e);
} catch (RemoteException e) {
log.error("publishing dynamic event receiver is failed due to " + e.getMessage(), e);
} catch (IOException e) {
log.error("publishing dynamic event receiver is failed due to " + e.getMessage(), e);
} catch (JWTClientException e) {
log.error("publishing dynamic event receiver is failed due to " + e.getMessage(), e);
} catch (UserStoreException e) {
log.error("publishing dynamic event receiver is failed due to " + e.getMessage(), e);
} finally {
cleanup(receiverAdminServiceStub);
PrivilegedCarbonContext.endTenantFlow();
}
}
private void publishDynamicEventStream(String deviceType, String tenantDomain, List<String> streamList)
throws IOException, UserStoreException, JWTClientException, ParseException {
private void publishDynamicEventStream(String deviceType, String tenantDomain){
PrivilegedCarbonContext.getThreadLocalCarbonContext().startTenantFlow();
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true);
EventStreamAdminServiceStub eventStreamAdminServiceStub = null;
try {
EventStreamAdminServiceStub eventStreamAdminServiceStub = new EventStreamAdminServiceStub(Utils.replaceSystemProperty(DAS_EVENT_RECEIVER_EP));
eventStreamAdminServiceStub = new EventStreamAdminServiceStub
(Utils.replaceSystemProperty(DAS_EVENT_STREAM_EP));
Options eventReciverOptions = eventStreamAdminServiceStub._getServiceClient().getOptions();
if (eventReciverOptions == null) {
eventReciverOptions = new Options();
@ -340,7 +337,7 @@ public class DeviceTypePublisherAdminServiceImpl implements DeviceTypePublisherA
String authValue = AUTHORIZATION_HEADER_VALUE + " " + new String(Base64.encodeBase64(
jwtClient.getJwtToken(username).getBytes()));
List<Header> list = new ArrayList<Header>();
List<Header> list = new ArrayList<>();
Header httpHeader = new Header();
httpHeader.setName(AUTHORIZATION_HEADER);
httpHeader.setValue(authValue);
@ -349,45 +346,32 @@ public class DeviceTypePublisherAdminServiceImpl implements DeviceTypePublisherA
eventReciverOptions.setProperty(HTTPConstants.HTTP_HEADERS, list);
eventReciverOptions.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER
, new Protocol(DEFAULT_HTTP_PROTOCOL
, (ProtocolSocketFactory) new SSLProtocolSocketFactory(sslContext)
, Integer.parseInt(Utils.replaceSystemProperty(DAS_PORT))));
, (ProtocolSocketFactory) new SSLProtocolSocketFactory(sslContext)
, Integer.parseInt(Utils.replaceSystemProperty(DAS_PORT))));
eventStreamAdminServiceStub._getServiceClient().setOptions(eventReciverOptions);
List<String> streamList = getStreamsList(deviceType);
for (String streamContent:streamList) {
JSONParser jsonParser = new JSONParser();
JSONObject steamJson = (JSONObject)jsonParser.parse(streamContent);
String name = (String) steamJson.get("name");
String version = (String) steamJson.get("version");
String streamId = name +":"+version;
if(eventStreamAdminServiceStub.getStreamDefinitionAsString(streamId)==null) {
if (eventStreamAdminServiceStub.getStreamDefinitionDto(streamId) == null) {
eventStreamAdminServiceStub.addEventStreamDefinitionAsString(streamContent);
}
}
} catch (AxisFault e) {
log.error("publishing dynamic event receiver is failed due to " + e.getMessage(), e);
} catch (RemoteException e) {
log.error("publishing dynamic event receiver is failed due to " + e.getMessage(), e);
} catch (IOException e) {
log.error("publishing dynamic event receiver is failed due to " + e.getMessage(), e);
} catch (JWTClientException e) {
log.error("publishing dynamic event receiver is failed due to " + e.getMessage(), e);
} catch (UserStoreException e) {
log.error("publishing dynamic event receiver is failed due to " + e.getMessage(), e);
} catch (ParseException e) {
log.error("publishing dynamic event receiver is failed due to " + e.getMessage(), e);
} finally {
cleanup(eventStreamAdminServiceStub);
PrivilegedCarbonContext.endTenantFlow();
}
}
private List<String> getReceiversList(String deviceType) throws IOException {
File directory = new File(CAR_FILE_LOCATION + File.separator + deviceType+File.separator+"receiver");
if (!directory.exists()) {
return null;
}
File[] receiverFiles = directory.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
@ -396,8 +380,8 @@ public class DeviceTypePublisherAdminServiceImpl implements DeviceTypePublisherA
});
List<String> receiverList = new ArrayList<>();
for (File receiverFile:receiverFiles) {
String receiverContent =new String(Files.readAllBytes(receiverFile.toPath()));
receiverContent.replaceAll(TENANT_DOMAIN_PROPERTY,tenantDomain.toLowerCase());
String receiverContentTemplate =new String(Files.readAllBytes(receiverFile.toPath()));
final String receiverContent = receiverContentTemplate.replaceAll(TENANT_DOMAIN_PROPERTY, tenantDomain.toLowerCase());
receiverList.add(receiverContent);
}
@ -405,8 +389,10 @@ public class DeviceTypePublisherAdminServiceImpl implements DeviceTypePublisherA
}
private List<String> getStreamsList(String deviceType) throws IOException {
File directory = new File(CAR_FILE_LOCATION + File.separator + deviceType+File.separator+"streams");
if (!directory.exists()) {
return null;
}
File[] receiverFiles = directory.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
@ -415,11 +401,9 @@ public class DeviceTypePublisherAdminServiceImpl implements DeviceTypePublisherA
});
List<String> streamList = new ArrayList<>();
for (File StreamFile:receiverFiles) {
String receiverContent =new String(Files.readAllBytes(StreamFile.toPath()));
receiverContent.replaceAll(TENANT_DOMAIN_PROPERTY,tenantDomain.toLowerCase());
streamList.add(receiverContent);
String streamContent =new String(Files.readAllBytes(StreamFile.toPath()));
streamList.add(streamContent);
}
return streamList;
}
@ -507,6 +491,15 @@ public class DeviceTypePublisherAdminServiceImpl implements DeviceTypePublisherA
SSLContext.setDefault(sslContext);
}
private void cleanup(Stub stub) {
if (stub != null) {
try {
stub.cleanup();
} catch (AxisFault axisFault) {
//do nothing
}
}
}
}

@ -40,8 +40,8 @@
<ref bean="applicationManagementAdminService"/>
<ref bean="deviceTypeManagementAdminService"/>
<ref bean="deviceTypeManagementAdminService"/>
<ref bean="deviceTypePublisherAdminService"/>
<ref bean="deviceEventManagementService"/>
<ref bean="deviceAnalyticsArtifactUploaderAdminService"/>
<ref bean="deviceEventManagementService"/>\
<ref bean="swaggerResource"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
@ -83,9 +83,8 @@
<bean id="userManagementAdminService" class="org.wso2.carbon.device.mgt.jaxrs.service.impl.admin.UserManagementAdminServiceImpl"/>
<bean id="deviceTypeManagementAdminService" class="org.wso2.carbon.device.mgt.jaxrs.service.impl.DeviceTypeManagementServiceImpl"/>
<bean id="deviceAccessAuthorizationAdminService" class="org.wso2.carbon.device.mgt.jaxrs.service.impl.admin.DeviceAccessAuthorizationAdminServiceImpl"/>
<bean id="deviceTypePublisherAdminService" class="org.wso2.carbon.device.mgt.jaxrs.service.impl.admin.DeviceTypePublisherAdminServiceImpl"/>
<bean id="deviceAnalyticsArtifactUploaderAdminService" class="org.wso2.carbon.device.mgt.jaxrs.service.impl.admin.DeviceAnalyticsArtifactUploaderAdminServiceImpl"/>
<bean id="deviceEventManagementService" class="org.wso2.carbon.device.mgt.jaxrs.service.impl.DeviceEventManagementServiceImpl"/>
<bean id="jsonProvider" class="org.wso2.carbon.device.mgt.jaxrs.common.GsonMessageBodyHandler"/>
<!--<bean id="errorHandler" class="org.wso2.carbon.device.mgt.jaxrs.common.ErrorHandler"/>-->

@ -21,7 +21,7 @@
<parent>
<artifactId>device-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -157,4 +157,13 @@ public interface DeviceManager {
*/
boolean requireDeviceAuthorization();
/**
* This method returns the default configuration values which is stored in the configuration file
* rather than fetching from the registry.
*
* @return Returns Default PlatformConfiguration
* @throws DeviceManagementException
*/
PlatformConfiguration getDefaultConfiguration() throws DeviceManagementException;
}

@ -117,7 +117,7 @@ public class EnrolmentInfo implements Serializable {
if (obj instanceof EnrolmentInfo) {
EnrolmentInfo tempInfo = (EnrolmentInfo) obj;
if (this.owner != null && this.ownership != null) {
if (this.owner.equals(tempInfo.getOwner()) && this.ownership.equals(tempInfo.getOwnership())) {
if (this.owner.equalsIgnoreCase(tempInfo.getOwner()) && this.ownership.equals(tempInfo.getOwnership())) {
return true;
}
}

@ -21,6 +21,7 @@ import org.wso2.carbon.device.mgt.common.*;
import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy;
import java.util.List;
import java.util.Map;
/**
* This represents the Device Operation management functionality which should be implemented by

@ -31,4 +31,10 @@ public interface NotificationStrategy {
*/
void undeploy();
/**
* Provides push notification configuration
*
*/
PushNotificationConfig getConfig();
}

@ -26,11 +26,13 @@ import java.util.Map;
public class PushNotificationConfig {
private String type;
private boolean isScheduled;
Map<String, String> properties;
public PushNotificationConfig(String type, Map<String, String> properties) {
public PushNotificationConfig(String type, boolean isScheduled, Map<String, String> properties) {
this.type = type;
this.properties = properties;
this.isScheduled = isScheduled;
}
@XmlElement(name = "Type", required = true)
@ -38,6 +40,11 @@ public class PushNotificationConfig {
return type;
}
@XmlElement(name = "isScheduled")
public boolean isScheduled() {
return isScheduled;
}
public Map<String, String> getProperties() {
return properties;
}

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>device-mgt</artifactId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -86,4 +86,13 @@ public final class DeviceManagementConstants {
public static final String ACTIVITY = "ACTIVITY_";
}
public static final class PushNotifications {
private PushNotifications() {
throw new AssertionError();
}
public static final int DEFAULT_SCHEDULER_TASK_INITIAL_DELAY = 60000;
public static final int DEFAULT_BATCH_DELAY_MILLS = 60000;
public static final int DEFAULT_BATCH_SIZE = 1000;
}
}

@ -20,6 +20,7 @@ package org.wso2.carbon.device.mgt.core.config;
import org.wso2.carbon.device.mgt.core.config.identity.IdentityConfigurations;
import org.wso2.carbon.device.mgt.core.config.pagination.PaginationConfiguration;
import org.wso2.carbon.device.mgt.core.config.policy.PolicyConfiguration;
import org.wso2.carbon.device.mgt.core.config.push.notification.PushNotificationConfiguration;
import org.wso2.carbon.device.mgt.core.config.task.TaskConfiguration;
import javax.xml.bind.annotation.XmlElement;
@ -39,7 +40,7 @@ public final class DeviceManagementConfig {
private IdentityConfigurations identityConfigurations;
private PolicyConfiguration policyConfiguration;
private PaginationConfiguration paginationConfiguration;
private List<String> pushNotificationProviders;
private PushNotificationConfiguration pushNotificationConfiguration;
@XmlElement(name = "ManagementRepository", required = true)
@ -79,16 +80,6 @@ public final class DeviceManagementConfig {
this.taskConfiguration = taskConfiguration;
}
@XmlElementWrapper(name = "PushNotificationProviders", required = true)
@XmlElement(name = "Provider", required = true)
public List<String> getPushNotificationProviders() {
return pushNotificationProviders;
}
public void setPushNotificationProviders(List<String> pushNotificationProviders) {
this.pushNotificationProviders = pushNotificationProviders;
}
@XmlElement(name = "PaginationConfiguration", required = true)
public PaginationConfiguration getPaginationConfiguration() {
return paginationConfiguration;
@ -98,5 +89,13 @@ public final class DeviceManagementConfig {
this.paginationConfiguration = paginationConfiguration;
}
@XmlElement(name = "PushNotificationConfiguration", required = true)
public PushNotificationConfiguration getPushNotificationConfiguration() {
return pushNotificationConfiguration;
}
public void setPushNotificationConfiguration(PushNotificationConfiguration pushNotificationConfiguration) {
this.pushNotificationConfiguration = pushNotificationConfiguration;
}
}

@ -0,0 +1,82 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.core.config.push.notification;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;
/**
* This class is for Push notification related Configurations
*/
@XmlRootElement(name = "PushNotificationConfiguration")
public class PushNotificationConfiguration {
private int schedulerBatchSize;
private int schedulerBatchDelayMills;
private int schedulerTaskInitialDelay;
private boolean schedulerTaskEnabled;
private List<String> pushNotificationProviders;
@XmlElement(name = "SchedulerBatchSize", required = true)
public int getSchedulerBatchSize() {
return schedulerBatchSize;
}
public void setSchedulerBatchSize(int schedulerBatchSize) {
this.schedulerBatchSize = schedulerBatchSize;
}
@XmlElement(name = "SchedulerBatchDelayMills", required = true)
public int getSchedulerBatchDelayMills() {
return schedulerBatchDelayMills;
}
public void setSchedulerBatchDelayMills(int schedulerBatchDelayMills) {
this.schedulerBatchDelayMills = schedulerBatchDelayMills;
}
@XmlElement(name = "SchedulerTaskInitialDelay", required = true)
public int getSchedulerTaskInitialDelay() {
return schedulerTaskInitialDelay;
}
public void setSchedulerTaskInitialDelay(int schedulerTaskInitialDelay) {
this.schedulerTaskInitialDelay = schedulerTaskInitialDelay;
}
@XmlElement(name = "SchedulerTaskEnabled", required = true)
public boolean isSchedulerTaskEnabled() {
return schedulerTaskEnabled;
}
public void setSchedulerTaskEnabled(boolean schedulerTaskEnabled) {
this.schedulerTaskEnabled = schedulerTaskEnabled;
}
@XmlElementWrapper(name = "PushNotificationProviders", required = true)
@XmlElement(name = "Provider", required = true)
public List<String> getPushNotificationProviders() {
return pushNotificationProviders;
}
public void setPushNotificationProviders(List<String> pushNotificationProviders) {
this.pushNotificationProviders = pushNotificationProviders;
}
}

@ -122,7 +122,7 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO {
"e.DATE_OF_ENROLMENT, e.ID AS ENROLMENT_ID FROM DM_ENROLMENT e, (SELECT d.ID, d.DESCRIPTION, d.NAME, " +
"t.NAME AS DEVICE_TYPE, d.DEVICE_IDENTIFICATION FROM DM_DEVICE d, DM_DEVICE_TYPE t WHERE " +
"t.NAME = ? AND d.DEVICE_IDENTIFICATION = ? AND d.TENANT_ID = ?) d1 WHERE d1.ID = e.DEVICE_ID " +
"AND TENANT_ID = ?";
"AND TENANT_ID = ? ORDER BY e.DATE_OF_LAST_UPDATE DESC";
stmt = conn.prepareStatement(sql);
stmt.setString(1, deviceIdentifier.getType());
stmt.setString(2, deviceIdentifier.getId());
@ -223,7 +223,7 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO {
"d1.DEVICE_IDENTIFICATION, e.OWNER, e.OWNERSHIP, e.STATUS, e.DATE_OF_LAST_UPDATE, " +
"e.DATE_OF_ENROLMENT, e.ID AS ENROLMENT_ID FROM DM_ENROLMENT e, (SELECT d.ID, d.DESCRIPTION, d.NAME, " +
"t.NAME AS DEVICE_TYPE, d.DEVICE_IDENTIFICATION FROM DM_DEVICE d, DM_DEVICE_TYPE t WHERE " +
"t.NAME = ? AND d.DEVICE_IDENTIFICATION = ? ) d1 WHERE d1.ID = e.DEVICE_ID ";
"t.NAME = ? AND d.DEVICE_IDENTIFICATION = ? ) d1 WHERE d1.ID = e.DEVICE_ID ORDER BY e.DATE_OF_LAST_UPDATE DESC";
stmt = conn.prepareStatement(sql);
stmt.setString(1, deviceIdentifier.getType());
stmt.setString(2, deviceIdentifier.getId());
@ -254,7 +254,7 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO {
"e.DATE_OF_ENROLMENT, e.ID AS ENROLMENT_ID FROM DM_ENROLMENT e, (SELECT d.ID, d.DESCRIPTION, d.NAME, " +
"t.NAME AS DEVICE_TYPE, d.DEVICE_IDENTIFICATION FROM DM_DEVICE d, DM_DEVICE_TYPE t WHERE " +
"d.ID = ? AND d.TENANT_ID = ?) d1 WHERE d1.ID = e.DEVICE_ID " +
"AND TENANT_ID = ?";
"AND TENANT_ID = ? ORDER BY e.DATE_OF_LAST_UPDATE DESC";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, deviceId);
stmt.setInt(2, tenantId);

@ -35,6 +35,10 @@ public class Operation implements Serializable {
REPEAT, NO_REPEAT, PAUSE_SEQUENCE, STOP_SEQUENCE
}
public enum PushNotificationStatus {
SCHEDULED, COMPLETED
}
private String code;
private Properties properties;
private Type type;

@ -48,6 +48,7 @@ import org.wso2.carbon.device.mgt.core.operation.mgt.OperationManagerImpl;
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory;
import org.wso2.carbon.device.mgt.core.permission.mgt.PermissionManagerServiceImpl;
import org.wso2.carbon.device.mgt.core.push.notification.mgt.PushNotificationProviderRepository;
import org.wso2.carbon.device.mgt.core.push.notification.mgt.task.PushNotificationSchedulerTask;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderServiceImpl;
import org.wso2.carbon.device.mgt.core.service.GroupManagementProviderService;
@ -62,6 +63,9 @@ import org.wso2.carbon.utils.ConfigurationContextService;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* @scr.component name="org.wso2.carbon.device.manager" immediate="true"
@ -151,7 +155,8 @@ public class DeviceManagementServiceComponent {
this.initOperationsManager();
PushNotificationProviderRepository pushNotificationRepo = new PushNotificationProviderRepository();
List<String> pushNotificationProviders = config.getPushNotificationProviders();
List<String> pushNotificationProviders = config.getPushNotificationConfiguration()
.getPushNotificationProviders();
if (pushNotificationProviders != null) {
for (String pushNoteProvider : pushNotificationProviders) {
pushNotificationRepo.addProvider(pushNoteProvider);
@ -176,6 +181,36 @@ public class DeviceManagementServiceComponent {
/* This is a workaround to initialize all Device Management Service Providers after the initialization
* of Device Management Service component in order to avoid bundle start up order related complications */
notifyStartupListeners();
if (log.isDebugEnabled()) {
log.debug("Push notification batch enabled : " + config.getPushNotificationConfiguration()
.isSchedulerTaskEnabled());
}
// Start Push Notification Scheduler Task
if (config.getPushNotificationConfiguration().isSchedulerTaskEnabled()) {
if (config.getPushNotificationConfiguration().getSchedulerBatchSize() <= 0) {
log.error("Push notification batch size cannot be 0 or less than 0. Setting default batch size " +
"to:" + DeviceManagementConstants.PushNotifications.DEFAULT_BATCH_SIZE);
config.getPushNotificationConfiguration().setSchedulerBatchSize(DeviceManagementConstants
.PushNotifications.DEFAULT_BATCH_SIZE);
}
if (config.getPushNotificationConfiguration().getSchedulerBatchDelayMills() <= 0) {
log.error("Push notification batch delay cannot be 0 or less than 0. Setting default batch delay " +
"milliseconds to" + DeviceManagementConstants.PushNotifications.DEFAULT_BATCH_DELAY_MILLS);
config.getPushNotificationConfiguration().setSchedulerBatchDelayMills(DeviceManagementConstants
.PushNotifications.DEFAULT_BATCH_DELAY_MILLS);
}
if (config.getPushNotificationConfiguration().getSchedulerTaskInitialDelay() < 0) {
log.error("Push notification initial delay cannot be less than 0. Setting default initial " +
"delay milliseconds to" + DeviceManagementConstants.PushNotifications
.DEFAULT_SCHEDULER_TASK_INITIAL_DELAY);
config.getPushNotificationConfiguration().setSchedulerTaskInitialDelay(DeviceManagementConstants
.PushNotifications.DEFAULT_SCHEDULER_TASK_INITIAL_DELAY);
}
ScheduledExecutorService pushNotificationExecutor = Executors.newSingleThreadScheduledExecutor();
pushNotificationExecutor.scheduleWithFixedDelay(new PushNotificationSchedulerTask(), config
.getPushNotificationConfiguration().getSchedulerTaskInitialDelay(), config
.getPushNotificationConfiguration().getSchedulerBatchDelayMills(), TimeUnit.MILLISECONDS);
}
if (log.isDebugEnabled()) {
log.debug("Device management core bundle has been successfully initialized");
}
@ -269,7 +304,7 @@ public class DeviceManagementServiceComponent {
try {
if (log.isDebugEnabled()) {
log.debug("Setting Device Management Service Provider: '" +
deviceManagementService.getType() + "'");
deviceManagementService.getType() + "'");
}
synchronized (LOCK) {
deviceManagers.add(deviceManagementService);
@ -278,10 +313,10 @@ public class DeviceManagementServiceComponent {
}
}
log.info("Device Type deployed successfully : " + deviceManagementService.getType() + " for tenant "
+ deviceManagementService.getProvisioningConfig().getProviderTenantDomain());
+ deviceManagementService.getProvisioningConfig().getProviderTenantDomain());
} catch (Throwable e) {
log.error("Failed to register device management service for device type" + deviceManagementService.getType() +
" for tenant " + deviceManagementService.getProvisioningConfig().getProviderTenantDomain(), e);
" for tenant " + deviceManagementService.getProvisioningConfig().getProviderTenantDomain(), e);
}
}

@ -40,6 +40,7 @@ import org.wso2.carbon.device.mgt.common.push.notification.NotificationContext;
import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy;
import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationExecutionFailedException;
import org.wso2.carbon.device.mgt.core.DeviceManagementConstants;
import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager;
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;
@ -130,7 +131,7 @@ public class OperationManagerImpl implements OperationManager {
DeviceIDHolder deviceAuthorizationResult = this.authorizeDevices(operation, validDeviceIds);
List<DeviceIdentifier> authorizedDeviceList = deviceAuthorizationResult.getValidDeviceIDList();
if (authorizedDeviceList.size() <= 0) {
log.info("User : " + getUser() + " is not authorized to perform operations on given device-list.");
log.warn("User : " + getUser() + " is not authorized to perform operations on given device-list.");
Activity activity = new Activity();
//Send the operation statuses only for admin triggered operations
String deviceType = validDeviceIds.get(0).getType();
@ -145,6 +146,16 @@ public class OperationManagerImpl implements OperationManager {
int operationId = this.lookupOperationDAO(operation).addOperation(operationDto);
boolean isScheduledOperation = this.isTaskScheduledOperation(operation, deviceIds);
boolean isNotRepeated = false;
boolean isScheduled = false;
// check whether device list is greater than batch size notification strategy has enable to send push
// notification using scheduler task
if (DeviceConfigurationManager.getInstance().getDeviceManagementConfig().
getPushNotificationConfiguration().getSchedulerBatchSize() < authorizedDeviceList.size() &&
notificationStrategy != null) {
isScheduled = notificationStrategy.getConfig().isScheduled();
}
boolean hasExistingTaskOperation;
int enrolmentId;
if (org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Control.NO_REPEAT == operationDto.
@ -161,7 +172,7 @@ public class OperationManagerImpl implements OperationManager {
if (isScheduledOperation) {
hasExistingTaskOperation = operationDAO.updateTaskOperation(enrolmentId, operationCode);
if (!hasExistingTaskOperation) {
operationMappingDAO.addOperationMapping(operationId, enrolmentId);
operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled);
}
} else if (isNotRepeated) {
operationDAO.updateEnrollmentOperationsStatus(enrolmentId, operationCode,
@ -169,17 +180,27 @@ public class OperationManagerImpl implements OperationManager {
Operation.Status.PENDING,
org.wso2.carbon.device.mgt.core.dto.operation.mgt.
Operation.Status.REPEATED);
operationMappingDAO.addOperationMapping(operationId, enrolmentId);
operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled);
} else {
operationMappingDAO.addOperationMapping(operationId, enrolmentId);
operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled);
}
if (notificationStrategy != null) {
/*
If notification strategy has not enable to send push notification using scheduler task
we will send notification immediately
*/
if (notificationStrategy != null && !isScheduled) {
try {
if (log.isDebugEnabled()) {
log.debug("Sending push notification to " + deviceId + " from add operation method.");
}
notificationStrategy.execute(new NotificationContext(deviceId, operation));
operationMappingDAO.updateOperationMapping(operationId, enrolmentId, org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.PushNotificationStatus.COMPLETED);
} catch (PushNotificationExecutionFailedException e) {
log.error("Error occurred while sending push notifications to " +
deviceId.getType() + " device carrying id '" +
deviceId + "'", e);
// Reschedule if push notification failed.
operationMappingDAO.updateOperationMapping(operationId, enrolmentId, org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.PushNotificationStatus.SCHEDULED);
}
}
}

@ -0,0 +1,73 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.core.operation.mgt;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation;
/**
* Class for represent operation mapping
*/
public class OperationMapping {
private DeviceIdentifier deviceIdentifier;
private int operationId;
private int tenantId;
private Operation.Status status;
private Operation.PushNotificationStatus pushNotificationStatus;
public int getOperationId() {
return operationId;
}
public void setOperationId(int operationId) {
this.operationId = operationId;
}
public int getTenantId() {
return tenantId;
}
public void setTenantId(int tenantId) {
this.tenantId = tenantId;
}
public DeviceIdentifier getDeviceIdentifier() {
return deviceIdentifier;
}
public void setDeviceIdentifier(DeviceIdentifier deviceIdentifier) {
this.deviceIdentifier = deviceIdentifier;
}
public Operation.Status getStatus() {
return status;
}
public void setStatus(Operation.Status status) {
this.status = status;
}
public Operation.PushNotificationStatus getPushNotificationStatus() {
return pushNotificationStatus;
}
public void setPushNotificationStatus(Operation.PushNotificationStatus pushNotificationStatus) {
this.pushNotificationStatus = pushNotificationStatus;
}
}

@ -20,10 +20,12 @@ package org.wso2.carbon.device.mgt.core.operation.mgt.dao;
import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationResponse;
import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation;
import java.util.List;
import java.util.Map;
public interface OperationDAO {
@ -80,4 +82,15 @@ public interface OperationDAO {
boolean resetAttemptCount(int enrolmentId) throws OperationManagementDAOException;
/**
* This method provides operation mappings for given status
* @param opStatus Operation status
* @param pushNotificationStatus Push notification Status
* @param limit Limit for no devices
* @return Tenant based operation mappings list
* @throws OperationManagementDAOException
*/
Map<Integer, List<OperationMapping>> getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushNotificationStatus pushNotificationStatus,
int limit) throws OperationManagementDAOException;
}

@ -18,10 +18,20 @@
*/
package org.wso2.carbon.device.mgt.core.operation.mgt.dao;
import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping;
import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation;
import java.util.List;
public interface OperationMappingDAO {
void addOperationMapping(int operationId, Integer deviceIds) throws OperationManagementDAOException;
void addOperationMapping(int operationId, Integer deviceId, boolean isScheduled) throws OperationManagementDAOException;
void removeOperationMapping(int operationId, Integer deviceId) throws OperationManagementDAOException;
void removeOperationMapping(int operationId, Integer deviceIds) throws OperationManagementDAOException;
void updateOperationMapping(int operationId, Integer deviceId, Operation.PushNotificationStatus pushNotificationStatus) throws
OperationManagementDAOException;
void updateOperationMapping(List<OperationMapping> operationMappingList) throws
OperationManagementDAOException;
}

@ -26,18 +26,30 @@ import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.common.operation.mgt.ActivityStatus;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationResponse;
import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping;
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationDAO;
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOException;
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory;
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOUtil;
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.util.OperationDAOUtil;
import java.io.*;
import java.sql.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* This class holds the generic implementation of OperationDAO which can be used to support ANSI db syntax.
@ -162,8 +174,8 @@ public class GenericOperationDAOImpl implements OperationDAO {
try {
Connection connection = OperationManagementDAOFactory.getConnection();
String query = "SELECT EOM.ID FROM DM_ENROLMENT_OP_MAPPING AS EOM INNER JOIN DM_OPERATION DM " +
"ON DM.ID = EOM.OPERATION_ID WHERE EOM.ENROLMENT_ID = ? AND DM.OPERATION_CODE = ? AND " +
"EOM.STATUS = ?;";
"ON DM.ID = EOM.OPERATION_ID WHERE EOM.ENROLMENT_ID = ? AND DM.OPERATION_CODE = ? AND " +
"EOM.STATUS = ?;";
stmt = connection.prepareStatement(query);
stmt.setInt(1, enrolmentId);
stmt.setString(2, operationCode);
@ -176,7 +188,7 @@ public class GenericOperationDAOImpl implements OperationDAO {
}
if (id != 0) {
stmt = connection.prepareStatement("UPDATE DM_ENROLMENT_OP_MAPPING SET UPDATED_TIMESTAMP = ? " +
"WHERE ID = ?");
"WHERE ID = ?");
stmt.setLong(1, System.currentTimeMillis() / 1000);
stmt.setInt(2, id);
stmt.executeUpdate();
@ -184,7 +196,7 @@ public class GenericOperationDAOImpl implements OperationDAO {
}
} catch (SQLException e) {
throw new OperationManagementDAOException("Error occurred while update device mapping operation status " +
"metadata", e);
"metadata", e);
} finally {
OperationManagementDAOUtil.cleanupResources(stmt);
}
@ -420,14 +432,13 @@ public class GenericOperationDAOImpl implements OperationDAO {
"WHERE opm.UPDATED_TIMESTAMP > ? \n" +
"AND de.TENANT_ID = ? \n";
if(timestamp == 0){
if (timestamp == 0) {
sql += "ORDER BY opm.OPERATION_ID LIMIT ? OFFSET ?;";
}else{
} else {
sql += "ORDER BY opm.UPDATED_TIMESTAMP asc LIMIT ? OFFSET ?";
}
stmt = conn.prepareStatement(sql);
stmt.setLong(1, timestamp);
@ -1068,7 +1079,7 @@ public class GenericOperationDAOImpl implements OperationDAO {
try {
conn = OperationManagementDAOFactory.getConnection();
String query = "UPDATE DM_POLICY_COMPLIANCE_STATUS SET ATTEMPTS = 0, LAST_REQUESTED_TIME = ? " +
"WHERE ENROLMENT_ID = ? AND TENANT_ID = ?";
"WHERE ENROLMENT_ID = ? AND TENANT_ID = ?";
stmt = conn.prepareStatement(query);
stmt.setTimestamp(1, currentTimestamp);
stmt.setInt(2, enrolmentId);
@ -1082,4 +1093,45 @@ public class GenericOperationDAOImpl implements OperationDAO {
}
return status;
}
@Override
public Map<Integer, List<OperationMapping>> getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushNotificationStatus pushNotificationStatus,
int limit) throws OperationManagementDAOException {
PreparedStatement stmt = null;
ResultSet rs = null;
Connection conn;
OperationMapping operationMapping;
Map<Integer, List<OperationMapping>> operationMappingsTenantMap = new HashMap<>();
try {
conn = OperationManagementDAOFactory.getConnection();
String sql = "SELECT op.ENROLMENT_ID, op.OPERATION_ID, dt.NAME ,d.TENANT_ID FROM DM_DEVICE d, " +
"DM_ENROLMENT_OP_MAPPING op, DM_DEVICE_TYPE dt WHERE op.STATUS = ? AND " +
"op.PUSH_NOTIFICATION_STATUS = ? AND d.DEVICE_TYPE_ID = dt.ID AND d.ID=op.ENROLMENT_ID ORDER BY " +
"op.OPERATION_ID LIMIT ?";
stmt = conn.prepareStatement(sql);
stmt.setString(1, opStatus.toString());
stmt.setString(2, pushNotificationStatus.toString());
stmt.setInt(3, limit);
rs = stmt.executeQuery();
while (rs.next()) {
int tenantID = rs.getInt("TENANT_ID");
List<OperationMapping> operationMappings = operationMappingsTenantMap.get(tenantID);
if (operationMappings == null) {
operationMappings = new LinkedList<>();
operationMappingsTenantMap.put(tenantID, operationMappings);
}
operationMapping = new OperationMapping();
operationMapping.setOperationId(rs.getInt("OPERATION_ID"));
operationMapping.setDeviceIdentifier(new DeviceIdentifier(String.valueOf(rs.getInt("ENROLMENT_ID")),
rs.getString("NAME")));
operationMapping.setTenantId(tenantID);
operationMappings.add(operationMapping);
}
} catch (SQLException e) {
throw new OperationManagementDAOException("SQL error while getting operation mappings from database. ", e);
} finally {
OperationManagementDAOUtil.cleanupResources(stmt, rs);
}
return operationMappingsTenantMap;
}
}

@ -19,6 +19,7 @@
package org.wso2.carbon.device.mgt.core.operation.mgt.dao.impl;
import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping;
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOException;
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory;
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOUtil;
@ -27,23 +28,30 @@ import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationMappingDAO;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
public class OperationMappingDAOImpl implements OperationMappingDAO {
@Override
public void addOperationMapping(int operationId, Integer deviceId) throws OperationManagementDAOException {
public void addOperationMapping(int operationId, Integer deviceId, boolean isScheduled) throws
OperationManagementDAOException {
PreparedStatement stmt = null;
try {
long time = System.currentTimeMillis()/1000;
long time = System.currentTimeMillis() / 1000;
Connection conn = OperationManagementDAOFactory.getConnection();
String sql = "INSERT INTO DM_ENROLMENT_OP_MAPPING(ENROLMENT_ID, OPERATION_ID, STATUS, CREATED_TIMESTAMP, " +
"UPDATED_TIMESTAMP) VALUES (?, ?, ?, ?, ?)";
String sql = "INSERT INTO DM_ENROLMENT_OP_MAPPING(ENROLMENT_ID, OPERATION_ID, STATUS, " +
"PUSH_NOTIFICATION_STATUS, CREATED_TIMESTAMP, UPDATED_TIMESTAMP) VALUES (?, ?, ?, ?, ?, ?)";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, deviceId);
stmt.setInt(2, operationId);
stmt.setString(3, Operation.Status.PENDING.toString());
stmt.setLong(4, time);
if (isScheduled) {
stmt.setString(4, Operation.PushNotificationStatus.SCHEDULED.toString());
} else {
stmt.setString(4, Operation.PushNotificationStatus.COMPLETED.toString());
}
stmt.setLong(5, time);
stmt.setLong(6, time);
stmt.executeUpdate();
} catch (SQLException e) {
throw new OperationManagementDAOException("Error occurred while persisting device operation mappings", e);
@ -54,13 +62,13 @@ public class OperationMappingDAOImpl implements OperationMappingDAO {
@Override
public void removeOperationMapping(int operationId,
Integer deviceIds) throws OperationManagementDAOException {
Integer deviceId) throws OperationManagementDAOException {
PreparedStatement stmt = null;
try {
Connection conn = OperationManagementDAOFactory.getConnection();
String sql = "DELETE FROM DM_ENROLMENT_OP_MAPPING WHERE ENROLMENT_ID = ? AND OPERATION_ID = ?";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, 0);
stmt.setInt(1, deviceId);
stmt.setInt(2, operationId);
stmt.executeUpdate();
} catch (SQLException e) {
@ -70,4 +78,55 @@ public class OperationMappingDAOImpl implements OperationMappingDAO {
}
}
@Override
public void updateOperationMapping(int operationId, Integer deviceId, Operation.PushNotificationStatus pushNotificationStatus) throws OperationManagementDAOException {
PreparedStatement stmt = null;
try {
Connection conn = OperationManagementDAOFactory.getConnection();
String sql = "UPDATE DM_ENROLMENT_OP_MAPPING SET PUSH_NOTIFICATION_STATUS = ? WHERE ENROLMENT_ID = ? and " +
"OPERATION_ID = ?";
stmt = conn.prepareStatement(sql);
stmt.setString(1, pushNotificationStatus.toString());
stmt.setInt(2, deviceId);
stmt.setInt(3, operationId);
stmt.executeUpdate();
} catch (SQLException e) {
throw new OperationManagementDAOException("Error occurred while updating device operation mappings", e);
} finally {
OperationManagementDAOUtil.cleanupResources(stmt, null);
}
}
@Override
public void updateOperationMapping(List<OperationMapping> operationMappingList) throws
OperationManagementDAOException {
PreparedStatement stmt = null;
try {
Connection conn = OperationManagementDAOFactory.getConnection();
String sql = "UPDATE DM_ENROLMENT_OP_MAPPING SET PUSH_NOTIFICATION_STATUS = ? WHERE ENROLMENT_ID = ? and " +
"OPERATION_ID = ?";
stmt = conn.prepareStatement(sql);
if (conn.getMetaData().supportsBatchUpdates()) {
for (OperationMapping operationMapping : operationMappingList) {
stmt.setString(1, operationMapping.getPushNotificationStatus().toString());
stmt.setInt(2, Integer.parseInt(operationMapping.getDeviceIdentifier().getId()));
stmt.setInt(3, operationMapping.getOperationId());
stmt.addBatch();
}
stmt.executeBatch();
} else {
for (OperationMapping operationMapping : operationMappingList) {
stmt.setString(1, operationMapping.getPushNotificationStatus().toString());
stmt.setInt(2, Integer.parseInt(operationMapping.getDeviceIdentifier().getId()));
stmt.setInt(3, operationMapping.getOperationId());
stmt.executeUpdate();
}
}
} catch (SQLException e) {
throw new OperationManagementDAOException("Error occurred while updating device operation mappings as " +
"batch ", e);
} finally {
OperationManagementDAOUtil.cleanupResources(stmt, null);
}
}
}

@ -25,6 +25,7 @@ import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.common.operation.mgt.ActivityStatus;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationResponse;
import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping;
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOException;
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory;
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOUtil;
@ -37,7 +38,10 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* This class holds the implementation of OperationDAO which can be used to support Oracle db syntax.
@ -135,7 +139,7 @@ public class OracleOperationDAOImpl extends GenericOperationDAOImpl {
@Override
public void updateEnrollmentOperationsStatus(int enrolmentId, String operationCode,
Operation.Status existingStatus, Operation.Status newStatus) throws OperationManagementDAOException {
Operation.Status existingStatus, Operation.Status newStatus) throws OperationManagementDAOException {
PreparedStatement stmt = null;
ResultSet rs = null;
try {
@ -361,4 +365,46 @@ public class OracleOperationDAOImpl extends GenericOperationDAOImpl {
}
return 0;
}
@Override
public Map<Integer, List<OperationMapping>> getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushNotificationStatus pushNotificationStatus,
int limit) throws OperationManagementDAOException {
PreparedStatement stmt = null;
ResultSet rs = null;
OperationMapping operationMapping;
Map<Integer, List<OperationMapping>> operationMappingsTenantMap = new HashMap<>();
try {
Connection conn = OperationManagementDAOFactory.getConnection();
String sql = "SELECT op.ENROLMENT_ID, op.OPERATION_ID, dt.NAME ,d.TENANT_ID FROM DM_DEVICE d, " +
"DM_ENROLMENT_OP_MAPPING op, DM_DEVICE_TYPE dt WHERE op.STATUS = ? AND op" +
".PUSH_NOTIFICATION_STATUS = ? AND d.DEVICE_TYPE_ID = dt.ID AND d.ID=op.ENROLMENT_ID AND ROWNUM" +
" <= ? ORDER BY op.OPERATION_ID";
stmt = conn.prepareStatement(sql);
stmt.setString(1, opStatus.toString());
stmt.setString(2, pushNotificationStatus.toString());
stmt.setInt(3, limit);
rs = stmt.executeQuery();
while (rs.next()) {
int tenantID = rs.getInt("TENANT_ID");
List<OperationMapping> operationMappings = operationMappingsTenantMap.get(tenantID);
if (operationMappings == null) {
operationMappings = new LinkedList<>();
operationMappingsTenantMap.put(tenantID, operationMappings);
}
operationMapping = new OperationMapping();
operationMapping.setOperationId(rs.getInt("OPERATION_ID"));
operationMapping.setDeviceIdentifier(new DeviceIdentifier(String.valueOf(rs.getInt("ENROLMENT_ID")),
rs.getString("NAME")));
operationMapping.setTenantId(tenantID);
operationMappings.add(operationMapping);
}
} catch (SQLException e) {
throw new OperationManagementDAOException("SQL error while getting operation mappings from database. ", e);
} finally {
OperationManagementDAOUtil.cleanupResources(stmt, rs);
}
return operationMappingsTenantMap;
}
}

@ -25,6 +25,7 @@ import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.common.operation.mgt.ActivityStatus;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationResponse;
import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping;
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOException;
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory;
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOUtil;
@ -37,7 +38,10 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* This class holds the implementation of OperationDAO which can be used to support SQLServer db syntax.
@ -264,4 +268,43 @@ public class SQLServerOperationDAOImpl extends GenericOperationDAOImpl {
return activities;
}
@Override
public Map<Integer, List<OperationMapping>> getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushNotificationStatus pushNotificationStatus,
int limit) throws OperationManagementDAOException {
PreparedStatement stmt = null;
ResultSet rs = null;
OperationMapping operationMapping;
Map<Integer, List<OperationMapping>> operationMappingsTenantMap = new HashMap<>();
try {
Connection conn = OperationManagementDAOFactory.getConnection();
String sql = "SELECT op.ENROLMENT_ID, op.OPERATION_ID, dt.NAME ,d.TENANT_ID FROM DM_DEVICE d, " +
"DM_ENROLMENT_OP_MAPPING op, DM_DEVICE_TYPE dt WHERE op.STATUS = ? AND op" +
".PUSH_NOTIFICATION_STATUS = ? AND d.DEVICE_TYPE_ID = dt.ID " +
"AND d.ID=op.ENROLMENT_ID ORDER BY op.OPERATION_ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY";
stmt = conn.prepareStatement(sql);
stmt.setString(1, opStatus.toString());
stmt.setString(2, pushNotificationStatus.toString());
stmt.setInt(3, limit);
rs = stmt.executeQuery();
while (rs.next()) {
int tenantID = rs.getInt("TENANT_ID");
List<OperationMapping> operationMappings = operationMappingsTenantMap.get(tenantID);
if (operationMappings == null) {
operationMappings = new LinkedList<>();
operationMappingsTenantMap.put(tenantID, operationMappings);
}
operationMapping = new OperationMapping();
operationMapping.setOperationId(rs.getInt("OPERATION_ID"));
operationMapping.setDeviceIdentifier(new DeviceIdentifier(String.valueOf(rs.getInt("ENROLMENT_ID")),
rs.getString("NAME")));
operationMapping.setTenantId(tenantID);
operationMappings.add(operationMapping);
}
} catch (SQLException e) {
throw new OperationManagementDAOException("SQL error while getting operation mappings from database. ", e);
} finally {
OperationManagementDAOUtil.cleanupResources(stmt, rs);
}
return operationMappingsTenantMap;
}
}

@ -0,0 +1,127 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.core.push.notification.mgt.task;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.TransactionManagementException;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
import org.wso2.carbon.device.mgt.common.push.notification.NotificationContext;
import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy;
import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationExecutionFailedException;
import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager;
import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder;
import org.wso2.carbon.device.mgt.core.operation.mgt.OperationMapping;
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationDAO;
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOException;
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory;
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationMappingDAO;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* ${{@link PushNotificationSchedulerTask}} is for sending push notifications for given device batch.
*/
public class PushNotificationSchedulerTask implements Runnable {
private static Log log = LogFactory.getLog(PushNotificationSchedulerTask.class);
private final OperationDAO operationDAO = OperationManagementDAOFactory.getOperationDAO();
private final OperationMappingDAO operationMappingDAO = OperationManagementDAOFactory.getOperationMappingDAO();
private final DeviceManagementProviderService provider = DeviceManagementDataHolder.getInstance()
.getDeviceManagementProvider();
@Override
public void run() {
try {
Map<Integer, List<OperationMapping>> operationMappingsTenantMap = new HashMap<>();
List<OperationMapping> operationsCompletedList = new LinkedList<>();
if (log.isDebugEnabled()) {
log.debug("Push notification job started");
}
try {
//Get next available operation list per device batch
OperationManagementDAOFactory.openConnection();
operationMappingsTenantMap = operationDAO.getOperationMappingsByStatus(Operation.Status
.PENDING, Operation.PushNotificationStatus.SCHEDULED, DeviceConfigurationManager.getInstance()
.getDeviceManagementConfig().getPushNotificationConfiguration().getSchedulerBatchSize());
} catch (OperationManagementDAOException e) {
log.error("Unable to retrieve scheduled pending operations for task.", e);
} finally {
OperationManagementDAOFactory.closeConnection();
}
// Sending push notification to each device
for (List<OperationMapping> operationMappings : operationMappingsTenantMap.values()) {
for (OperationMapping operationMapping : operationMappings) {
try {
if (log.isDebugEnabled()) {
log.debug("Sending push notification for operationId :" + operationMapping.getOperationId() +
"to deviceId : " + operationMapping.getDeviceIdentifier().getId());
}
// Set tenant id and domain
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(operationMapping.getTenantId(), true);
// Get notification strategy for given device type
NotificationStrategy notificationStrategy = provider.getNotificationStrategyByDeviceType
(operationMapping.getDeviceIdentifier().getType());
// Send the push notification on given strategy
notificationStrategy.execute(new NotificationContext(operationMapping.getDeviceIdentifier(),
provider.getOperation(operationMapping.getDeviceIdentifier().getType(), operationMapping
.getOperationId())));
operationMapping.setPushNotificationStatus(Operation.PushNotificationStatus.COMPLETED);
operationsCompletedList.add(operationMapping);
} catch (DeviceManagementException e) {
log.error("Error occurred while getting notification strategy for operation mapping " +
operationMapping.getDeviceIdentifier().getType(), e);
} catch (OperationManagementException e) {
log.error("Unable to get the operation for operation " + operationMapping.getOperationId(), e);
} catch (PushNotificationExecutionFailedException e) {
log.error("Error occurred while sending push notification to operation: " + operationMapping
.getOperationId(), e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
}
// Update push notification status to competed for operations which already sent
if (operationsCompletedList.size() > 0) {
try {
OperationManagementDAOFactory.beginTransaction();
operationMappingDAO.updateOperationMapping(operationsCompletedList);
OperationManagementDAOFactory.commitTransaction();
} catch (TransactionManagementException | OperationManagementDAOException e) {
OperationManagementDAOFactory.rollbackTransaction();
log.error("Error occurred while updating operation mappings for sent notifications ", e);
} finally {
OperationManagementDAOFactory.closeConnection();
}
}
if (log.isDebugEnabled()) {
log.debug("Push notification job running completed.");
}
} catch (Throwable cause) {
log.error("PushNotificationSchedulerTask failed due to " + cause);
}
}
}

@ -32,6 +32,7 @@ import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
import org.wso2.carbon.device.mgt.common.policy.mgt.PolicyMonitoringManager;
import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy;
import java.util.Date;
import java.util.HashMap;
@ -130,7 +131,8 @@ public interface DeviceManagementProviderService {
/**
* This method returns the list of device owned by a user of given device type.
* @param userName user name.
*
* @param userName user name.
* @param deviceType device type name
* @return
* @throws DeviceManagementException
@ -210,13 +212,21 @@ public interface DeviceManagementProviderService {
* This method is used to check whether the device is enrolled with the give user.
*
* @param deviceId identifier of the device that needs to be checked against the user.
* @param user username of the device owner.
*
* @param user username of the device owner.
* @return true if the user owns the device else will return false.
* @throws DeviceManagementException If some unusual behaviour is observed while fetching the device.
*/
boolean isEnrolled(DeviceIdentifier deviceId, String user) throws DeviceManagementException;
/**
* This method is used to get notification strategy for given device type
*
* @param deviceType Device type
* @return Notification Strategy for device type
* @throws DeviceManagementException
*/
NotificationStrategy getNotificationStrategyByDeviceType(String deviceType) throws DeviceManagementException;
License getLicense(String deviceType, String languageCode) throws DeviceManagementException;
void addLicense(String deviceType, License license) throws DeviceManagementException;
@ -239,6 +249,7 @@ public interface DeviceManagementProviderService {
/**
* Returns the device of specified id.
*
* @param deviceId device Id
* @return Device returns null when device is not avaialble.
* @throws DeviceManagementException

@ -23,7 +23,21 @@ import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.CarbonConstants;
import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.*;
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.DeviceManager;
import org.wso2.carbon.device.mgt.common.DeviceNotFoundException;
import org.wso2.carbon.device.mgt.common.DeviceTypeIdentifier;
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.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.TransactionManagementException;
import org.wso2.carbon.device.mgt.common.app.mgt.Application;
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration;
import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo;
@ -37,7 +51,9 @@ import org.wso2.carbon.device.mgt.common.license.mgt.LicenseManagementException;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManager;
import org.wso2.carbon.device.mgt.common.policy.mgt.PolicyMonitoringManager;
import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy;
import org.wso2.carbon.device.mgt.common.spi.DeviceManagementService;
import org.wso2.carbon.device.mgt.core.DeviceManagementConstants;
import org.wso2.carbon.device.mgt.core.DeviceManagementPluginRepository;
@ -307,7 +323,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
return enrolmentInfos;
}
@Override
@Override
public boolean disenrollDevice(DeviceIdentifier deviceId) throws DeviceManagementException {
DeviceManager deviceManager = this.getDeviceManager(deviceId.getType());
if (deviceManager == null) {
@ -649,7 +665,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
device.setDeviceInfo(info);
} catch (DeviceDetailsMgtDAOException e) {
log.error("Error occurred while retrieving advance info of '" + device.getType() +
"' that carries the id '" + device.getDeviceIdentifier() + "'");
"' that carries the id '" + device.getDeviceIdentifier() + "'");
} catch (SQLException e) {
log.error("Error occurred while opening a connection to the data source", e);
} finally {
@ -663,7 +679,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
device.setApplications(applications);
} catch (DeviceManagementDAOException e) {
log.error("Error occurred while retrieving the application list of '" + device.getType() + "', " +
"which carries the id '" + device.getId() + "'", e);
"which carries the id '" + device.getId() + "'", e);
} catch (SQLException e) {
log.error("Error occurred while opening a connection to the data source", e);
} finally {
@ -674,7 +690,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
if (deviceManager == null) {
if (log.isDebugEnabled()) {
log.debug("Device Manager associated with the device type '" + device.getType() + "' is null. " +
"Therefore, not attempting method 'isEnrolled'");
"Therefore, not attempting method 'isEnrolled'");
}
devices.add(device);
continue;
@ -689,6 +705,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
}
return devices;
}
@Override
public List<Device> getAllDevices(String deviceType) throws DeviceManagementException {
List<Device> devices = new ArrayList<>();
@ -779,7 +796,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
try {
EmailContext ctx =
new EmailContext.EmailContextBuilder(new ContentProviderInfo(templateName, params),
metaInfo.getRecipients()).build();
metaInfo.getRecipients()).build();
DeviceManagementDataHolder.getInstance().getEmailSenderService().sendEmail(ctx);
} catch (EmailSendingFailedException ex) {
throw new DeviceManagementException("Error occurred while sending enrollment invitation", ex);
@ -1958,6 +1975,17 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
return false;
}
@Override
public NotificationStrategy getNotificationStrategyByDeviceType(String deviceType) throws DeviceManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
OperationManager operationManager = pluginRepository.getOperationManager(deviceType, tenantId);
if (operationManager != null) {
return operationManager.getNotificationStrategy();
} else {
throw new DeviceManagementException("Cannot find operation manager for given device type :" + deviceType);
}
}
/**
* Change device status.
*
@ -2007,7 +2035,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
throw new DeviceManagementException("Error occurred while opening a connection to the data source", e);
} catch (DeviceManagementDAOException e) {
throw new DeviceManagementException("Error occurred while updating the enrollment information device for" +
"id '" + deviceId + "' ." , e);
"id '" + deviceId + "' .", e);
} finally {
try {
DeviceManagementDAOFactory.getConnection().setAutoCommit(isAutoCommit);
@ -2085,23 +2113,22 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
List<DeviceIdentifier> deviceIdentifiers = new ArrayList<>();
deviceIdentifiers.add(deviceIdentifier);
if (init != null) {
List<String> initialOperations = init.getOperations();
for (String str : initialOperations) {
CommandOperation operation = new CommandOperation();
operation.setEnabled(true);
operation.setType(Operation.Type.COMMAND);
operation.setCode(str);
try {
deviceManagementProviderService.
addOperation(deviceType,
operation, deviceIdentifiers);
} catch (OperationManagementException e) {
throw new DeviceManagementException("Unable to find the device with the id: '" + deviceIdentifier.getId(),
e);
} catch (InvalidDeviceException e) {
throw new DeviceManagementException("Unable to find the device with the id: '" + deviceIdentifier.getId(),
e);
List<String> initialOperations = init.getOperations();
if (initialOperations != null) {
for (String str : initialOperations) {
CommandOperation operation = new CommandOperation();
operation.setEnabled(true);
operation.setType(Operation.Type.COMMAND);
operation.setCode(str);
try {
deviceManagementProviderService.addOperation(deviceType, operation, deviceIdentifiers);
} catch (OperationManagementException e) {
throw new DeviceManagementException("Unable to add the operation for the device with the id: '"
+ deviceIdentifier.getId(), e);
} catch (InvalidDeviceException e) {
throw new DeviceManagementException("Unable to find the device with the id: '"
+ deviceIdentifier.getId(), e);
}
}
}
}

@ -121,4 +121,9 @@ public class TestDeviceManager implements DeviceManager {
return false;
}
@Override
public PlatformConfiguration getDefaultConfiguration() throws DeviceManagementException {
return null;
}
}

@ -22,7 +22,7 @@
<parent>
<artifactId>device-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>device-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>2.0.48-SNAPSHOT</version>
<version>2.0.65-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -62,6 +62,7 @@ if (uriMatcher.match("/{context}/api/data-tables/invoker")) {
function (backendResponse) {
response["status"] = backendResponse["status"];
response["content"] = utility.encodeJson(backendResponse["responseText"]);
response["contentType"] = "application/json";
}
);
}

@ -176,6 +176,27 @@ if (uriMatcher.match("/{context}/api/user/authenticate")) {
}
} else if (uriMatcher.match("/{context}/api/user/all")) {
result = userModule.getUsers();
} else if (uriMatcher.match("/{context}/api/user/environment-loaded")) {
try {
var carbonUser = session.get(constants.USER_SESSION_KEY);
if (!carbonUser) {
response.sendRedirect("/devicemgt/login?#login-required");
exit();
}
utility.startTenantFlow(carbonUser);
var APIManagementProviderService = utility.getAPIManagementProviderService();
var isLoaded = APIManagementProviderService.isTierLoaded();
result = {"isLoaded": isLoaded};
if (isLoaded) {
var samlToken = session.get(constants.SAML_TOKEN_KEY);
if (samlToken) {
apiWrapperUtil.setupTokenPairByJWTGrantType(carbonUser.username + '@' + carbonUser.domain, samlToken);
}
}
response.contentType = 'application/json';
} finally {
utility.endTenantFlow();
}
}
// returning the result.

@ -11,7 +11,7 @@
"login": {
"onSuccess": {
"script": "/app/modules/login.js",
"page": "cdmf.page.dashboard"
"page": "cdmf.page.processing"
},
"onFail": {
"script": "/app/modules/login.js",

@ -0,0 +1,57 @@
{{!-- Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
WSO2 Inc. licenses this file to you under the Apache License,
Version 2.0 (the "License"); you may not use this file except
in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
either express or implied. See the License for the
specific language governing permissions and limitations
under the License. --}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{{defineZone "favicon"}}
<title>
{{defineZone "title"}}
</title>
{{defineZone "topLibCss"}}
{{defineZone "topCss"}}
{{defineZone "topJs"}}
</head>
<body>
<!--modal-->
<div class="modal fade" tabindex="-1" role="dialog" aria-labelledby="modalDemo">
<div class="modal-dialog" role="document">
<div class="modal-content clearfix">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i class="fw fw-cancel"></i></button>
</div>
<div class="modal-body add-margin-top-2x add-margin-bottom-2x">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<!--modal-->
{{defineZone "content"}}
{{defineZone "bottomModalContent"}}
{{defineZone "bottomLibJs"}}
{{defineZone "bottomJs"}}
</body>
</html>

@ -612,6 +612,9 @@ var userModule = function () {
if (publicMethods.isAuthorized("/permission/admin/device-mgt/devices/change-status")) {
permissions["CHANGE_DEVICE_STATUS"] = true;
}
if (publicMethods.isAuthorized("/permission/admin/device-mgt")) {
permissions["IS_ADMIN"] = true;
}
return permissions;
};

@ -81,3 +81,6 @@ var CACHED_CREDENTIALS = "tenantBasedCredentials";
var CACHED_CREDENTIALS_FOR_WEBSOCKET_APP = "tenantBasedWebSocketClientCredentials";
var ALLOWED_SCOPES = "scopes";
var SAML_TOKEN_KEY = "samlToken";
var SKIP_WELCOME_SCREEN ="skipWelcomeScreen";

@ -25,6 +25,19 @@ var onFail;
onSuccess = function (context) {
var utility = require("/app/modules/utility.js").utility;
var apiWrapperUtil = require("/app/modules/oauth/token-handlers.js")["handlers"];
try {
utility.startTenantFlow(context.user);
var APIManagementProviderService = utility.getAPIManagementProviderService();
var isLoaded = APIManagementProviderService.isTierLoaded();
if(!isLoaded && context.input.samlToken) {
session.put(constants.SKIP_WELCOME_SCREEN, false);
session.put(constants.SAML_TOKEN_KEY, context.input.samlToken);
return;
}
} finally {
utility.endTenantFlow();
}
session.put(constants.SKIP_WELCOME_SCREEN, true);
if (context.input.samlToken) {
//apiWrapperUtil.setupTokenPairBySamlGrantType(context.user.username + '@' + context.user.domain, context.input.samlToken);
/**

@ -53,6 +53,10 @@ utility = function () {
return getOsgiService('org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService');
};
publicMethods.getAPIManagementProviderService = function () {
return getOsgiService('org.wso2.carbon.apimgt.application.extension.APIManagementProviderService');
};
publicMethods.getUserManagementService = function () {
return getOsgiService("org.wso2.carbon.device.mgt.user.core.UserManager");
};

@ -16,7 +16,7 @@
* under the License.
*/
function onRequest() {
function onRequest(context) {
var constants = require("/app/modules/constants.js");
var userModule = require("/app/modules/business-controllers/user.js")["userModule"];
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
@ -24,6 +24,11 @@ function onRequest() {
var groupModule = require("/app/modules/business-controllers/group.js")["groupModule"];
var policyModule = require("/app/modules/business-controllers/policy.js")["policyModule"];
if(!session.get(constants["TOKEN_PAIR"])){
response.sendRedirect(context.app.context + "/welcome");
return;
}
var user = session.get(constants["USER_SESSION_KEY"]);
var permissions = userModule.getUIPermissions();

@ -40,6 +40,20 @@
</li>
{{/zone}}
{{#zone "navbarActions"}}
{{#if isCloud}}
<li>
<a href="{{contact_form_url}}" class="cu-btn">
<span class="icon fw-stack">
<i class="fw fw-mail fw-stack-1x"></i>
<i class="fw fw-circle-outline fw-stack-2x"></i>
</span>
Request new device type
</a>
</li>
{{/if}}
{{/zone}}
{{#zone "content"}}
<div class="wr-device-list row">
<div class="wr-hidden-operations wr-advance-operations"></div>

@ -0,0 +1,31 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* Returns the dynamic state to be populated by device-enrollment page.
*
* @param context Object that gets updated with the dynamic state of this page to be presented
* @returns {*} A context object that returns the dynamic state of this page to be presented
*/
function onRequest(context) {
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
var page = {};
page["isCloud"] = devicemgtProps.isCloud;
page["contact_form_url"] = "https://cloudmgt.cloud.wso2.com/cloudmgt/site/pages/contact-us.jag?cloud-type=device_cloud&subject=Requesting for a new device type";
return page;
}

@ -153,6 +153,7 @@
<!-- / result content -->
</div>
</div>
</div>
<!-- /content/body -->
{{/zone}}
{{#zone "bottomJs"}}

@ -519,7 +519,7 @@
{{/zone}}
{{#zone "bottomJs"}}
<script id="device-listing" data-current-user="{{@user.username}}" data-device-types="{{deviceTypes}}"
<script id="device-listing" data-analitics-url="{{analyticsURL}}" data-current-user="{{@user.username}}" data-device-types="{{deviceTypes}}"
type="text/x-handlebars-template"></script>
{{js "js/listing.js"}}
{{/zone}}

@ -86,5 +86,11 @@ function onRequest(context) {
viewModel.deviceTypes = stringify(deviceTypes);
}
}
var mdmProps = require("/app/modules/conf-reader/main.js")["conf"];
var analyticsServer = mdmProps["dashboardServerURL"];
var analyticsURL = analyticsServer + "/portal/t/" + context.user.userDomain + "/dashboards/android-iot/battery?owner=" + context.user.username + "&deviceId=";
viewModel.analyticsURL = analyticsURL;
return viewModel;
}

@ -323,11 +323,14 @@ function loadDevices(searchType, searchParam) {
var deviceType = row.deviceType;
var deviceIdentifier = row.deviceIdentifier;
var html = '<span></span>';
var statURL = $("#device-listing").data("analitics-url");
if (status != 'REMOVED') {
html = '';
if (analyticsEnabled(row.deviceType)) {
html += '<a href="' + context + '/device/' + deviceType + '/analytics?deviceId=' +
html += '<a href="' + statURL +
deviceIdentifier + '&deviceName=' + row.name + '" ' + 'data-click-event="remove-form"' +
' class="btn padding-reduce-on-grid-view" data-placement="top" data-toggle="tooltip" data-original-title="Analytics"><span class="fw-stack">' +
'<i class="fw fw-circle-outline fw-stack-2x"></i><i class="fw fw-statistics fw-stack-1x"></i></span>' +

@ -0,0 +1,57 @@
{{!
Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
WSO2 Inc. licenses this file to you under the Apache License,
Version 2.0 (the "License"); you may not use this file except
in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
}}
{{unit "cdmf.unit.ui.title" pageTitle="Home"}}
{{#zone "breadcrumbs"}}
<li>
<a href="{{@app.context}}/">
<i class="icon fw fw-home"></i>
</a>
</li>
{{/zone}}
{{#zone "content"}}
<div class="row">
<div class="col-md-12">
Loading...Please Wait
</div>
</div>
{{/zone}}
{{#zone "bottomJs"}}
<script type="text/javascript">
$('body').attr("data-toggle", "loading")
.attr("data-loading-style", "overlay")
.attr("data-loading-text", "SETTING UP YOUR ENVIRONMENT . . .");
$('[data-toggle="loading"]').loading('show');
</script>
{{js "/js/script.js"}}
{{/zone}}
{{#zone "topCss"}}
<style>
.loading[data-loading-style=overlay] .loading-bg{
background: #11375B;
opacity: 1;
filter: alpha(opacity=100);
}
.loading .loading-animation{
width : 200px;
}
</style>
{{/zone}}

@ -0,0 +1,27 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
function onRequest(context) {
var constants = require("/app/modules/constants.js");
var skipWelcomeScreen = session.get(constants.SKIP_WELCOME_SCREEN);
if (skipWelcomeScreen) {
response.sendRedirect(context.app.context + "/");
exit();
}
return {};
}

@ -0,0 +1,30 @@
var pollingCount = 24;
function poll() {
$.ajax({
url: context + "/api/user/environment-loaded",
type: "GET",
success: function (data) {
if (data.isLoaded) {
window.location = context + "/";
}
},
dataType: "json",
complete: setTimeout(function () {
pollingCount = pollingCount - 1;
if (pollingCount > 0) {
poll();
} else {
$(".loading-animation .logo").hide();
$(".loading-animation").prepend(
'<i class="fw fw-error fw-inverse fw-2x" style="float: left;"></i>');
$(".loading-animation p").css("width", "150%")
.html("Ops... it seems something went wrong.<br/> Refresh the page to retry!");
}
}, 5000),
timeout: 5000
});
}
$(document).ready(function () {
poll();
});

@ -17,8 +17,8 @@
}}
{{#zone "footer"}}
<p>
<span class="hidden-xs">WSO2 IoT Server 3.1.0</span>
<span class="visible-xs-inline">WSO2 IoT Server 3.1.0</span> | &copy; <script>document.write(new Date().getFullYear());</script>,
<span class="hidden-xs">WSO2 IoT Server{{#unless isCloud}} 3.1.0{{/unless}}</span>
<span class="visible-xs-inline">WSO2 IoT Server{{#unless isCloud}} 3.1.0{{/unless}}</span> | &copy; <script>document.write(new Date().getFullYear());</script>,
<a href="http://wso2.com/" target="_blank"><i class="icon fw fw-wso2"></i> Inc</a>. All Rights Reserved.
</p>
{{/zone}}

@ -0,0 +1,24 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
function onRequest(context) {
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
var page = {};
page["isCloud"] = devicemgtProps.isCloud;
return page;
}

@ -1,7 +1,7 @@
{{#zone "content"}}
{{#if isAuthorized}}
<span id="logged-in-user" class="hidden" data-username="{{user.username}}" data-domain="{{user.domain}}"
data-tenant-id="{{user.tenantId}}" data-iscloud="{{isCloud}}"></span>
<span id="logged-in-user" class="hidden" data-username="{{@user.username}}" data-domain="{{@user.domain}}"
data-tenant-id="{{@user.tenantId}}" data-iscloud="{{isCloud}}"></span>
<div class="row">
<div class="col-md-12">

@ -67,8 +67,6 @@ function onRequest(context) {
}
}
var user = userModule.getCarbonUser();
types["user"] = {username: user.username, domain: user.domain, tenantId: user.tenantId};
var roles = userModule.getRoles();
if (roles["status"] == "success") {
types["roles"] = roles["content"];

@ -1,7 +1,7 @@
{{#zone "content"}}
{{#if isAuthorized }}
<span id="logged-in-user" class="hidden" data-username="{{user.username}}" data-domain="{{user.domain}}"
data-tenant-id="{{user.tenantId}}"></span>
<span id="logged-in-user" class="hidden" data-username="{{@user.username}}" data-domain="{{@user.domain}}"
data-tenant-id="{{@user.tenantId}}" data-iscloud="{{isCloud}}"></span>
<span id="policy-operations" class="hidden" data-template="{{policyOperations.template}}"
data-script="{{policyOperations.script}}" data-style="{{policyOperations.style}}"></span>
<div class="row">

@ -60,5 +60,8 @@ function onRequest(context) {
context.isAuthorizedViewRoles = userModule.isAuthorized("/permission/admin/device-mgt/users/view");
context.isAuthorizedViewGroups = userModule.isAuthorized("/permission/admin/device-mgt/groups/view");
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
context["isCloud"] = devicemgtProps.isCloud;
return context;
}

@ -196,7 +196,7 @@ skipStep["policy-platform"] = function (policyPayloadObj) {
hasPolicyProfileScript = false;
}
$.template(policyEditTemplateCacheKey, context + policyEditTemplateSrc, function (template) {
var content = template();
var content = template({"iscloud" : $("#logged-in-user").data("iscloud")});
$("#device-type-policy-operations").html(content).removeClass("hidden");
$(".policy-platform").addClass("hidden");
if (hasPolicyProfileScript) {

@ -84,7 +84,7 @@ var displayPolicy = function (policyPayloadObj) {
hasPolicyProfileScript = false;
}
$.template(policyViewTemplateCacheKey, context + policyViewTemplateSrc, function (template) {
var content = template();
var content = template({"iscloud" : $("#logged-in-user").data("iscloud")});
$("#device-type-policy-operations").html(content).removeClass("hidden");
$(".policy-platform").addClass("hidden");
if (hasPolicyProfileScript) {

@ -1,5 +1,7 @@
{{#zone "content"}}
{{#if isAuthorized}}
<span id="logged-in-user" class="hidden" data-username="{{@user.username}}" data-domain="{{@user.domain}}"
data-tenant-id="{{@user.tenantId}}" data-iscloud="{{isCloud}}"></span>
{{#defineZone "policy-profile-top"}}
<div class="row wr-device-board">
<div class="col-lg-12 wr-secondary-bar">

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save