Compare commits

Invalid templates have been ignored

1 invalid template(s) found pull_request_template.md: frontmatter must start with a separator line

...

114 Commits

Author SHA1 Message Date
Rajitha Kumara b8d5759109 Add batch executor
2 years ago
Lasantha Dharmakeerthi c8c18c4f3d Fix policy bundle repeating issue
2 years ago
Lasantha Dharmakeerthi d30f27a584 Add Improvements on chat feature
2 years ago
Thashmi-nil 19750486de Add improvements
2 years ago
Charitha Goonetilleke 3382966543 Merge pull request 'extension to create event streams,receivers,publishers in file system' (#86) from amalka.subasinghe/device-mgt-core:master into master
2 years ago
Amalka Subasinghe 3c13196aa5 fixed feature installation issue
2 years ago
Amalka Subasinghe 5da3df3984 fixed template location
2 years ago
Amalka Subasinghe 766606f9f7 added analytics extension to persist event streams,receivers,publishers
2 years ago
Lasantha Dharmakeerthi ad3cc84558 Add self-guiding-ui feature
2 years ago
osh c4e08362ff Merge branch 'master' of ssh://repository.entgra.net:222/community/device-mgt-core into self-guiding-ui-9939
2 years ago
osh 5275bb180e Change config implementation
2 years ago
Charitha Goonetilleke 0ae4ff68a6 Merge pull request 'fixed adding operation and operation response paths with emqx integration' (#85) from amalka.subasinghe/device-mgt-core:master into master
2 years ago
Charitha Goonetilleke 802922022b Merge branch 'master' into master
2 years ago
osh 7747d7b425 Update status history path
2 years ago
osh d2bc463284 Resolve comments
2 years ago
osh 0f28d318ed Remove unwanted code
2 years ago
osh 6962e94d44 Merge branch 'master' of ssh://repository.entgra.net:222/community/device-mgt-core into self-guiding-ui-9939
2 years ago
osh f89e71d4bf Reuse email implementation
2 years ago
Lasantha Dharmakeerthi 65c93aea81 Add improvements for chat feature
2 years ago
Thashmi-nil 3d8f704699 Add license
2 years ago
Amalka Subasinghe 4dac92b260 fixed adding operation and operation response paths with emqx integration
2 years ago
Thashmi-nil 798e851922 Add modifications
2 years ago
Rajitha Kumara 4f7b317761 Add functionality to mark previous policy bundles as repeated
2 years ago
Inosh Perara d201e295ac Merge pull request 'Add Entgra Device Notification Logger' (#51) from pramilaniroshan/device-mgt-core:entgra-logger into master
2 years ago
Pramila Niroshan cad2468b3d Fix osgi import package error
2 years ago
Pramila Niroshan 1923fb7dfb Remove log4j2.properties file
2 years ago
osh 24064b650b Resolve conflict
2 years ago
Thashmi-nil 2d1879d1b6 Changes on reviews
2 years ago
Pramila Niroshan c168503994 log4j2.properties file added
2 years ago
Pramila Niroshan 7441e57d36 Refactor log context name
2 years ago
Pramila Niroshan 4005a9e8cb User log context added
2 years ago
Pramila Niroshan b99587f1df Remove test cases
2 years ago
Pramila Niroshan 950f67da5f Merge branch 'master' of ssh://repository.entgra.net:222/community/device-mgt-core into entgra-logger
2 years ago
Charitha Goonetilleke ba42f79fba Merge pull request 'Fixing iot story with emqx integration' (#80) from amalka.subasinghe/device-mgt-core:master into master
2 years ago
Amalka Subasinghe 98baaf8fc1 added entgra licence
2 years ago
Amalka Subasinghe 78dd331306 Merge branch 'master' of https://repository.entgra.net/community/device-mgt-core
2 years ago
Amalka Subasinghe 6c1b224b89 fixing formatting and licence headers
2 years ago
Charitha Goonetilleke 79b84aa191 Merge remote-tracking branch 'origin/master'
2 years ago
Charitha Goonetilleke c78abf0564 Remove unnecessary logs
2 years ago
Amalka Subasinghe 44b5b4f44d fixing invalid attribute
2 years ago
Amalka Subasinghe 800694de97 introduce new datasource for events
2 years ago
Amalka Subasinghe d3ffba8e26 improve device type configuring and event data publishing
2 years ago
Amalka Subasinghe bf8efa35a7 updated keymgt extensions to support validity period
2 years ago
builder 4d8d4bdcf7 [maven-release-plugin] prepare for next development iteration
2 years ago
builder 1b363c0978 [maven-release-plugin] prepare release v5.0.20
2 years ago
Charitha Goonetilleke 204ba91010 Remove unnecessary logs
2 years ago
osh 5dab9433a4 Update email subject
2 years ago
Thashmi-nil 0f6db69c18 Merge branch 'master' of https://repository.entgra.net/community/device-mgt-core into live-chat-feature
2 years ago
Thashmi-nil 74f50b28c5 Add user identification improvement
2 years ago
osh 0bbcac4a93 Add enrollment guide permissions
2 years ago
osh 79a2d573fa Fix build failure
2 years ago
osh 36052663ba Merge branch 'master' of ssh://repository.entgra.net:222/community/device-mgt-core
2 years ago
osh 66afe95fe9 Add api for self guide enrollment
2 years ago
Charitha Goonetilleke 0009bdd460 Merge remote-tracking branch 'origin/master'
2 years ago
Charitha Goonetilleke ce20ead035 Fix issues with task id getting null
2 years ago
Charitha Goonetilleke 0a9b20e0fc Fix issues with unnecessary task deletion
2 years ago
Inosh Perara 0a9661f98e Merge pull request 'Fix MSSQL dbscripts of DM_DB, APPM_DB' (#66) from prathabanKavin/device-mgt-core:mssqlfix into master
2 years ago
prathabanKavin 5fca50f8d7 Change latitude and longitude datatype
2 years ago
Inosh Perara b51a608a41 Merge pull request 'Add fix to load apps and create app' (#68) from prathabanKavin/device-mgt-core:mssqlcreateappfix into master
2 years ago
Charitha Goonetilleke 1d54aa7958 Merge pull request 'Enhance dynamic task watcher functionality' (#69) from improvement/task-watcher into master
2 years ago
Charitha Goonetilleke 28488d3e08 Merge remote-tracking branch 'origin/master'
2 years ago
Charitha Goonetilleke 1db4b4095e Enhance dynamic task watcher functionality
2 years ago
prathabanKavin fb3797774e Add fix to load apps and create app
2 years ago
Lasantha Dharmakeerthi dcbcfe23fe Enhance dynamic task execution functionality
2 years ago
Charitha Goonetilleke 78f8e80718 Enhance dynamic task execution functionality
2 years ago
prathabanKavin e4a5f49b9c Fix dynamic task tables
2 years ago
prathabanKavin a3eca63dfd Fix mssql dbscripts of DM_DB, APPM_DB
2 years ago
Charitha Goonetilleke ce0d834b12 Fix NPE
2 years ago
Charitha Goonetilleke 17f28c8b55 Suppress unnecessary logs
2 years ago
Chamindu Senanayake 89e72bdf86 Add dynamic task manager and task watcher (#65)
2 years ago
builder 2d56b0ea9a [maven-release-plugin] prepare for next development iteration
2 years ago
builder 73d17e61a8 [maven-release-plugin] prepare release v5.0.19
2 years ago
Lasantha Dharmakeerthi 3859281216 Add unique key constraint into AP_DEVICE_SUBSCRIPTION tables
2 years ago
Pahansith Gunathilake 2926c2e523 Add unique key constraint into AP_DEVICE_SUBSCRIPTION tables
2 years ago
Thashmi-nil 9c3020fc77 Add improvements for chat feature
2 years ago
Pahansith Gunathilake 9ad7438d69 Merge pull request 'Remove device details loading while processing policies' (#62) from pramilaniroshan/device-mgt-core:master into master
2 years ago
Pahansith Gunathilake 9644dda7ef Remove device details loading while processing policies
2 years ago
builder d715609b53 [maven-release-plugin] prepare for next development iteration
2 years ago
builder 0beeedef43 [maven-release-plugin] prepare release v5.0.18
2 years ago
Pahansith Gunathilake 215c0f44a0 Merge pull request 'Revert "Change the device status and see the device status lifecycle history (#58)"' (#61) from pahansith/device-mgt-core:revert-lifecycle-history into master
2 years ago
Pahansith Gunathilake 5228a84400 Revert "Change the device status and see the device status lifecycle history (#58)"
2 years ago
builder 9f724eeffb [maven-release-plugin] prepare for next development iteration
2 years ago
builder 50bc5560f8 [maven-release-plugin] prepare release v5.0.17
2 years ago
Kavin Prathaban 846d7a0f59 Add support to perform group operations (#59)
2 years ago
Pramila Niroshan 12b3b1a41d Add missing dependency
2 years ago
Kavin Prathaban 7f327bac08 Change the device status and see the device status lifecycle history (#58)
2 years ago
Navod Zoysa 2e2e9abc90 Add Android alternate app install permission to UI config (#55)
2 years ago
Pramila Niroshan 9401a4501b Add Entgra Device Notification Feature
2 years ago
Pramila Niroshan db624d26df Add Entgra Device Notification Logger
2 years ago
Pramila Niroshan 80458a4b9d Merge branch 'master' of ssh://repository.entgra.net:222/community/device-mgt-core into entgra-logger
2 years ago
Pahansith Gunathilake 8be8b2928a Merge pull request 'Update sendDeviceNameChangedNotification' (#56) from rushdi-entgra.io/device-mgt-core:fix-naming into master
2 years ago
Rushdi Mohamed 5cf7377a85 Update sendDeviceNameChangedNotification
2 years ago
builder 071b9486bb [maven-release-plugin] prepare for next development iteration
2 years ago
builder cf305362b4 [maven-release-plugin] prepare release v5.0.16
2 years ago
Pahansith Gunathilake 9ef3e0cf6e Revert "Change the device status and see the device status lifecycle history"
2 years ago
Pahansith Gunathilake 86f709a74a Revert "Fix api errors in Lifecycle methods"
2 years ago
Rushdi Mohamed a7cf4fa86c Add pagination sort by column (#48)
2 years ago
prathabanKavin d69619bf65 Fix api errors in Lifecycle methods
2 years ago
Pahansith Gunathilake a05007b835 Merge pull request 'Add notification feature when a device is renamed' (#18) from arshana790/device-mgt-core-fork:android-feature into master
2 years ago
Pahansith Gunathilake 2580add403 Merge branch 'master' into android-feature
2 years ago
Pahansith Gunathilake 32a9d7a61f Merge pull request 'Change the device status and see the device status lifecycle history' (#52) from prathabanKavin/device-mgt-core:device-lifecycle into master
2 years ago
prathabanKavin df6a8e20a3 Change the device status and see the device status lifecycle history
2 years ago
Pahansith Gunathilake 0f8c3e22e6 Merge branch 'master' into android-feature
2 years ago
Pramila Niroshan d5c709cfc0 Add Entgra Device Notification Logger
2 years ago
Lasantha Dharmakeerthi 8d036da061 Improve OTP mgt service functionalities
2 years ago
Dharmakeerthi Lasantha 01aaa44e89 improve OTP mgt service functionalities
2 years ago
Ravindu Madhubhashana e28c71d4ae Added validation for app name length when creating an app
2 years ago
Lasantha Dharmakeerthi c03e1359d3 Add download URL generating method
2 years ago
Dharmakeerthi Lasantha d55ea733e7 Add download URL generating method
2 years ago
Oshani Silva a93f534e06 Improve billing feature
2 years ago
Lasantha Dharmakeerthi ad111a3999 Revert direct app publishing merge conflict
2 years ago
navodzoysa b25fb4e6ad Revert direct app publishing merge conflict
2 years ago
Arshana 777940b896 Fix SendDeviceNameChangedNotification
2 years ago
Arshana 5e612ceaf2 Add capability to send a notification when device rename
2 years ago

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>grafana-mgt</artifactId>
<version>5.0.16-SNAPSHOT</version>
<version>5.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>grafana-mgt</artifactId>
<version>5.0.16-SNAPSHOT</version>
<version>5.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>grafana-mgt</artifactId>
<version>5.0.16-SNAPSHOT</version>
<version>5.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>analytics-mgt</artifactId>
<version>5.0.16-SNAPSHOT</version>
<version>5.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -3,7 +3,7 @@
<parent>
<artifactId>carbon-devicemgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.16-SNAPSHOT</version>
<version>5.0.21-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -0,0 +1,119 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
~
~ Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
~ Version 2.0 (the "License"); you may not use this file except
~ in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.21-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>io.entgra.device.mgt.core.apimgt.analytics.extension</artifactId>
<packaging>bundle</packaging>
<name>Entgra - API mgt analytics extension</name>
<url>http://wso2.org</url>
<dependencies>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.core</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.utils</artifactId>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/Abstract*</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Bundle-Version>${carbon.device.mgt.version}</Bundle-Version>
<Bundle-Description>API Management Application Bundle</Bundle-Description>
<Private-Package>org.wso2.carbon.apimgt.application.extension.internal</Private-Package>
<Import-Packages>
io.entgra.device.mgt.core.apimgt.analytics.extension.dto,
org.apache.velocity,
org.apache.velocity.app,
org.apache.velocity.context,
org.wso2.carbon.utils;version="[4.6,5)"
</Import-Packages>
<Export-Package>
io.entgra.device.mgt.core.apimgt.analytics.extension.*
</Export-Package>
<Embed-Dependency>
scribe;scope=compile|runtime;inline=false;
</Embed-Dependency>
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<destFile>${basedir}/target/coverage-reports/jacoco-unit.exec</destFile>
</configuration>
<executions>
<execution>
<id>jacoco-initialize</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-site</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${basedir}/target/coverage-reports/jacoco-unit.exec</dataFile>
<outputDirectory>${basedir}/target/coverage-reports/site</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,176 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.apimgt.analytics.extension;
import io.entgra.device.mgt.core.apimgt.analytics.extension.dto.EventPublisherData;
import io.entgra.device.mgt.core.apimgt.analytics.extension.dto.EventReceiverData;
import io.entgra.device.mgt.core.apimgt.analytics.extension.dto.EventStreamData;
import io.entgra.device.mgt.core.apimgt.analytics.extension.dto.MetaData;
import io.entgra.device.mgt.core.apimgt.analytics.extension.exception.EventPublisherDeployerException;
import io.entgra.device.mgt.core.apimgt.analytics.extension.exception.EventReceiverDeployerException;
import io.entgra.device.mgt.core.apimgt.analytics.extension.exception.EventStreamDeployerException;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.wso2.carbon.utils.CarbonUtils;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
public class AnalyticsArtifactsDeployer {
public static final String TEMPLATE_LOCATION = "repository" + File.separator + "resources" + File.separator + "iot-analytics-templates";
public static final String EVENT_STREAM_LOCATION = "eventstreams";
public static final String EVENT_PUBLISHER_LOCATION = "eventpublishers";
public static final String EVENT_RECEIVER_LOCATION = "eventreceivers";
public static final String EVENT_STREAM_TEMPLATE = TEMPLATE_LOCATION + File.separator + "event_stream.json.template";
public static final String EVENT_PUBLISHER_TEMPLATE = TEMPLATE_LOCATION + File.separator + "event_publisher.xml.template";
public static final String EVENT_RECEIVER_TEMPLATE = TEMPLATE_LOCATION + File.separator + "event_receiver.xml.template";
public void deployEventStream(EventStreamData eventStreamData, int tenantId) throws EventStreamDeployerException {
try {
VelocityEngine ve = new VelocityEngine();
ve.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, CarbonUtils.getCarbonHome());
ve.init();
Template template = ve.getTemplate(EVENT_STREAM_TEMPLATE);
VelocityContext context = populateContextForEventStreams(eventStreamData);
StringWriter writer = new StringWriter();
template.merge(context, writer);
String fileName = eventStreamData.getName() + "_" + eventStreamData.getVersion() + ".json";
String fileLocation = null;
if (MultitenantConstants.SUPER_TENANT_ID == tenantId) {
fileLocation = CarbonUtils.getCarbonHome() + File.separator + "repository" + File.separator + "deployment"
+ File.separator + "server" + File.separator + EVENT_STREAM_LOCATION + File.separator + fileName;
} else {
fileLocation = CarbonUtils.getCarbonTenantsDirPath() + File.separator + tenantId + File.separator
+ EVENT_STREAM_LOCATION + File.separator + fileName;
}
PrintWriter printWriter = new PrintWriter(fileLocation, "UTF-8");
printWriter.println(writer.toString());
printWriter.close();
} catch (FileNotFoundException | UnsupportedEncodingException e) {
throw new EventStreamDeployerException("Error while persisting event stream definition ", e);
}
}
public void deployEventPublisher(EventPublisherData eventPublisherData, int tenantId) throws EventPublisherDeployerException {
try {
VelocityEngine ve = new VelocityEngine();
ve.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, CarbonUtils.getCarbonHome());
ve.init();
Template template = ve.getTemplate(EVENT_PUBLISHER_TEMPLATE);
VelocityContext context = populateContextForEventPublisher(eventPublisherData);
StringWriter writer = new StringWriter();
template.merge(context, writer);
String fileName = eventPublisherData.getName() + ".xml";
String fileLocation = null;
if (MultitenantConstants.SUPER_TENANT_ID == tenantId) {
fileLocation = CarbonUtils.getCarbonHome() + File.separator + "repository" + File.separator + "deployment"
+ File.separator + "server" + File.separator + EVENT_PUBLISHER_LOCATION + File.separator + fileName;
} else {
fileLocation = CarbonUtils.getCarbonTenantsDirPath() + File.separator + tenantId + File.separator
+ EVENT_PUBLISHER_LOCATION + File.separator + fileName;
}
PrintWriter printWriter = new PrintWriter(fileLocation, "UTF-8");
printWriter.println(writer.toString());
printWriter.close();
} catch (FileNotFoundException | UnsupportedEncodingException e) {
throw new EventPublisherDeployerException("Error while persisting rdbms event publisher ", e);
}
}
public void deployEventReceiver(EventReceiverData eventReceiverData, int tenantId) throws EventReceiverDeployerException {
try {
VelocityEngine ve = new VelocityEngine();
ve.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, CarbonUtils.getCarbonHome());
ve.init();
Template template = ve.getTemplate(EVENT_RECEIVER_TEMPLATE);
VelocityContext context = populateContextForEventReceiver(eventReceiverData);
StringWriter writer = new StringWriter();
template.merge(context, writer);
String fileName = eventReceiverData.getName() + ".xml";
String fileLocation = null;
if (MultitenantConstants.SUPER_TENANT_ID == tenantId) {
fileLocation = CarbonUtils.getCarbonHome() + File.separator + "repository" + File.separator + "deployment"
+ File.separator + "server" + File.separator + EVENT_RECEIVER_LOCATION + File.separator + fileName;
} else {
fileLocation = CarbonUtils.getCarbonTenantsDirPath() + File.separator + tenantId + File.separator
+ EVENT_RECEIVER_LOCATION + File.separator + fileName;
}
PrintWriter printWriter = new PrintWriter(fileLocation, "UTF-8");
printWriter.println(writer.toString());
printWriter.close();
} catch (FileNotFoundException | UnsupportedEncodingException e) {
throw new EventReceiverDeployerException("Error while persisting oauth mqtt event receiver ", e);
}
}
private VelocityContext populateContextForEventStreams(EventStreamData eventStreamData) {
VelocityContext context = new VelocityContext();
context.put("name", eventStreamData.getName());
context.put("version", eventStreamData.getVersion());
context.put("metaData",
eventStreamData.getMetaData() != null ? eventStreamData.getMetaData() : new MetaData("deviceId", "STRING"));
if (eventStreamData.getPayloadData() != null) {
context.put("properties", eventStreamData.getPayloadData());
}
return context;
}
private VelocityContext populateContextForEventPublisher(EventPublisherData eventPublisherData) {
VelocityContext context = new VelocityContext();
context.put("name", eventPublisherData.getName());
context.put("streamName", eventPublisherData.getStreamName());
context.put("streamVersion", eventPublisherData.getStreamVersion());
context.put("properties", eventPublisherData.getPropertyList());
context.put("eventAdapterType", eventPublisherData.getEventAdaptorType());
context.put("customMappingType", eventPublisherData.getCustomMappingType());
return context;
}
private VelocityContext populateContextForEventReceiver(EventReceiverData eventReceiverData) {
VelocityContext context = new VelocityContext();
context.put("name", eventReceiverData.getName());
context.put("streamName", eventReceiverData.getStreamName());
context.put("streamVersion", eventReceiverData.getStreamVersion());
context.put("properties", eventReceiverData.getPropertyList());
context.put("eventAdapterType", eventReceiverData.getEventAdapterType());
context.put("customMappingType", eventReceiverData.getCustomMappingType());
return context;
}
}

@ -0,0 +1,80 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.apimgt.analytics.extension.dto;
import java.util.List;
public class EventPublisherData {
private String name;
private String streamVersion;
private String streamName;
private List<Property> propertyList;
private String eventAdaptorType;
private String customMappingType;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStreamVersion() {
return streamVersion;
}
public void setStreamVersion(String streamVersion) {
this.streamVersion = streamVersion;
}
public String getStreamName() {
return streamName;
}
public void setStreamName(String streamName) {
this.streamName = streamName;
}
public List<Property> getPropertyList() {
return propertyList;
}
public void setPropertyList(List<Property> propertyList) {
this.propertyList = propertyList;
}
public String getEventAdaptorType() {
return eventAdaptorType;
}
public void setEventAdaptorType(String eventAdaptorType) {
this.eventAdaptorType = eventAdaptorType;
}
public String getCustomMappingType() {
return customMappingType;
}
public void setCustomMappingType(String customMappingType) {
this.customMappingType = customMappingType;
}
}

@ -0,0 +1,81 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.apimgt.analytics.extension.dto;
import java.util.List;
public class EventReceiverData {
private String name;
private String streamVersion;
private String streamName;
private String eventAdapterType;
List<Property> propertyList;
private String customMappingType;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStreamVersion() {
return streamVersion;
}
public void setStreamVersion(String streamVersion) {
this.streamVersion = streamVersion;
}
public String getStreamName() {
return streamName;
}
public void setStreamName(String streamName) {
this.streamName = streamName;
}
public String getEventAdapterType() {
return eventAdapterType;
}
public void setEventAdapterType(String eventAdapterType) {
this.eventAdapterType = eventAdapterType;
}
public List<Property> getPropertyList() {
return propertyList;
}
public void setPropertyList(List<Property> propertyList) {
this.propertyList = propertyList;
}
public String getCustomMappingType() {
return customMappingType;
}
public void setCustomMappingType(String customMappingType) {
this.customMappingType = customMappingType;
}
}

@ -0,0 +1,59 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.apimgt.analytics.extension.dto;
import java.util.List;
public class EventStreamData {
private String name;
private String version;
private MetaData metaData;
private List<Property> payloadData;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public MetaData getMetaData() {
return metaData;
}
public void setMetaData(MetaData metaData) {
this.metaData = metaData;
}
public List<Property> getPayloadData() {
return payloadData;
}
public void setPayloadData(List<Property> payloadData) {
this.payloadData = payloadData;
}
}

@ -0,0 +1,44 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.apimgt.analytics.extension.dto;
public class MetaData {
String name;
String type;
public MetaData(String name, String type){
this.setName(name);
this.setType(type);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}

@ -0,0 +1,45 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.apimgt.analytics.extension.dto;
public class Property {
String name;
String value;
public Property(String name, String value){
this.setName(name);
this.setValue(value);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

@ -0,0 +1,43 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.apimgt.analytics.extension.exception;
public class EventPublisherDeployerException extends Exception {
private static final long serialVersionUID = -3151279311929070299L;
public EventPublisherDeployerException(String msg, Exception nestedEx) {
super(msg, nestedEx);
}
public EventPublisherDeployerException(String message, Throwable cause) {
super(message, cause);
}
public EventPublisherDeployerException(String msg) {
super(msg);
}
public EventPublisherDeployerException() {
super();
}
public EventPublisherDeployerException(Throwable cause) {
super(cause);
}
}

@ -0,0 +1,43 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.apimgt.analytics.extension.exception;
public class EventReceiverDeployerException extends Exception {
private static final long serialVersionUID = -3151279311929070299L;
public EventReceiverDeployerException(String msg, Exception nestedEx) {
super(msg, nestedEx);
}
public EventReceiverDeployerException(String message, Throwable cause) {
super(message, cause);
}
public EventReceiverDeployerException(String msg) {
super(msg);
}
public EventReceiverDeployerException() {
super();
}
public EventReceiverDeployerException(Throwable cause) {
super(cause);
}
}

@ -0,0 +1,43 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.apimgt.analytics.extension.exception;
public class EventStreamDeployerException extends Exception {
private static final long serialVersionUID = -3151279311929070298L;
public EventStreamDeployerException(String msg, Exception nestedEx) {
super(msg, nestedEx);
}
public EventStreamDeployerException(String message, Throwable cause) {
super(message, cause);
}
public EventStreamDeployerException(String msg) {
super(msg);
}
public EventStreamDeployerException() {
super();
}
public EventStreamDeployerException(Throwable cause) {
super(cause);
}
}

@ -22,7 +22,7 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.16-SNAPSHOT</version>
<version>5.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.16-SNAPSHOT</version>
<version>5.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.16-SNAPSHOT</version>
<version>5.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -256,10 +256,14 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe
keyManagerId = keyManagerConfigurationDTO.getUuid();
}
}
String applicationAccessTokenExpiryTime = "N/A";
if (!StringUtils.isEmpty(validityTime)) {
applicationAccessTokenExpiryTime = validityTime;
}
String jsonString = "{\"grant_types\":\"refresh_token,access_token," +
"urn:ietf:params:oauth:grant-type:saml2-bearer," +
"password,client_credentials,iwa:ntlm,urn:ietf:params:oauth:grant-type:jwt-bearer\"," +
"\"additionalProperties\":\"{\\\"application_access_token_expiry_time\\\":\\\"N\\/A\\\"," +
"\"additionalProperties\":\"{\\\"application_access_token_expiry_time\\\":\\\"" + applicationAccessTokenExpiryTime + "\\\"," +
"\\\"user_access_token_expiry_time\\\":\\\"N\\/A\\\"," +
"\\\"refresh_token_expiry_time\\\":\\\"N\\/A\\\"," +
"\\\"id_token_expiry_time\\\":\\\"N\\/A\\\"}\"," +

@ -3,7 +3,7 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.16-SNAPSHOT</version>
<version>5.0.21-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

@ -40,6 +40,9 @@ public class DCRRequest {
@XmlElement
private boolean isSaasApp;
@XmlElement
private int validityPeriod;
public String getApplicationName() {
return applicationName;
}
@ -87,4 +90,12 @@ public class DCRRequest {
public void setIsSaasApp(boolean saasApp) {
isSaasApp = saasApp;
}
public int getValidityPeriod() {
return validityPeriod;
}
public void setValidityPeriod(int validityPeriod) {
this.validityPeriod = validityPeriod;
}
}

@ -46,5 +46,6 @@ public interface KeyManagerService {
@FormParam("assertion") String assertion,
@FormParam("admin_access_token") String admin_access_token,
@FormParam("username") String username,
@FormParam("password") String password);
@FormParam("password") String password,
@FormParam("validityPeriod") int validityPeriod);
}

@ -51,7 +51,7 @@ public class KeyManagerServiceImpl implements KeyManagerService {
try {
KeyMgtService keyMgtService = new KeyMgtServiceImpl();
DCRResponse resp = keyMgtService.dynamicClientRegistration(dcrRequest.getApplicationName(), dcrRequest.getUsername(),
dcrRequest.getGrantTypes(), dcrRequest.getCallBackUrl(), dcrRequest.getTags(), dcrRequest.getIsSaasApp());
dcrRequest.getGrantTypes(), dcrRequest.getCallBackUrl(), dcrRequest.getTags(), dcrRequest.getIsSaasApp(), dcrRequest.getValidityPeriod());
return Response.status(Response.Status.CREATED).entity(gson.toJson(resp)).build();
} catch (KeyMgtException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
@ -69,7 +69,8 @@ public class KeyManagerServiceImpl implements KeyManagerService {
@FormParam("assertion") String assertion,
@FormParam("admin_access_token") String admin_access_token,
@FormParam("username") String username,
@FormParam("password") String password) {
@FormParam("password") String password,
@FormParam("validityPeriod") int validityPeriod) {
try {
if (basicAuthHeader == null) {
String msg = "Invalid credentials. Make sure your API call is invoked with a Basic Authorization header.";
@ -80,7 +81,7 @@ public class KeyManagerServiceImpl implements KeyManagerService {
TokenResponse resp = keyMgtService.generateAccessToken(
new TokenRequest(encodedClientCredentials.split(":")[0],
encodedClientCredentials.split(":")[1], refreshToken, scope,
grantType, assertion, admin_access_token, username, password));
grantType, assertion, admin_access_token, username, password, validityPeriod));
return Response.status(Response.Status.OK).entity(gson.toJson(resp)).build();
} catch (KeyMgtException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();

@ -3,7 +3,7 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.16-SNAPSHOT</version>
<version>5.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -29,8 +29,10 @@ public class TokenRequest {
private String username;
private String password;
private int validityPeriod;
public TokenRequest(String clientId, String clientSecret, String refreshToken, String scope, String grantType,
String assertion, String admin_access_token, String username, String password) {
String assertion, String admin_access_token, String username, String password, int validityPeriod) {
this.clientId = clientId;
this.clientSecret = clientSecret;
this.refreshToken = refreshToken;
@ -40,6 +42,7 @@ public class TokenRequest {
this.admin_access_token = admin_access_token;
this.username = username;
this.password = password;
this.validityPeriod = validityPeriod;
}
public String getClientId() {
@ -113,4 +116,12 @@ public class TokenRequest {
public void setPassword(String password) {
this.password = password;
}
public int getValidityPeriod() {
return validityPeriod;
}
public void setValidityPeriod(int validityPeriod) {
this.validityPeriod = validityPeriod;
}
}

@ -39,7 +39,7 @@ public interface KeyMgtService {
* @throws KeyMgtException if any error occurs during DCR process
*/
DCRResponse dynamicClientRegistration(String clientName, String owner, String grantTypes, String callBackUrl,
String[] tags, boolean isSaasApp) throws KeyMgtException;
String[] tags, boolean isSaasApp, int validityPeriod) throws KeyMgtException;
/***
* This method will handle the access token requests

@ -77,7 +77,7 @@ public class KeyMgtServiceImpl implements KeyMgtService {
String subTenantUserUsername, subTenantUserPassword, keyManagerName, msg = null;
public DCRResponse dynamicClientRegistration(String clientName, String owner, String grantTypes, String callBackUrl,
String[] tags, boolean isSaasApp) throws KeyMgtException {
String[] tags, boolean isSaasApp, int validityPeriod) throws KeyMgtException {
if (owner == null) {
PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
@ -105,13 +105,13 @@ public class KeyMgtServiceImpl implements KeyMgtService {
kmConfig = getKeyManagerConfig();
if (KeyMgtConstants.SUPER_TENANT.equals(tenantDomain)) {
OAuthApplication dcrApplication = createOauthApplication(clientName, kmConfig.getAdminUsername(), tags);
OAuthApplication dcrApplication = createOauthApplication(clientName, kmConfig.getAdminUsername(), tags, validityPeriod);
return new DCRResponse(dcrApplication.getClientId(), dcrApplication.getClientSecret());
} else {
// super-tenant admin dcr and token generation
OAuthApplication superTenantOauthApp = createOauthApplication(
KeyMgtConstants.RESERVED_OAUTH_APP_NAME_PREFIX + KeyMgtConstants.SUPER_TENANT,
kmConfig.getAdminUsername(), null);
kmConfig.getAdminUsername(), null, validityPeriod);
String superAdminAccessToken = createAccessToken(superTenantOauthApp);
// create new key manager for the tenant, under super-tenant space
@ -133,7 +133,7 @@ public class KeyMgtServiceImpl implements KeyMgtService {
createUserIfNotExists(subTenantUserUsername, subTenantUserPassword);
// DCR for the requesting user
OAuthApplication dcrApplication = createOauthApplication(clientName, owner, tags);
OAuthApplication dcrApplication = createOauthApplication(clientName, owner, tags, validityPeriod);
String requestingUserAccessToken = createAccessToken(dcrApplication);
// get application id
@ -167,7 +167,8 @@ public class KeyMgtServiceImpl implements KeyMgtService {
case "client_credentials":
appTokenPayload = new FormBody.Builder()
.add("grant_type", "client_credentials")
.add("scope", tokenRequest.getScope()).build();
.add("scope", tokenRequest.getScope())
.add("validityPeriod", String.valueOf(tokenRequest.getValidityPeriod())).build();
break;
case "password":
appTokenPayload = new FormBody.Builder()
@ -322,8 +323,8 @@ public class KeyMgtServiceImpl implements KeyMgtService {
* @return @{@link OAuthApplication} OAuth application object
* @throws KeyMgtException if any error occurs while creating response object
*/
private OAuthApplication createOauthApplication (String clientName, String owner, String[] tags) throws KeyMgtException {
String oauthAppCreationPayloadStr = createOauthAppCreationPayload(clientName, owner, tags);
private OAuthApplication createOauthApplication (String clientName, String owner, String[] tags, int validityPeriod) throws KeyMgtException {
String oauthAppCreationPayloadStr = createOauthAppCreationPayload(clientName, owner, tags, validityPeriod);
RequestBody oauthAppCreationPayload = RequestBody.Companion.create(oauthAppCreationPayloadStr, JSON);
kmConfig = getKeyManagerConfig();
String dcrEndpoint = kmConfig.getServerUrl() + KeyMgtConstants.DCR_ENDPOINT;
@ -442,11 +443,12 @@ public class KeyMgtServiceImpl implements KeyMgtService {
}
}
private String createOauthAppCreationPayload(String clientName, String owner, String[] tags) {
private String createOauthAppCreationPayload(String clientName, String owner, String[] tags, int validityPeriod) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("applicationName", clientName);
jsonObject.put("username", owner);
jsonObject.put("tags", tags);
jsonObject.put("validityPeriod", validityPeriod);
return jsonObject.toString();
}

@ -22,7 +22,7 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.16-SNAPSHOT</version>
<version>5.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>carbon-devicemgt</artifactId>
<version>5.0.16-SNAPSHOT</version>
<version>5.0.21-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
@ -39,6 +39,7 @@
<module>org.wso2.carbon.apimgt.annotations</module>
<module>org.wso2.carbon.apimgt.keymgt.extension</module>
<module>org.wso2.carbon.apimgt.keymgt.extension.api</module>
<module>io.entgra.device.mgt.core.apimgt.analytics.extension</module>
</modules>
<build>

@ -20,7 +20,7 @@
<parent>
<artifactId>application-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.16-SNAPSHOT</version>
<version>5.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>application-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.16-SNAPSHOT</version>
<version>5.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>application-mgt</artifactId>
<version>5.0.16-SNAPSHOT</version>
<version>5.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>application-mgt</artifactId>
<version>5.0.16-SNAPSHOT</version>
<version>5.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -94,6 +94,7 @@ public class SQLServerApplicationDAOImpl extends GenericApplicationDAOImpl {
|| StringUtils.isNotEmpty(filter.getAppReleaseType())) {
sql += "LEFT JOIN AP_APP_RELEASE ON AP_APP.ID = AP_APP_RELEASE.AP_APP_ID ";
}
sql += "WHERE AP_APP.TENANT_ID = ? ";
if (StringUtils.isNotEmpty(filter.getAppType()) && !Constants.ALL.equalsIgnoreCase(filter.getAppType())) {
sql += "AND AP_APP.TYPE = ? ";
}
@ -128,7 +129,7 @@ public class SQLServerApplicationDAOImpl extends GenericApplicationDAOImpl {
sql += filter.getSortBy() +" ";
}
if (filter.getLimit() != -1) {
sql += "ORDER BY ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY ";
sql += "OFFSET ? ROWS FETCH NEXT ? ROWS ONLY ";
}
sql += ") AS app_data ON app_data.ID = AP_APP.ID "
+ "LEFT JOIN ("
@ -145,6 +146,7 @@ public class SQLServerApplicationDAOImpl extends GenericApplicationDAOImpl {
Connection conn = this.getDBConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
int paramIndex = 1;
stmt.setInt(paramIndex++, tenantId);
if (StringUtils.isNotEmpty(filter.getAppType()) && !Constants.ALL.equalsIgnoreCase(filter.getAppType())) {
stmt.setString(paramIndex++, filter.getAppType());
}

@ -3434,6 +3434,7 @@ public class ApplicationManagerImpl implements ApplicationManager {
String userName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
int deviceTypeId = -1;
String appName;
int appNameLength = 20;
List<String> appCategories;
List<String> unrestrictedRoles;
@ -3445,6 +3446,11 @@ public class ApplicationManagerImpl implements ApplicationManager {
log.error(msg);
throw new BadRequestException(msg);
}
if (appName.length() > appNameLength) {
String msg = "Application name must be less than or equal to 20 characters in length.";
log.error(msg);
throw new BadRequestException(msg);
}
appCategories = applicationWrapper.getCategories();
if (appCategories == null) {
String msg = "Application category can't be null.";
@ -3477,6 +3483,11 @@ public class ApplicationManagerImpl implements ApplicationManager {
log.error(msg);
throw new BadRequestException(msg);
}
if (appName.length() > appNameLength) {
String msg = "Application name must be less than or equal to 20 characters in length.";
log.error(msg);
throw new BadRequestException(msg);
}
appCategories = webAppWrapper.getCategories();
if (appCategories == null) {
String msg = "Web Clip category can't be null.";
@ -3510,6 +3521,11 @@ public class ApplicationManagerImpl implements ApplicationManager {
log.error(msg);
throw new BadRequestException(msg);
}
if (appName.length() > appNameLength) {
String msg = "Application name must be less than or equal to 20 characters in length.";
log.error(msg);
throw new BadRequestException(msg);
}
appCategories = publicAppWrapper.getCategories();
if (appCategories == null) {
String msg = "Application category can't be null.";
@ -3542,6 +3558,11 @@ public class ApplicationManagerImpl implements ApplicationManager {
log.error(msg);
throw new BadRequestException(msg);
}
if (appName.length() > appNameLength) {
String msg = "Application name must be less than or equal to 20 characters in length.";
log.error(msg);
throw new BadRequestException(msg);
}
appCategories = customAppWrapper.getCategories();
if (appCategories == null) {
String msg = "Application category can't be null.";

@ -22,7 +22,7 @@
<parent>
<artifactId>application-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.16-SNAPSHOT</version>
<version>5.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -169,7 +169,7 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem
@Consumes(MediaType.APPLICATION_JSON)
@Path("/ent-app")
public Response createEntApp(
ApplicationWrapper applicationWrapper, @QueryParam("isPublished") boolean isPublished) {
ApplicationWrapper applicationWrapper, @QueryParam("is-published") boolean isPublished) {
try {
return createApplication(applicationWrapper, isPublished);
} catch (BadRequestException e) {
@ -191,7 +191,7 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem
@Consumes(MediaType.APPLICATION_JSON)
@Path("/web-app")
public Response createWebApp(
WebAppWrapper webAppWrapper, @QueryParam("isPublished") boolean isPublished) {
WebAppWrapper webAppWrapper, @QueryParam("is-published") boolean isPublished) {
try {
return createApplication(webAppWrapper, isPublished);
} catch (BadRequestException e) {
@ -213,7 +213,7 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem
@Consumes(MediaType.APPLICATION_JSON)
@Path("/public-app")
public Response createPubApp(
PublicAppWrapper publicAppWrapper, @QueryParam("isPublished") boolean isPublished) {
PublicAppWrapper publicAppWrapper, @QueryParam("is-published") boolean isPublished) {
try {
return createApplication(publicAppWrapper, isPublished);
} catch (BadRequestException e) {
@ -235,7 +235,7 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem
@Consumes(MediaType.APPLICATION_JSON)
@Path("/custom-app")
public Response createCustomApp(
CustomAppWrapper customAppWrapper, @QueryParam("isPublished") boolean isPublished) {
CustomAppWrapper customAppWrapper, @QueryParam("is-published") boolean isPublished) {
try {
return createApplication(customAppWrapper, isPublished);
} catch (BadRequestException e) {
@ -371,19 +371,28 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem
if (appName == null) {
String msg = "Invalid app name, appName query param cannot be empty/null.";
log.error(msg);
return Response.status(Response.Status.BAD_REQUEST).build();
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
}
if (appName.length() > 20) {
String msg = "Invalid app name, maximum length of the application name should be 20 characters.";
log.error(msg);
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
}
ApplicationManager applicationManager = APIUtil.getApplicationManager();
if (applicationManager.isExistingAppName(appName, deviceType)) {
return Response.status(Response.Status.CONFLICT).build();
String msg = "Invalid app name, app name already exists.";
log.error(msg);
return Response.status(Response.Status.CONFLICT).entity(msg).build();
}
return Response.status(Response.Status.OK).build();
} catch (BadRequestException e) {
log.error("Found invalid device type to check application existence.", e);
return Response.status(Response.Status.BAD_REQUEST).build();
String msg = "Found invalid device type to check application existence.";
log.error(msg, e);
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
} catch (ApplicationManagementException e) {
log.error("Internal Error occurred while checking the application existence.", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
String msg = "Internal Error occurred while checking the application existence.";
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
}
}

@ -22,7 +22,7 @@
<parent>
<artifactId>application-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.16-SNAPSHOT</version>
<version>5.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

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

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

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

@ -38,7 +38,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>certificate-mgt</artifactId>
<version>5.0.16-SNAPSHOT</version>
<version>5.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

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

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

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

@ -48,6 +48,22 @@ public interface EntgraLogger extends Log {
void warn(Object object, Throwable t, LogContext logContext);
void info(String message, LogContext logContext);
void debug(String message, LogContext logContext);
void error(String message, LogContext logContext);
void error(String message, Throwable t, LogContext logContext);
void warn(String message, LogContext logContext);
void warn(String message, Throwable t, LogContext logContext);
void trace(String message, LogContext logContext);
void fatal(String message, LogContext logContext);
void clearLogContext();
}

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

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

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

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

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

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

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

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

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

@ -22,7 +22,7 @@
<parent>
<artifactId>device-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>5.0.16-SNAPSHOT</version>
<version>5.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -145,6 +145,11 @@
</profiles>
<dependencies>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.10.0</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
@ -425,5 +430,35 @@
<artifactId>io.entgra.application.mgt.core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.apimgt.keymgt.extension</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.analytics-common</groupId>
<artifactId>org.wso2.carbon.event.stream.core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.analytics-common</groupId>
<artifactId>org.wso2.carbon.event.receiver.core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.analytics-common</groupId>
<artifactId>org.wso2.carbon.event.publisher.core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.analytics-common</groupId>
<artifactId>org.wso2.carbon.event.output.adapter.rdbms</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>io.entgra.device.mgt.core.apimgt.analytics.extension</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

@ -0,0 +1,52 @@
package org.wso2.carbon.device.mgt.jaxrs.beans;
import okhttp3.Request;
import okhttp3.Response;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class BatchResponse implements Serializable {
private List<Response> responses = new ArrayList<>();
private boolean success;
private List<Response> failedResponses = new ArrayList<>();
private List<Response> succeededResponses = new ArrayList<>();
private List<Request> failedRequests = new ArrayList<>();
public void setResponses(List<Response> responses) { this.responses = responses; }
public List<Response> getResponses() { return this.responses; }
public void setFailedResponses(List<Response> failedResponses) { this.failedResponses = failedResponses; }
public List<Response> getFailedResponses() { return this.failedResponses; }
public void setSucceededResponses(List<Response> succeededResponses) { this.succeededResponses = succeededResponses; }
public List<Response> getSucceededResponses() { return this.succeededResponses; }
public void setFailedRequests(List<Request> failedRequests) { this.failedRequests = failedRequests; }
public List<Request> getFailedRequests() { return this.failedRequests; }
public void setSuccess(boolean success) { this.success = success; }
public boolean getSuccess() { return this.success; }
public void addResponse(Response response) {
this.responses.add(response);
if(response.isSuccessful()) {
this.succeededResponses.add(response);
} else {
this.failedResponses.add(response);
}
}
public void addRequest(Request request) {
this.failedRequests.add(request);
}
public BatchResponse() {}
}

@ -0,0 +1,116 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.jaxrs.beans;
import io.swagger.annotations.ApiModel;
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration;
import java.util.List;
@ApiModel(value = "DeviceConfig", description = "Device config")
public class DeviceConfig {
private String clientId;
private String clientSecret;
private String deviceId;
private String type;
private String accessToken;
private String refreshToken;
private String mqttGateway;
private String httpsGateway;
private String httpGateway;
private PlatformConfiguration platformConfiguration;
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public String getClientSecret() {
return clientSecret;
}
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
public String getMqttGateway() {
return mqttGateway;
}
public void setMqttGateway(String mqttGateway) {
this.mqttGateway = mqttGateway;
}
public String getHttpsGateway() {
return httpsGateway;
}
public void setHttpsGateway(String httpsGateway) {
this.httpsGateway = httpsGateway;
}
public String getHttpGateway() {
return httpGateway;
}
public void setHttpGateway(String httpGateway) {
this.httpGateway = httpGateway;
}
public PlatformConfiguration getPlatformConfiguration() {
return platformConfiguration;
}
public void setPlatformConfiguration(PlatformConfiguration platformConfiguration) {
this.platformConfiguration = platformConfiguration;
}
}

@ -35,8 +35,11 @@ public class DeviceList extends BasePaginatedResult {
@ApiModelProperty(name = "message", value = "Send information text to the billing UI", required = false)
private String message;
@ApiModelProperty(name = "billedDateIsValid", value = "Check if user entered date is valid", required = false)
private boolean billedDateIsValid;
@ApiModelProperty(name = "deviceCount", value = "Total count of all devices per tenant", required = false)
private double deviceCount;
@ApiModelProperty(name = "billPeriod", value = "Billed period", required = false)
private String billPeriod;
@ApiModelProperty(value = "List of devices returned")
@JsonProperty("devices")
@ -48,12 +51,20 @@ public class DeviceList extends BasePaginatedResult {
this.devices = devices;
}
public boolean isBilledDateIsValid() {
return billedDateIsValid;
public String getBillPeriod() {
return billPeriod;
}
public void setBillPeriod(String billPeriod) {
this.billPeriod = billPeriod;
}
public double getDeviceCount() {
return deviceCount;
}
public void setBilledDateIsValid(boolean billedDateIsValid) {
this.billedDateIsValid = billedDateIsValid;
public void setDeviceCount(double deviceCount) {
this.deviceCount = deviceCount;
}
public String getMessage() {

@ -20,14 +20,18 @@ package org.wso2.carbon.device.mgt.jaxrs.beans.analytics;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import java.util.List;
/**
* This hold stats data record
*/
public class DeviceTypeEvent {
private String eventName;
private EventAttributeList eventAttributes;
private TransportType transport;
private String eventTopicStructure;
@ApiModelProperty(value = "Attributes related to device type event")
@JsonProperty("eventAttributes")
public EventAttributeList getEventAttributeList() {
@ -48,5 +52,25 @@ public class DeviceTypeEvent {
public void setTransportType(TransportType transport) {
this.transport = transport;
}
@ApiModelProperty(value = "event topic structure")
@JsonProperty("eventTopicStructure")
public String getEventTopicStructure() {
return eventTopicStructure;
}
public void setEventTopicStructure(String eventTopicStructure) {
this.eventTopicStructure = eventTopicStructure;
}
@ApiModelProperty(value = "event topic name")
@JsonProperty("eventName")
public String getEventName() {
return eventName;
}
public void setEventName(String eventName) {
this.eventName = eventName;
}
}

@ -29,6 +29,7 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;
@SwaggerDefinition(
info = @Info(
@ -69,64 +70,64 @@ import javax.ws.rs.core.Response;
@Consumes(MediaType.APPLICATION_JSON)
public interface DeviceEventManagementService {
// @POST
// @Path("/{type}")
// @ApiOperation(
// produces = MediaType.APPLICATION_JSON,
// httpMethod = "POST",
// value = "Adding the Event Type Definition",
// notes = "Add the event definition for a device.",
// tags = "Device Event Management",
// extensions = {
// @Extension(properties = {
// @ExtensionProperty(name = Constants.SCOPE, value = "perm:device-types:events")
// })
// }
// )
// @ApiResponses(
// value = {
// @ApiResponse(
// code = 200,
// message = "OK. \n Successfully added the event defintion.",
// responseHeaders = {
// @ResponseHeader(
// name = "Content-Type",
// description = "The content type of the body"),
// @ResponseHeader(
// name = "ETag",
// description = "Entity Tag of the response resource.\n" +
// "Used by caches, or in conditional requests."),
// @ResponseHeader(
// name = "Last-Modified",
// description =
// "Date and time the resource was last modified.\n" +
// "Used by caches, or in conditional requests."),
// }
// ),
// @ApiResponse(
// code = 400,
// message =
// "Bad Request. \n"),
// @ApiResponse(
// code = 406,
// message = "Not Acceptable.\n The requested media type is not supported"),
// @ApiResponse(
// code = 500,
// message = "Internal Server Error. \n Server error occurred while fetching the " +
// "list of supported device types.",
// response = ErrorResponse.class)
// }
// )
// Response deployDeviceTypeEventDefinition(
// @ApiParam(name = "type", value = "The device type, such as android, ios, and windows.")
// @PathParam("type")String deviceType,
// @ApiParam(name = "skipPersist", value = "Is it required to persist the data or not")
// @QueryParam("skipPersist") boolean skipPersist,
// @ApiParam(name = "isSharedWithAllTenants", value = "Should artifacts be available to all tenants")
// @QueryParam("isSharedWithAllTenants") boolean isSharedWithAllTenants,
// @ApiParam(name = "deviceTypeEvent", value = "Add the data to complete the DeviceTypeEvent object.",
// required = true)
// @Valid DeviceTypeEvent deviceTypeEvent);
@POST
@Path("/{type}")
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "POST",
value = "Adding the Event Type Definition",
notes = "Add the event definition for a device.",
tags = "Device Event Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:device-types:events")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully added the event defintion.",
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description =
"Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests."),
}
),
@ApiResponse(
code = 400,
message =
"Bad Request. \n"),
@ApiResponse(
code = 406,
message = "Not Acceptable.\n The requested media type is not supported"),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Server error occurred while fetching the " +
"list of supported device types.",
response = ErrorResponse.class)
}
)
Response deployDeviceTypeEventDefinition(
@ApiParam(name = "type", value = "The device type, such as android, ios, and windows.")
@PathParam("type")String deviceType,
@ApiParam(name = "skipPersist", value = "Is it required to persist the data or not")
@QueryParam("skipPersist") boolean skipPersist,
@ApiParam(name = "isSharedWithAllTenants", value = "Should artifacts be available to all tenants")
@QueryParam("isSharedWithAllTenants") boolean isSharedWithAllTenants,
@ApiParam(name = "deviceTypeEvents", value = "Add the data to complete the DeviceTypeEvent object.",
required = true)
@Valid List<DeviceTypeEvent> deviceTypeEvent);
@DELETE
@Path("/{type}")

@ -188,6 +188,13 @@ import java.util.List;
roles = {"Internal/devicemgt-user"},
permissions = {"/device-mgt/devices/owning-device/add"}
),
@Scope(
name = "Viewing Enrollment Guide",
description = "Show enrollment guide to users",
key = "perm:devices:enrollment-guide:view",
roles = {"Internal/devicemgt-user"},
permissions = {"/device-mgt/devices/enrollment-guide/view"}
),
}
)
@Path("/devices")
@ -344,179 +351,6 @@ public interface DeviceManagementService {
@QueryParam("limit")
int limit);
@GET
@Path("/billing")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "Getting Cost details of devices in a tenant",
notes = "Provides individual cost and total cost of all devices per tenant.",
tags = "Device Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:devices:view")
})
}
)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK. \n Successfully fetched the list of devices.",
response = DeviceList.class,
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests."),
}),
@ApiResponse(
code = 304,
message = "Not Modified. \n Empty body because the client already has the latest version of " +
"the requested resource.\n"),
@ApiResponse(
code = 400,
message = "The incoming request has more than one selection criteria defined via the query parameters.",
response = ErrorResponse.class),
@ApiResponse(
code = 404,
message = "The search criteria did not match any device registered with the server.",
response = ErrorResponse.class),
@ApiResponse(
code = 406,
message = "Not Acceptable.\n The requested media type is not supported."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Server error occurred while fetching the device list.",
response = ErrorResponse.class)
})
Response getDevicesBilling(
@ApiParam(
name = "tenantDomain",
value = "The tenant domain.",
required = false)
@QueryParam("tenantDomain")
String tenantDomain,
@ApiParam(
name = "startDate",
value = "The start date.",
required = false)
@QueryParam("startDate")
Timestamp startDate,
@ApiParam(
name = "endDate",
value = "The end date.",
required = false)
@QueryParam("endDate")
Timestamp endDate,
@ApiParam(
name = "generateBill",
value = "The generate bill boolean.",
required = false)
@QueryParam("generateBill")
boolean generateBill,
@ApiParam(
name = "offset",
value = "The starting pagination index for the complete list of qualified items.",
required = false,
defaultValue = "0")
@QueryParam("offset")
int offset,
@ApiParam(
name = "limit",
value = "Provide how many device details you require from the starting pagination index/offset.",
required = false,
defaultValue = "10")
@QueryParam("limit")
int limit);
@GET
@Path("/billing/file")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "Getting Cost details of devices in a tenant",
notes = "Provides individual cost and total cost of all devices per tenant.",
tags = "Device Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:devices:view")
})
}
)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK. \n Successfully fetched the list of devices.",
response = DeviceList.class,
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body"),
@ResponseHeader(
name = "Content-Disposition",
description = "The content disposition of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests."),
}),
@ApiResponse(
code = 304,
message = "Not Modified. \n Empty body because the client already has the latest version of " +
"the requested resource.\n"),
@ApiResponse(
code = 400,
message = "The incoming request has more than one selection criteria defined via the query parameters.",
response = ErrorResponse.class),
@ApiResponse(
code = 404,
message = "The search criteria did not match any device registered with the server.",
response = ErrorResponse.class),
@ApiResponse(
code = 406,
message = "Not Acceptable.\n The requested media type is not supported."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Server error occurred while fetching the device list.",
response = ErrorResponse.class)
})
Response exportBilling(
@ApiParam(
name = "tenantDomain",
value = "The tenant domain.",
required = false)
@QueryParam("tenantDomain")
String tenantDomain,
@ApiParam(
name = "startDate",
value = "The start date.",
required = false)
@QueryParam("startDate")
Timestamp startDate,
@ApiParam(
name = "endDate",
value = "The end date.",
required = false)
@QueryParam("endDate")
Timestamp endDate,
@ApiParam(
name = "generateBill",
value = "The generate bill boolean.",
required = false)
@QueryParam("generateBill")
boolean generateBill);
@GET
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(
@ -726,12 +560,12 @@ public interface DeviceManagementService {
required = false,
defaultValue = "0")
@QueryParam("offset") int offset,
@ApiParam(
name = "limit",
value = "Provide how many device details you require from the starting pagination index/offset.",
required = false,
defaultValue = "100")
@QueryParam("limit") int limit
@ApiParam(
name = "limit",
value = "Provide how many device details you require from the starting pagination index/offset.",
required = false,
defaultValue = "100")
@QueryParam("limit") int limit
);
@GET
@ -975,6 +809,59 @@ public interface DeviceManagementService {
@QueryParam("requireDeviceInfo")
boolean requireDeviceInfo);
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Path("/enrollment/guide")
@ApiOperation(
consumes = MediaType.MULTIPART_FORM_DATA,
produces = MediaType.APPLICATION_JSON,
httpMethod = "POST",
value = "Sending Enrollment Mode chosen by customer",
notes = "Enrollment mode selected and path is sent as parameters",
tags = "Device Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:devices:enrollment-guide:view")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully mailed the Enrollment Guide of customer.",
response = Device.class,
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests."),
}),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error.",
response = ErrorResponse.class),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n " +
"Server error occurred while sending mail of the Enrollment Guide.",
response = ErrorResponse.class)
})
Response sendEnrollmentGuide(
@ApiParam(
name = "enrolmentGuide",
value = "The details of the enrolment path suggested.",
required = true)
String enrolmentGuide);
@POST
@Produces(MediaType.APPLICATION_JSON)
@Path("/type/any/list")
@ -1232,6 +1119,82 @@ public interface DeviceManagementService {
@HeaderParam("If-Modified-Since")
String ifModifiedSince);
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/{type}/{id}/config")
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "Getting the Configuration of a Device",
notes = "Get the configuration of a device by specifying the device type and device identifier.",
tags = "Device Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:devices:details")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully fetched the configuration of the device.",
response = DeviceInfo.class,
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests."),
}),
@ApiResponse(
code = 304,
message = "Not Modified. Empty body because the client already has the latest version" +
" of the requested resource.\n"),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error.",
response = ErrorResponse.class),
@ApiResponse(
code = 404,
message = "Not Found. \n Location data for the specified device was not found.",
response = ErrorResponse.class),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n " +
"Server error occurred while retrieving the device details.",
response = ErrorResponse.class)
})
Response getDeviceConfiguration(
@ApiParam(
name = "type",
value = "The device type name, such as ios, android, windows, or fire-alarm.",
required = true)
@PathParam("type")
@Size(max = 45)
String type,
@ApiParam(
name = "id",
value = "The device identifier of the device you want ot get details.",
required = true)
@PathParam("id")
@Size(max = 45)
String id,
@ApiParam(
name = "If-Modified-Since",
value = "Checks if the requested variant was modified, since the specified date-time. \n" +
"Provide the value in the following format: EEE, d MMM yyyy HH:mm:ss Z. \n" +
"Example: Mon, 05 Jan 2014 15:10:00 +0200",
required = false)
@HeaderParam("If-Modified-Since")
String ifModifiedSince);
//device rename request would looks like follows
//POST devices/type/virtual_firealarm/id/us06ww93auzp/rename
@POST
@ -1382,7 +1345,7 @@ public interface DeviceManagementService {
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/{type}/{id}/features")
@Path("/device-type/{type}/features")
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
@ -1453,14 +1416,6 @@ public interface DeviceManagementService {
@PathParam("type")
@Size(max = 45)
String type,
@ApiParam(
name = "id",
value = "The device identifier of the device.\n" +
"INFO: Make sure to add the ID of a device that is already registered with WSO2 IoTS.",
required = true)
@PathParam("id")
@Size(max = 45)
String id,
@ApiParam(
name = "If-Modified-Since",
value = "Checks if the requested variant was modified, since the specified date-time. \n" +
@ -1580,15 +1535,15 @@ public interface DeviceManagementService {
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource was last modified. \n" +
"Used by caches, or in conditional requests.")}),
"Used by caches, or in conditional requests.")}),
@ApiResponse(
code = 304,
message = "Not Modified. \n " +
"Empty body because the client already has the latest version of the requested resource.\n"),
"Empty body because the client already has the latest version of the requested resource.\n"),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error.",
@ -1606,7 +1561,7 @@ public interface DeviceManagementService {
@ApiResponse(
code = 500,
message = "Internal Server Error. \n " +
"Server error occurred while getting the device details.",
"Server error occurred while getting the device details.",
response = ErrorResponse.class)
})
Response queryDevicesByProperties(
@ -1628,7 +1583,7 @@ public interface DeviceManagementService {
name = "device property map",
value = "properties by which devices need filtered",
required = true)
PropertyMap map);
PropertyMap map);
@GET
@Produces(MediaType.APPLICATION_JSON)
@ -2054,140 +2009,141 @@ public interface DeviceManagementService {
@Size(max = 45)
String id);
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/{type}/{id}/getstatushistory")
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "Get Device status history",
notes = "Get a list of status history associated with the device type and id",
tags = "Device Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:devices:view")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully fetched the status history of matching devices.",
response = List.class,
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests."),
}),
@ApiResponse(
code = 304,
message = "Not Modified. Empty body because the client already has the latest version" +
" of the requested resource.\n"),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error.",
response = ErrorResponse.class),
@ApiResponse(
code = 404,
message = "Not Found. \n A device with the specified device type and id was not found.",
response = ErrorResponse.class),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n " +
"Server error occurred while retrieving the device details.",
response = ErrorResponse.class)
})
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/{type}/{id}/status-history")
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "Get Device status history",
notes = "Get a list of status history associated with the device type and id",
tags = "Device Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:devices:view")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully fetched the status history of matching devices.",
response = List.class,
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests."),
}),
@ApiResponse(
code = 304,
message = "Not Modified. Empty body because the client already has the latest version" +
" of the requested resource.\n"),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error.",
response = ErrorResponse.class),
@ApiResponse(
code = 404,
message = "Not Found. \n A device with the specified device type and id was not found.",
response = ErrorResponse.class),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n " +
"Server error occurred while retrieving the device details.",
response = ErrorResponse.class)
})
Response getDeviceStatusHistory(
@ApiParam(
name = "type",
value = "The device type, such as ios, android, or windows.",
required = true)
@PathParam("type")
@Size(max = 45)
String type,
@ApiParam(
name = "id",
value = "Device ID.",
required = true)
@PathParam("id")
@Size(max = 45)
String id);
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/{type}/{id}/getenrolmentstatushistory")
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "Get Device Current Enrolment status history",
notes = "Get a list of status history associated with the device type and id for the current enrolment",
tags = "Device Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:devices:view")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully fetched the status history of matching devices.",
response = List.class,
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests."),
}),
@ApiResponse(
code = 304,
message = "Not Modified. Empty body because the client already has the latest version" +
" of the requested resource.\n"),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error.",
response = ErrorResponse.class),
@ApiResponse(
code = 404,
message = "Not Found. \n A device with the specified device type and id was not found.",
response = ErrorResponse.class),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n " +
"Server error occurred while retrieving the device details.",
response = ErrorResponse.class)
})
@ApiParam(
name = "type",
value = "The device type, such as ios, android, or windows.",
required = true)
@PathParam("type")
@Size(max = 45)
String type,
@ApiParam(
name = "id",
value = "Device ID.",
required = true)
@PathParam("id")
@Size(max = 45)
String id);
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/{type}/{id}/enrolment-status-history")
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "Get Device Current Enrolment status history",
notes = "Get a list of status history associated with the device type and id for the current enrolment",
tags = "Device Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:devices:view")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully fetched the status history of matching devices.",
response = List.class,
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests."),
}),
@ApiResponse(
code = 304,
message = "Not Modified. Empty body because the client already has the latest version" +
" of the requested resource.\n"),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error.",
response = ErrorResponse.class),
@ApiResponse(
code = 404,
message = "Not Found. \n A device with the specified device type and id was not found.",
response = ErrorResponse.class),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n " +
"Server error occurred while retrieving the device details.",
response = ErrorResponse.class)
})
Response getCurrentEnrolmentDeviceStatusHistory(
@ApiParam(
name = "type",
value = "The device type, such as ios, android, or windows.",
required = true)
@PathParam("type")
@Size(max = 45)
String type,
@ApiParam(
name = "id",
value = "Device ID.",
required = true)
@PathParam("id")
@Size(max = 45)
String id);
@ApiParam(
name = "type",
value = "The device type, such as ios, android, or windows.",
required = true)
@PathParam("type")
@Size(max = 45)
String type,
@ApiParam(
name = "id",
value = "Device ID.",
required = true)
@PathParam("id")
@Size(max = 45)
String id);
@PUT
@Produces(MediaType.APPLICATION_JSON)
@ -2352,16 +2308,16 @@ public interface DeviceManagementService {
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests."),
"Used by caches, or in conditional requests."),
}),
@ApiResponse(
code = 304,
message = "Not Modified. Empty body because the client already has the latest version" +
" of the requested resource.\n"),
" of the requested resource.\n"),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error.",
@ -2373,7 +2329,7 @@ public interface DeviceManagementService {
@ApiResponse(
code = 500,
message = "Internal Server Error. \n " +
"Server error occurred while retrieving the device details.",
"Server error occurred while retrieving the device details.",
response = ErrorResponse.class)
})
Response getDeviceCountByStatus(
@ -2421,16 +2377,16 @@ public interface DeviceManagementService {
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests."),
"Used by caches, or in conditional requests."),
}),
@ApiResponse(
code = 304,
message = "Not Modified. Empty body because the client already has the latest version" +
" of the requested resource.\n"),
" of the requested resource.\n"),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error.",
@ -2442,7 +2398,7 @@ public interface DeviceManagementService {
@ApiResponse(
code = 500,
message = "Internal Server Error. \n " +
"Server error occurred while retrieving the device details.",
"Server error occurred while retrieving the device details.",
response = ErrorResponse.class)
})
Response getDeviceIdentifiersByStatus(
@ -2491,16 +2447,16 @@ public interface DeviceManagementService {
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource has been modified the last time.\n" +
"Used by caches, or in conditional requests."),
"Used by caches, or in conditional requests."),
}),
@ApiResponse(
code = 304,
message = "Not Modified. Empty body because the client already has the latest " +
"version of the requested resource."),
"version of the requested resource."),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error.",
@ -2512,7 +2468,7 @@ public interface DeviceManagementService {
@ApiResponse(
code = 500,
message = "Internal Server Error. \n " +
"Server error occurred while retrieving information requested device.",
"Server error occurred while retrieving information requested device.",
response = ErrorResponse.class)
})
Response bulkUpdateDeviceStatus(
@ -2823,11 +2779,11 @@ public interface DeviceManagementService {
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests."),
"Used by caches, or in conditional requests."),
}),
@ApiResponse(
code = 500,

@ -192,6 +192,13 @@ import java.util.List;
key = "perm:groups:device",
roles = {"Internal/devicemgt-user"},
permissions = {"/device-mgt/groups/devices/view"}
),
@Scope(
name = "View whether the groups has relevant device types",
description = "View whether the groups has relevant device types",
key = "perm:groups:devices-types",
roles = {"Internal/devicemgt-user"},
permissions = {"/device-mgt/groups/devices/types"}
)
}
)
@ -1185,4 +1192,58 @@ public interface GroupManagementService {
@QueryParam("requireGroupProps")
boolean requireGroupProps);
@Path("/device-types")
@POST
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = HTTPConstants.HEADER_GET,
value = "Getting Details whether the groups has relevant device type or not",
notes = "Getting Details whether the groups has relevant device type or not.",
tags = "Device Group Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:groups:devices-types")
})
},
nickname = "getGroupByGroupNameFilter"
)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK. \n Successfully fetched the device types of groups.",
response = DeviceGroup.class,
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource has been modified the last time.\n" +
"Used by caches, or in conditional requests."),
}),
@ApiResponse(
code = 304,
message = "Not Modified. \n Empty body because the client has already the latest version of " +
"the requested resource."),
@ApiResponse(
code = 404,
message = "Error occurred",
response = ErrorResponse.class),
@ApiResponse(
code = 406,
message = "Not Acceptable.\n The requested media type is not supported."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Server error occurred while fetching the group details.",
response = ErrorResponse.class)
})
Response getGroupHasDeviceTypes(
@ApiParam(
name = "identifiers",
value = "GET list of identifiers.",
required = true)
List<String> identifiers);
}

@ -65,6 +65,7 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.sql.Timestamp;
import java.util.List;
@SwaggerDefinition(
@ -110,7 +111,14 @@ import java.util.List;
key = "perm:devices:permanent-delete",
roles = {"Internal/devicemgt-admin"},
permissions = {"/device-mgt/admin/devices/permanent-delete"}
)
),
@Scope(
name = "Get Usage of Devices",
description = "Get Usage of Devices",
key = "perm:admin:usage:view",
roles = {"Internal/devicemgt-admin"},
permissions = {"/device-mgt/admin/devices/usage/view"}
),
}
)
public interface DeviceManagementAdminService {
@ -423,4 +431,78 @@ public interface DeviceManagementAdminService {
List<String> actions
);
@GET
@Path("/billing")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "Getting Cost details of devices in a tenant",
notes = "Provides individual cost and total cost of all devices per tenant.",
tags = "Device Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:admin:usage:view")
})
}
)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK. \n Successfully fetched the list of devices.",
response = DeviceList.class,
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body"),
@ResponseHeader(
name = "Content-Disposition",
description = "The content disposition of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests."),
}),
@ApiResponse(
code = 304,
message = "Not Modified. \n Empty body because the client already has the latest version of " +
"the requested resource.\n"),
@ApiResponse(
code = 400,
message = "The incoming request has more than one selection criteria defined via the query parameters.",
response = ErrorResponse.class),
@ApiResponse(
code = 404,
message = "The search criteria did not match any device registered with the server.",
response = ErrorResponse.class),
@ApiResponse(
code = 406,
message = "Not Acceptable.\n The requested media type is not supported."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Server error occurred while fetching the device list.",
response = ErrorResponse.class)
})
Response getBilling(
@ApiParam(
name = "tenantDomain",
value = "The tenant domain.",
required = false)
@QueryParam("tenantDomain")
String tenantDomain,
@ApiParam(
name = "startDate",
value = "The start date.",
required = false)
@QueryParam("startDate")
Timestamp startDate,
@ApiParam(
name = "endDate",
value = "The end date.",
required = false)
@QueryParam("endDate")
Timestamp endDate);
}

@ -1,11 +1,19 @@
package org.wso2.carbon.device.mgt.jaxrs.service.impl;
import io.entgra.device.mgt.core.apimgt.analytics.extension.AnalyticsArtifactsDeployer;
import io.entgra.device.mgt.core.apimgt.analytics.extension.dto.*;
import io.entgra.device.mgt.core.apimgt.analytics.extension.exception.EventReceiverDeployerException;
import io.entgra.device.mgt.core.apimgt.analytics.extension.exception.EventPublisherDeployerException;
import io.entgra.device.mgt.core.apimgt.analytics.extension.exception.EventStreamDeployerException;
import org.apache.axis2.AxisFault;
import org.apache.axis2.client.Stub;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.databridge.commons.StreamDefinition;
import org.wso2.carbon.databridge.commons.exception.MalformedStreamDefinitionException;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.Attribute;
import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.AttributeType;
@ -15,26 +23,40 @@ import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.TransportType;
import org.wso2.carbon.device.mgt.jaxrs.service.api.DeviceEventManagementService;
import org.wso2.carbon.device.mgt.jaxrs.util.Constants;
import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterConfiguration;
import org.wso2.carbon.event.publisher.core.EventPublisherService;
import org.wso2.carbon.event.publisher.core.config.EventPublisherConfiguration;
import org.wso2.carbon.event.publisher.core.config.mapping.JSONOutputMapping;
import org.wso2.carbon.event.publisher.core.config.mapping.MapOutputMapping;
import org.wso2.carbon.event.publisher.core.exception.EventPublisherConfigurationException;
import org.wso2.carbon.event.publisher.stub.EventPublisherAdminServiceCallbackHandler;
import org.wso2.carbon.event.publisher.stub.EventPublisherAdminServiceStub;
import org.wso2.carbon.event.receiver.core.EventReceiverService;
import org.wso2.carbon.event.receiver.core.config.EventReceiverConfiguration;
import org.wso2.carbon.event.receiver.core.config.mapping.JSONInputMapping;
import org.wso2.carbon.event.receiver.core.config.mapping.WSO2EventInputMapping;
import org.wso2.carbon.event.receiver.core.exception.EventReceiverConfigurationException;
import org.wso2.carbon.event.receiver.stub.EventReceiverAdminServiceCallbackHandler;
import org.wso2.carbon.event.receiver.stub.EventReceiverAdminServiceStub;
import org.wso2.carbon.event.receiver.stub.types.BasicInputAdapterPropertyDto;
import org.wso2.carbon.event.receiver.stub.types.EventReceiverConfigurationDto;
import org.wso2.carbon.event.stream.core.EventStreamService;
import org.wso2.carbon.event.stream.core.exception.EventStreamConfigurationException;
import org.wso2.carbon.event.stream.stub.EventStreamAdminServiceStub;
import org.wso2.carbon.event.stream.stub.types.EventStreamAttributeDto;
import org.wso2.carbon.event.stream.stub.types.EventStreamDefinitionDto;
import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
import org.wso2.carbon.user.api.UserStoreException;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.validation.Valid;
import javax.ws.rs.*;
import javax.ws.rs.core.Response;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
@ -173,65 +195,129 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe
/**
* Deploy Event Stream, Receiver, Publisher and Store Configuration.
*/
// @POST
// @Path("/{type}")
// @Override
// public Response deployDeviceTypeEventDefinition(@PathParam("type") String deviceType,
// @QueryParam("skipPersist") boolean skipPersist,
// @QueryParam("isSharedWithAllTenants") boolean isSharedWithAllTenants,
// @Valid DeviceTypeEvent deviceTypeEvent) {
// TransportType transportType = deviceTypeEvent.getTransportType();
// EventAttributeList eventAttributes = deviceTypeEvent.getEventAttributeList();
// String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
// try {
// if (eventAttributes == null || eventAttributes.getList() == null || eventAttributes.getList().size() == 0 ||
// deviceType == null || transportType == null ||
// !DeviceMgtAPIUtils.getDeviceManagementService().getAvailableDeviceTypes().contains(deviceType)) {
// String errorMessage = "Invalid Payload";
// log.error(errorMessage);
// return Response.status(Response.Status.BAD_REQUEST).build();
// }
// String streamName = DeviceMgtAPIUtils.getStreamDefinition(deviceType, tenantDomain);
// String streamNameWithVersion = streamName + ":" + Constants.DEFAULT_STREAM_VERSION;
// publishStreamDefinitons(streamName, Constants.DEFAULT_STREAM_VERSION, deviceType, eventAttributes);
// publishEventReceivers(streamNameWithVersion, transportType, tenantDomain, isSharedWithAllTenants, deviceType);
// if (!skipPersist) {
// publishEventStore(streamName, Constants.DEFAULT_STREAM_VERSION, eventAttributes);
// }
// publishWebsocketPublisherDefinition(streamNameWithVersion, deviceType);
// try {
// PrivilegedCarbonContext.startTenantFlow();
// PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
// MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, true);
// if (!MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
// publishStreamDefinitons(streamName, Constants.DEFAULT_STREAM_VERSION, deviceType, eventAttributes);
// publishEventReceivers(streamNameWithVersion, transportType, tenantDomain, isSharedWithAllTenants, deviceType);
// }
// } finally {
// PrivilegedCarbonContext.endTenantFlow();
// }
// return Response.ok().build();
// } catch (AxisFault e) {
// log.error("Failed to create 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 (DeviceManagementException e) {
// log.error("Failed to access device management service, tenantDomain: " + tenantDomain, e);
// return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
// } catch (EventStreamPersistenceAdminServiceEventStreamPersistenceAdminServiceExceptionException e) {
// log.error("Failed to create event store for, tenantDomain: " + tenantDomain + " deviceType" + deviceType,
// e);
// return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
// }
// }
@POST
@Path("/{type}")
@Override
public Response deployDeviceTypeEventDefinition(@PathParam("type") String deviceType,
@QueryParam("skipPersist") boolean skipPersist,
@QueryParam("isSharedWithAllTenants") boolean isSharedWithAllTenants,
@Valid List<DeviceTypeEvent> deviceTypeEvents) {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
try {
for (DeviceTypeEvent deviceTypeEvent : deviceTypeEvents) {
TransportType transportType = deviceTypeEvent.getTransportType();
EventAttributeList eventAttributes = deviceTypeEvent.getEventAttributeList();
String eventName = deviceTypeEvent.getEventName();
if (eventAttributes == null || eventAttributes.getList() == null || eventAttributes.getList().size() == 0 ||
deviceType == null || transportType == null ||
!DeviceMgtAPIUtils.getDeviceManagementService().getAvailableDeviceTypes().contains(deviceType)) {
String errorMessage = "Invalid Payload";
log.error(errorMessage);
return Response.status(Response.Status.BAD_REQUEST).build();
}
// event stream
String streamName = DeviceMgtAPIUtils.getStreamDefinition(deviceType, tenantDomain, eventName);
AnalyticsArtifactsDeployer artifactsDeployer = new AnalyticsArtifactsDeployer();
List<Property> props = new ArrayList<>();
for (Attribute attribute : eventAttributes.getList()) {
props.add(new Property(attribute.getName(), attribute.getType().name()));
}
EventStreamData eventStreamData = new EventStreamData();
eventStreamData.setName(streamName);
eventStreamData.setVersion(Constants.DEFAULT_STREAM_VERSION);
eventStreamData.setMetaData(new MetaData(DEFAULT_DEVICE_ID_ATTRIBUTE, "STRING"));
eventStreamData.setPayloadData(props);
artifactsDeployer.deployEventStream(eventStreamData, tenantId);
// event receiver
String receiverName = getReceiverName(deviceType, tenantDomain, transportType, eventName);
EventReceiverData receiverData = new EventReceiverData();
receiverData.setName(receiverName);
receiverData.setStreamName(streamName);
receiverData.setStreamVersion(Constants.DEFAULT_STREAM_VERSION);
List<Property> propertyList = new ArrayList<>();
if (transportType == TransportType.MQTT) {
receiverData.setEventAdapterType(OAUTH_MQTT_ADAPTER_TYPE);
propertyList.add(new Property(MQTT_CONTENT_TRANSFORMER_TYPE, MQTT_CONTENT_TRANSFORMER));
propertyList.add(new Property(MQTT_CONTENT_VALIDATOR_TYPE, MQTT_CONTENT_VALIDATOR));
String topic;
if (!StringUtils.isEmpty(deviceTypeEvent.getEventTopicStructure())) {
if (isSharedWithAllTenants) {
topic = deviceTypeEvent.getEventTopicStructure().replace("${deviceId}", "+")
.replace("${deviceType}", deviceType)
.replace("${tenantDomain}", "+");
} else {
topic = deviceTypeEvent.getEventTopicStructure().replace("${deviceId}", "+")
.replace("${deviceType}", deviceType)
.replace("${tenantDomain}", tenantDomain);
}
} else {
if (isSharedWithAllTenants) {
topic = "+/" + deviceType + "/+/events";
} else {
topic = tenantDomain + "/" + deviceType + "/+/events";
}
}
propertyList.add(new Property("topic", topic));
receiverData.setCustomMappingType("json");
} else {
receiverData.setEventAdapterType(THRIFT_ADAPTER_TYPE);
propertyList.add(new Property("events.duplicated.in.cluster", "false"));
receiverData.setCustomMappingType("wso2event");
}
receiverData.setPropertyList(propertyList);
artifactsDeployer.deployEventReceiver(receiverData, tenantId);
if (!skipPersist) {
// rdbms event publisher
String rdbmsPublisherName = getPublisherName(deviceType, tenantDomain, eventName) + "_rdbms_publisher";
EventPublisherData eventPublisherData = new EventPublisherData();
eventPublisherData.setName(rdbmsPublisherName);
eventPublisherData.setStreamName(streamName);
eventPublisherData.setStreamVersion(Constants.DEFAULT_STREAM_VERSION);
eventPublisherData.setEventAdaptorType("rdbms");
eventPublisherData.setCustomMappingType("map");
List<Property> publisherProps = new ArrayList<>();
publisherProps.add(new Property("datasource.name", "EVENT_DB"));
publisherProps.add(new Property("table.name", "table_" + rdbmsPublisherName.replace(".", "")));
publisherProps.add(new Property("execution.mode", "insert"));
eventPublisherData.setPropertyList(publisherProps);
artifactsDeployer.deployEventPublisher(eventPublisherData, tenantId);
}
// web socket event publisher
String wsPublisherName = getPublisherName(deviceType, tenantDomain, eventName) + "_ws_publisher";
EventPublisherData wsEventPublisherData = new EventPublisherData();
wsEventPublisherData.setName(wsPublisherName);
wsEventPublisherData.setStreamName(streamName);
wsEventPublisherData.setStreamVersion(Constants.DEFAULT_STREAM_VERSION);
wsEventPublisherData.setEventAdaptorType("websocket-local");
wsEventPublisherData.setCustomMappingType("json");
artifactsDeployer.deployEventPublisher(wsEventPublisherData, tenantId);
}
return Response.ok().build();
} catch (DeviceManagementException e) {
log.error("Failed to access device management service, tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (EventStreamDeployerException e) {
log.error("Failed while deploying event stream definition, tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (EventPublisherDeployerException e) {
log.error("Failed while deploying event publisher, tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (EventReceiverDeployerException e) {
log.error("Failed while deploying event receiver, tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
}
/**
* Delete device type specific artifacts from DAS.
@ -498,160 +584,174 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe
// return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
// }
// }
private void publishEventReceivers(String streamNameWithVersion, TransportType transportType
, String requestedTenantDomain, boolean isSharedWithAllTenants, String deviceType)
throws RemoteException, UserStoreException, JWTClientException {
EventReceiverAdminServiceStub receiverAdminServiceStub = DeviceMgtAPIUtils.getEventReceiverAdminServiceStub();
private void publishEventReceivers(String streamName, String version, TransportType transportType
, String requestedTenantDomain, boolean isSharedWithAllTenants, String deviceType,
String eventTopicStructure, String receiverName) throws EventReceiverConfigurationException {
EventReceiverService eventReceiverService = DeviceMgtAPIUtils.getEventReceiverService();
try {
TransportType transportTypeToBeRemoved = TransportType.HTTP;
if (transportType == TransportType.HTTP) {
transportTypeToBeRemoved = TransportType.MQTT;
}
String eventRecieverNameTobeRemoved = getReceiverName(deviceType, requestedTenantDomain, transportTypeToBeRemoved);
EventReceiverConfigurationDto eventReceiverConfigurationDto = receiverAdminServiceStub
.getActiveEventReceiverConfiguration(eventRecieverNameTobeRemoved);
if (eventReceiverConfigurationDto != null) {
EventReceiverAdminServiceCallbackHandler eventReceiverAdminServiceCallbackHandler =
new EventReceiverAdminServiceCallbackHandler() {
};
receiverAdminServiceStub.startundeployActiveEventReceiverConfiguration(eventRecieverNameTobeRemoved
, eventReceiverAdminServiceCallbackHandler);
// TransportType transportTypeToBeRemoved = TransportType.HTTP;
// if (transportType == TransportType.HTTP) {
// transportTypeToBeRemoved = TransportType.MQTT;
// }
// String eventRecieverNameTobeRemoved = getReceiverName(deviceType, requestedTenantDomain, transportTypeToBeRemoved);
EventReceiverConfiguration eventReceiverConfiguration =
eventReceiverService.getActiveEventReceiverConfiguration(receiverName);
if (eventReceiverConfiguration != null) {
eventReceiverService.undeployActiveEventReceiverConfiguration(receiverName);
}
String adapterType = OAUTH_MQTT_ADAPTER_TYPE;
BasicInputAdapterPropertyDto basicInputAdapterPropertyDtos[];
InputEventAdapterConfiguration inputEventAdapterConfiguration = new InputEventAdapterConfiguration();
Map<String, String> propertyMap = new HashMap<>();
if (transportType == TransportType.MQTT) {
basicInputAdapterPropertyDtos = new BasicInputAdapterPropertyDto[3];
inputEventAdapterConfiguration.setType(OAUTH_MQTT_ADAPTER_TYPE);
String topic;
if (isSharedWithAllTenants) {
topic = "+/" + deviceType + "/+/events";
if (!StringUtils.isEmpty(eventTopicStructure)) {
if (isSharedWithAllTenants) {
topic = eventTopicStructure.replace("${deviceId}", "+")
.replace("${deviceType}", deviceType)
.replace("${tenantDomain}", "+");
} else {
topic = eventTopicStructure.replace("${deviceId}", "+")
.replace("${deviceType}", deviceType)
.replace("${tenantDomain}", requestedTenantDomain);
}
} else {
topic = requestedTenantDomain + "/" + deviceType + "/+/events";
if (isSharedWithAllTenants) {
topic = "+/" + deviceType + "/+/events";
} else {
topic = requestedTenantDomain + "/" + deviceType + "/+/events";
}
}
basicInputAdapterPropertyDtos[0] = getBasicInputAdapterPropertyDto("topic", topic);
basicInputAdapterPropertyDtos[1] = getBasicInputAdapterPropertyDto(MQTT_CONTENT_TRANSFORMER_TYPE
, MQTT_CONTENT_TRANSFORMER);
basicInputAdapterPropertyDtos[2] = getBasicInputAdapterPropertyDto(MQTT_CONTENT_VALIDATOR_TYPE
, MQTT_CONTENT_VALIDATOR);
propertyMap.put("topic", topic);
propertyMap.put(MQTT_CONTENT_TRANSFORMER_TYPE, MQTT_CONTENT_TRANSFORMER);
propertyMap.put(MQTT_CONTENT_VALIDATOR_TYPE, MQTT_CONTENT_VALIDATOR);
} else {
adapterType = THRIFT_ADAPTER_TYPE;
basicInputAdapterPropertyDtos = new BasicInputAdapterPropertyDto[1];
basicInputAdapterPropertyDtos[0] = getBasicInputAdapterPropertyDto("events.duplicated.in.cluster", "false");
inputEventAdapterConfiguration.setType(THRIFT_ADAPTER_TYPE);
propertyMap.put("events.duplicated.in.cluster", "false");
}
String eventRecieverName = getReceiverName(deviceType, requestedTenantDomain, transportType);
if (receiverAdminServiceStub.getActiveEventReceiverConfiguration(eventRecieverName) == null) {
inputEventAdapterConfiguration.setProperties(propertyMap);
if (eventReceiverService.getActiveEventReceiverConfiguration(receiverName) == null) {
EventReceiverConfiguration configuration = new EventReceiverConfiguration();
configuration.setEventReceiverName(receiverName);
configuration.setToStreamName(streamName);
configuration.setToStreamVersion(version);
configuration.setFromAdapterConfiguration(inputEventAdapterConfiguration);
if (transportType == TransportType.MQTT) {
receiverAdminServiceStub.deployJsonEventReceiverConfiguration(eventRecieverName, streamNameWithVersion
, adapterType, null, basicInputAdapterPropertyDtos, false);
JSONInputMapping jsonInputMapping = new JSONInputMapping();
jsonInputMapping.setCustomMappingEnabled(false);
configuration.setInputMapping(jsonInputMapping);
eventReceiverService.deployEventReceiverConfiguration(configuration);
} else {
receiverAdminServiceStub.deployWso2EventReceiverConfiguration(eventRecieverName, streamNameWithVersion
, adapterType, null, null, null, basicInputAdapterPropertyDtos, false, null);
WSO2EventInputMapping wso2EventInputMapping = new WSO2EventInputMapping();
wso2EventInputMapping.setCustomMappingEnabled(false);
configuration.setInputMapping(wso2EventInputMapping);
eventReceiverService.deployEventReceiverConfiguration(configuration);
}
}
} finally {
cleanup(receiverAdminServiceStub);
} catch (EventReceiverConfigurationException e) {
log.error("Error while publishing event receiver" , e);
throw new EventReceiverConfigurationException(e);
}
}
private void publishStreamDefinitons(String streamName, String version, String deviceType
, EventAttributeList eventAttributes)
throws RemoteException, UserStoreException, JWTClientException {
EventStreamAdminServiceStub eventStreamAdminServiceStub = DeviceMgtAPIUtils.getEventStreamAdminServiceStub();
private void publishStreamDefinitons(String streamName, String version, EventAttributeList eventAttributes)
throws MalformedStreamDefinitionException, EventStreamConfigurationException {
EventStreamService eventStreamService = DeviceMgtAPIUtils.getEventStreamService();
try {
EventStreamDefinitionDto eventStreamDefinitionDto = new EventStreamDefinitionDto();
eventStreamDefinitionDto.setName(streamName);
eventStreamDefinitionDto.setVersion(version);
EventStreamAttributeDto eventStreamAttributeDtos[] =
new EventStreamAttributeDto[eventAttributes.getList().size()];
EventStreamAttributeDto metaStreamAttributeDtos[] =
new EventStreamAttributeDto[1];
int i = 0;
StreamDefinition streamDefinition = new StreamDefinition(streamName, version);
List<org.wso2.carbon.databridge.commons.Attribute> payloadDataAttributes = new ArrayList<>();
for (Attribute attribute : eventAttributes.getList()) {
EventStreamAttributeDto eventStreamAttributeDto = new EventStreamAttributeDto();
eventStreamAttributeDto.setAttributeName(attribute.getName());
eventStreamAttributeDto.setAttributeType(attribute.getType().toString());
eventStreamAttributeDtos[i] = eventStreamAttributeDto;
i++;
payloadDataAttributes.add(new org.wso2.carbon.databridge.commons.Attribute(attribute.getName(),
org.wso2.carbon.databridge.commons.AttributeType.valueOf(attribute.getType().name())));
}
streamDefinition.setPayloadData(payloadDataAttributes);
List<org.wso2.carbon.databridge.commons.Attribute> metaDataAttributes = new ArrayList<>();
metaDataAttributes.add(new org.wso2.carbon.databridge.commons.Attribute(DEFAULT_DEVICE_ID_ATTRIBUTE,
org.wso2.carbon.databridge.commons.AttributeType.STRING));
streamDefinition.setMetaData(metaDataAttributes);
EventStreamAttributeDto eventStreamAttributeDto = new EventStreamAttributeDto();
eventStreamAttributeDto.setAttributeName(DEFAULT_DEVICE_ID_ATTRIBUTE);
eventStreamAttributeDto.setAttributeType(AttributeType.STRING.toString());
metaStreamAttributeDtos[0] = eventStreamAttributeDto;
eventStreamDefinitionDto.setPayloadData(eventStreamAttributeDtos);
eventStreamDefinitionDto.setMetaData(metaStreamAttributeDtos);
String streamId = streamName + ":" + version;
if (eventStreamAdminServiceStub.getStreamDefinitionDto(streamId) != null) {
eventStreamAdminServiceStub.editEventStreamDefinitionAsDto(eventStreamDefinitionDto, streamId);
if (eventStreamService.getStreamDefinition(streamDefinition.getStreamId()) != null) {
eventStreamService.removeEventStreamDefinition(streamName, version);
eventStreamService.addEventStreamDefinition(streamDefinition);
} else {
eventStreamAdminServiceStub.addEventStreamDefinitionAsDto(eventStreamDefinitionDto);
eventStreamService.addEventStreamDefinition(streamDefinition);
}
} finally {
cleanup(eventStreamAdminServiceStub);
} catch (MalformedStreamDefinitionException e) {
log.error("Error while initializing stream definition " , e);
throw new MalformedStreamDefinitionException(e);
} catch (EventStreamConfigurationException e) {
log.error("Error while configuring stream definition " , e);
throw new EventStreamConfigurationException(e);
}
}
/*
// private void publishEventStore(String streamName, String version, EventAttributeList eventAttributes)
// throws RemoteException, UserStoreException, JWTClientException,
// EventStreamPersistenceAdminServiceEventStreamPersistenceAdminServiceExceptionException {
// EventStreamPersistenceAdminServiceStub eventStreamPersistenceAdminServiceStub =
// DeviceMgtAPIUtils.getEventStreamPersistenceAdminServiceStub();
// try {
// AnalyticsTable analyticsTable = new AnalyticsTable();
// analyticsTable.setRecordStoreName(DEFAULT_EVENT_STORE_NAME);
// analyticsTable.setStreamVersion(version);
// analyticsTable.setTableName(streamName);
// analyticsTable.setMergeSchema(false);
// analyticsTable.setPersist(true);
// AnalyticsTableRecord analyticsTableRecords[] = new AnalyticsTableRecord[eventAttributes.getList().size() + 1];
// int i = 0;
// for (Attribute attribute : eventAttributes.getList()) {
// AnalyticsTableRecord analyticsTableRecord = new AnalyticsTableRecord();
// analyticsTableRecord.setColumnName(attribute.getName());
// analyticsTableRecord.setColumnType(attribute.getType().toString().toUpperCase());
// analyticsTableRecord.setFacet(false);
// analyticsTableRecord.setIndexed(false);
// analyticsTableRecord.setPersist(true);
// analyticsTableRecord.setPrimaryKey(false);
// analyticsTableRecord.setScoreParam(false);
// analyticsTableRecords[i] = analyticsTableRecord;
// i++;
// }
// AnalyticsTableRecord analyticsTableRecord = new AnalyticsTableRecord();
// analyticsTableRecord.setColumnName(DEFAULT_META_DEVICE_ID_ATTRIBUTE);
// analyticsTableRecord.setColumnType(AttributeType.STRING.toString().toUpperCase());
// analyticsTableRecord.setFacet(false);
// analyticsTableRecord.setIndexed(true);
// analyticsTableRecord.setPersist(true);
// analyticsTableRecord.setPrimaryKey(false);
// analyticsTableRecord.setScoreParam(false);
// analyticsTableRecords[i] = analyticsTableRecord;
// analyticsTable.setAnalyticsTableRecords(analyticsTableRecords);
// eventStreamPersistenceAdminServiceStub.addAnalyticsTable(analyticsTable);
// } finally {
// cleanup(eventStreamPersistenceAdminServiceStub);
// }
// }
*/
private void publishEventStore(String streamName, String version, String publisherName)
throws EventPublisherConfigurationException {
EventPublisherService eventPublisherService = DeviceMgtAPIUtils.getEventPublisherService();
private void publishWebsocketPublisherDefinition(String streamNameWithVersion, String deviceType)
throws RemoteException, UserStoreException, JWTClientException {
EventPublisherAdminServiceStub eventPublisherAdminServiceStub = DeviceMgtAPIUtils
.getEventPublisherAdminServiceStub();
try {
String eventPublisherName = deviceType.trim().replace(" ", "_") + "_websocket_publisher";
if (eventPublisherAdminServiceStub.getActiveEventPublisherConfiguration(eventPublisherName) == null) {
eventPublisherAdminServiceStub.deployJsonEventPublisherConfiguration(eventPublisherName
, streamNameWithVersion, DEFAULT_WEBSOCKET_PUBLISHER_ADAPTER_TYPE, null, null
, null, false);
if (eventPublisherService.getActiveEventPublisherConfiguration(publisherName) == null) {
EventPublisherConfiguration configuration = new EventPublisherConfiguration();
configuration.setEventPublisherName(publisherName);
configuration.setFromStreamName(streamName);
configuration.setFromStreamVersion(version);
MapOutputMapping mapOutputMapping = new MapOutputMapping();
mapOutputMapping.setCustomMappingEnabled(false);
configuration.setOutputMapping(mapOutputMapping);
OutputEventAdapterConfiguration outputEventAdapterConfiguration = new OutputEventAdapterConfiguration();
outputEventAdapterConfiguration.setType("rdbms");
Map<String, String> staticProperties = new HashMap<>();
staticProperties.put("datasource.name", "EVENT_DB");
staticProperties.put("execution.mode", "insert");
staticProperties.put("table.name", "table_" + publisherName.replace(".", ""));
outputEventAdapterConfiguration.setStaticProperties(staticProperties);
configuration.setProcessEnabled(true);
configuration.setToAdapterConfiguration(outputEventAdapterConfiguration);
eventPublisherService.deployEventPublisherConfiguration(configuration);
}
} finally {
cleanup(eventPublisherAdminServiceStub);
} catch (EventPublisherConfigurationException e) {
log.error("Error while publishing to rdbms store" , e);
throw new EventPublisherConfigurationException(e);
}
}
private void publishWebsocketPublisherDefinition(String streamName, String version, String publisherName)
throws EventPublisherConfigurationException {
EventPublisherService eventPublisherService = DeviceMgtAPIUtils.getEventPublisherService();
try {
if (eventPublisherService.getActiveEventPublisherConfiguration(publisherName) == null) {
EventPublisherConfiguration configuration = new EventPublisherConfiguration();
configuration.setEventPublisherName(publisherName);
configuration.setFromStreamName(streamName);
configuration.setFromStreamVersion(version);
JSONOutputMapping jsonOutputMapping = new JSONOutputMapping();
jsonOutputMapping.setCustomMappingEnabled(false);
configuration.setOutputMapping(jsonOutputMapping);
OutputEventAdapterConfiguration outputEventAdapterConfiguration = new OutputEventAdapterConfiguration();
outputEventAdapterConfiguration.setType("websocket-local");
configuration.setToAdapterConfiguration(outputEventAdapterConfiguration);
eventPublisherService.deployEventPublisherConfiguration(configuration);
}
} catch (EventPublisherConfigurationException e) {
log.error("Error while publishing to websocket-local" , e);
throw new EventPublisherConfigurationException(e);
}
}
private BasicInputAdapterPropertyDto getBasicInputAdapterPropertyDto(String key, String value) {
BasicInputAdapterPropertyDto basicInputAdapterPropertyDto = new BasicInputAdapterPropertyDto();
basicInputAdapterPropertyDto.setKey(key);
@ -667,6 +767,13 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe
return deviceType.replace(" ", "_").trim() + "-" + tenantDomain + "-" + transportType.toString() + "-receiver";
}
private String getReceiverName(String deviceType, String tenantDomain, TransportType transportType, String eventName) {
return eventName + "-" + getReceiverName(deviceType, tenantDomain, transportType);
}
private String getPublisherName(String tenantDomain, String deviceType, String eventName) {
return eventName + "_" + tenantDomain.replace(".", "_") + "_" + deviceType;
}
private void cleanup(Stub stub) {
if (stub != null) {

@ -37,33 +37,26 @@
package org.wso2.carbon.device.mgt.jaxrs.service.impl;
import com.google.gson.Gson;
import io.entgra.application.mgt.common.ApplicationInstallResponse;
import io.entgra.application.mgt.common.SubscriptionType;
import io.entgra.application.mgt.common.exception.SubscriptionManagementException;
import io.entgra.application.mgt.common.services.ApplicationManager;
import io.entgra.application.mgt.common.services.SubscriptionManager;
import io.entgra.application.mgt.core.util.HelperUtil;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONException;
import org.json.JSONObject;
import org.wso2.carbon.apimgt.keymgt.extension.DCRResponse;
import org.wso2.carbon.apimgt.keymgt.extension.TokenRequest;
import org.wso2.carbon.apimgt.keymgt.extension.TokenResponse;
import org.wso2.carbon.apimgt.keymgt.extension.exception.KeyMgtException;
import org.wso2.carbon.apimgt.keymgt.extension.service.KeyMgtService;
import org.wso2.carbon.apimgt.keymgt.extension.service.KeyMgtServiceImpl;
import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import io.entgra.application.mgt.common.ApplicationInstallResponse;
import io.entgra.application.mgt.common.SubscriptionType;
import io.entgra.application.mgt.common.exception.SubscriptionManagementException;
import io.entgra.application.mgt.common.services.SubscriptionManager;
import io.entgra.application.mgt.core.util.HelperUtil;
import org.wso2.carbon.device.mgt.common.DeviceFilters;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.OperationLogFilters;
import org.wso2.carbon.device.mgt.common.MDMAppConstants;
import org.wso2.carbon.device.mgt.common.DeviceManagementConstants;
import org.wso2.carbon.device.mgt.common.Feature;
import org.wso2.carbon.device.mgt.common.FeatureManager;
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.PaginationResult;
import org.wso2.carbon.device.mgt.common.TrackerDeviceInfo;
import org.wso2.carbon.device.mgt.common.TrackerPermissionInfo;
import org.wso2.carbon.device.mgt.common.*;
import org.wso2.carbon.device.mgt.common.app.mgt.Application;
import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManagementException;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException;
@ -72,12 +65,8 @@ import org.wso2.carbon.device.mgt.common.device.details.DeviceData;
import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistorySnapshotWrapper;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceTypeNotFoundException;
import org.wso2.carbon.device.mgt.common.exceptions.InvalidConfigurationException;
import org.wso2.carbon.device.mgt.common.exceptions.InvalidDeviceException;
import org.wso2.carbon.device.mgt.common.exceptions.BadRequestException;
import org.wso2.carbon.device.mgt.common.exceptions.UnAuthorizedException;
import org.wso2.carbon.device.mgt.common.exceptions.*;
import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
@ -91,6 +80,8 @@ import org.wso2.carbon.device.mgt.common.search.PropertyMap;
import org.wso2.carbon.device.mgt.common.search.SearchContext;
import org.wso2.carbon.device.mgt.common.type.mgt.DeviceStatus;
import org.wso2.carbon.device.mgt.core.app.mgt.ApplicationManagementProviderService;
import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager;
import org.wso2.carbon.device.mgt.core.config.DeviceManagementConfig;
import org.wso2.carbon.device.mgt.core.dao.TrackerManagementDAOException;
import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceDetailsMgtException;
import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceInformationManager;
@ -103,19 +94,10 @@ import org.wso2.carbon.device.mgt.core.search.mgt.SearchMgtException;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.core.service.GroupManagementProviderService;
import org.wso2.carbon.device.mgt.core.traccar.api.service.DeviceAPIClientService;
import org.wso2.carbon.device.mgt.core.traccar.api.service.impl.DeviceAPIClientServiceImpl;
import org.wso2.carbon.device.mgt.core.traccar.common.TraccarHandlerConstants;
import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil;
import org.wso2.carbon.device.mgt.core.util.HttpReportingUtil;
import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceList;
import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse;
import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceCompliance;
import org.wso2.carbon.device.mgt.jaxrs.beans.ApplicationList;
import org.wso2.carbon.device.mgt.jaxrs.beans.OperationStatusBean;
import org.wso2.carbon.device.mgt.jaxrs.beans.ComplianceDeviceList;
import org.wso2.carbon.device.mgt.jaxrs.beans.OperationRequest;
import org.wso2.carbon.device.mgt.jaxrs.beans.OperationList;
import org.wso2.carbon.device.mgt.jaxrs.beans.ApplicationUninstallation;
import org.wso2.carbon.device.mgt.jaxrs.beans.*;
import org.wso2.carbon.device.mgt.jaxrs.service.api.DeviceManagementService;
import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.InputValidationException;
import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil;
@ -128,29 +110,17 @@ import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerSer
import org.wso2.carbon.policy.mgt.common.PolicyManagementException;
import org.wso2.carbon.policy.mgt.core.PolicyManagerService;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import javax.validation.Valid;
import javax.ws.rs.Consumes;
import javax.validation.constraints.Size;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.*;
import javax.ws.rs.core.Response;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
@ -355,105 +325,6 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
}
}
@GET
@Override
@Path("/billing")
public Response getDevicesBilling(
@QueryParam("tenantDomain") String tenantDomain,
@QueryParam("startDate") Timestamp startDate,
@QueryParam("endDate") Timestamp endDate,
@QueryParam("generateBill") boolean generateBill,
@QueryParam("offset") int offset,
@DefaultValue("10")
@QueryParam("limit") int limit) {
try {
RequestValidationUtil.validatePaginationParameters(offset, limit);
DeviceManagementProviderService dms = DeviceMgtAPIUtils.getDeviceManagementService();
PaginationRequest request = new PaginationRequest(offset, limit);
PaginationResult result;
DeviceList devices = new DeviceList();
int tenantId = 0;
RealmService realmService = DeviceMgtAPIUtils.getRealmService();
if (!tenantDomain.isEmpty()) {
tenantId = realmService.getTenantManager().getTenantId(tenantDomain);
} else {
tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
}
try {
result = dms.getAllDevicesBillings(request, tenantId, tenantDomain, startDate, endDate, generateBill);
} catch (Exception exception) {
String msg = "Error occurred when trying to retrieve billing data";
log.error(msg, exception);
return Response.serverError().entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
}
int resultCount = result.getRecordsTotal();
if (resultCount == 0) {
Response.status(Response.Status.OK).entity(devices).build();
}
devices.setList((List<Device>) result.getData());
devices.setBilledDateIsValid(result.isBilledDateIsValid());
devices.setMessage(result.getMessage());
devices.setCount(result.getRecordsTotal());
devices.setTotalCost(result.getTotalCost());
return Response.status(Response.Status.OK).entity(devices).build();
} catch (Exception e) {
String msg = "Error occurred while retrieving billing data";
log.error(msg, e);
return Response.serverError().entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
}
}
@GET
@Override
@Path("/billing/file")
public Response exportBilling(
@QueryParam("tenantDomain") String tenantDomain,
@QueryParam("startDate") Timestamp startDate,
@QueryParam("endDate") Timestamp endDate,
@QueryParam("generateBill") boolean generateBill) {
try {
DeviceManagementProviderService dms = DeviceMgtAPIUtils.getDeviceManagementService();
PaginationResult result;
int tenantId = 0;
RealmService realmService = DeviceMgtAPIUtils.getRealmService();
DeviceList devices = new DeviceList();
if (!tenantDomain.isEmpty()) {
tenantId = realmService.getTenantManager().getTenantId(tenantDomain);
} else {
tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
}
try {
result = dms.createBillingFile(tenantId, tenantDomain, startDate, endDate, generateBill);
} catch (Exception exception) {
String msg = "Error occurred when trying to retrieve billing data without pagination";
log.error(msg, exception);
return null;
}
devices.setList((List<Device>) result.getData());
devices.setBilledDateIsValid(result.isBilledDateIsValid());
devices.setMessage(result.getMessage());
devices.setCount(result.getRecordsTotal());
devices.setTotalCost(result.getTotalCost());
return Response.status(Response.Status.OK).entity(devices).build();
} catch (Exception e) {
String msg = "Error occurred while retrieving billing data without pagination";
log.error(msg, e);
return null;
}
}
@GET
@Override
@Path("/user-devices")
@ -715,9 +586,13 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
Device persistedDevice = deviceManagementProviderService.getDevice(new DeviceIdentifier
(deviceId, deviceType), true);
persistedDevice.setName(device.getName());
boolean response = deviceManagementProviderService.modifyEnrollment(persistedDevice);
return Response.status(Response.Status.CREATED).entity(response).build();
System.out.println("This is rename device");
boolean responseOfmodifyEnrollment = deviceManagementProviderService.modifyEnrollment(persistedDevice);
boolean responseOfDeviceNameChanged = deviceManagementProviderService.sendDeviceNameChangedNotification(
persistedDevice);
boolean response = responseOfmodifyEnrollment && responseOfDeviceNameChanged;
return Response.status(Response.Status.CREATED).entity(response).build();
} catch (DeviceManagementException e) {
log.error("Error encountered while updating device of type : " + deviceType + " and " +
"ID : " + deviceId);
@ -911,6 +786,32 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
return Response.status(Response.Status.OK).entity(device).build();
}
@POST
@Path("/enrollment/guide")
@Override
public Response sendEnrollmentGuide(String enrolmentGuide) {
if (log.isDebugEnabled()) {
log.debug("Sending enrollment invitation mail to existing user.");
}
DeviceManagementConfig config = DeviceConfigurationManager.getInstance().getDeviceManagementConfig();
if (!config.getEnrollmentGuideConfiguration().isEnabled()) {
String msg = "Sending enrollment guide config is not enabled.";
log.error(msg);
return Response.status(Response.Status.FORBIDDEN).entity(msg).build();
}
DeviceManagementProviderService dms = DeviceMgtAPIUtils.getDeviceManagementService();
try {
dms.sendEnrolmentGuide(enrolmentGuide);
return Response.status(Response.Status.OK).entity("Invitation mails have been sent.").build();
} catch (DeviceManagementException e) {
String msg = "Error occurred sending mail to group in enrollment guide";
log.error(msg, e);
return Response.serverError().entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
}
}
@POST
@Path("/type/any/list")
@Override
@ -982,19 +883,118 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
}
return Response.status(Response.Status.OK).entity(deviceInfo).build();
}
@GET
@Path("/{type}/{id}/config")
@Override
public Response getDeviceConfiguration(
@PathParam("type") @Size(max = 45) String type,
@PathParam("id") @Size(max = 45) String id,
@HeaderParam("If-Modified-Since") String ifModifiedSince) {
DeviceConfig deviceConfig = new DeviceConfig();
deviceConfig.setDeviceId(id);
deviceConfig.setType(type);
// find token validity time
DeviceManagementProviderService deviceManagementProviderService =
DeviceMgtAPIUtils.getDeviceManagementService();
int validityTime = 3600;
// add scopes for event topics
List<String> mqttEventTopicStructure = new ArrayList<>();
try {
DeviceType deviceType = deviceManagementProviderService.getDeviceType(type);
if (deviceType != null) {
if (deviceType.getDeviceTypeMetaDefinition().isLongLivedToken()) {
validityTime = Integer.MAX_VALUE;
}
mqttEventTopicStructure = deviceType.getDeviceTypeMetaDefinition().getMqttEventTopicStructures();
} else {
String msg = "Device not found, device id : " + id + ", device type : " + type;
log.error(msg);
return Response.serverError().entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
}
} catch (DeviceManagementException e) {
String msg = "Error occurred while retrieving device, device id : " + id + ", device type : " + type;
log.error(msg, e);
return Response.serverError().entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
}
String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain();
String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
String applicationName = type.replace(" ", "").replace("_", "")
+ "_" + tenantDomain;
KeyMgtService keyMgtService = new KeyMgtServiceImpl();
try {
DCRResponse dcrResponse = keyMgtService.dynamicClientRegistration(applicationName, username,
"client_credentials", null, new String[] {"device_management"}, false, validityTime);
deviceConfig.setClientId(dcrResponse.getClientId());
deviceConfig.setClientSecret(dcrResponse.getClientSecret());
StringBuilder scopes = new StringBuilder("device_" + type.replace(" ", "")
.replace("_", "") + "_" + id);
for (String topic : mqttEventTopicStructure) {
if (topic.contains("${deviceId}")) {
topic = topic.replace("${deviceId}", id);
}
topic = topic.replace("/",":");
// scopes.append(" perm:topic:sub:".concat(topic));
scopes.append(" perm:topic:pub:".concat(topic));
}
// add scopes for retrieve operation topic /tenantDomain/deviceType/deviceId/operation/#
scopes.append(" perm:topic:sub:" + tenantDomain + ":" + type + ":" + id + ":operation");
// add scopes for update operation /tenantDomain/deviceType/deviceId/update/operation
scopes.append(" perm:topic:pub:" + tenantDomain + ":" + type + ":" + id + ":update:operation");
TokenRequest tokenRequest = new TokenRequest(dcrResponse.getClientId(), dcrResponse.getClientSecret(),
null, scopes.toString(), "client_credentials", null,
null, null, null, validityTime);
TokenResponse tokenResponse = keyMgtService.generateAccessToken(tokenRequest);
deviceConfig.setAccessToken(tokenResponse.getAccessToken());
deviceConfig.setRefreshToken(tokenResponse.getRefreshToken());
try {
deviceConfig.setPlatformConfiguration(deviceManagementProviderService.getConfiguration(type));
} catch (DeviceManagementException e) {
String msg = "Error occurred while reading platform configurations token, device id : " + id + ", device type : " + type;
log.error(msg, e);
return Response.serverError().entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
}
deviceConfig.setMqttGateway("tcp://" + System.getProperty("mqtt.broker.host") + ":" + System.getProperty("mqtt.broker.port"));
deviceConfig.setHttpGateway("http://" + System.getProperty("iot.gateway.host") + ":" + System.getProperty("iot.gateway.http.port"));
deviceConfig.setHttpsGateway("https://" + System.getProperty("iot.gateway.host") + ":" + System.getProperty("iot.gateway.https.port"));
} catch (KeyMgtException e) {
String msg = "Error occurred while creating oauth application, device id : " + id + ", device type : " + type;
log.error(msg, e);
return Response.serverError().entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
} catch (org.wso2.carbon.apimgt.keymgt.extension.exception.BadRequestException e) {
String msg = "Error occurred while generating token, device id : " + id + ", device type : " + type;
log.error(msg, e);
return Response.serverError().entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
}
return Response.status(Response.Status.OK).entity(deviceConfig).build();
}
@GET
@Path("/{type}/{id}/features")
@Path("/device-type/{type}/features")
@Override
public Response getFeaturesOfDevice(
@PathParam("type") @Size(max = 45) String type,
@PathParam("id") @Size(max = 45) String id,
@HeaderParam("If-Modified-Since") String ifModifiedSince) {
List<Feature> features = new ArrayList<>();
DeviceManagementProviderService dms;
try {
RequestValidationUtil.validateDeviceIdentifier(type, id);
dms = DeviceMgtAPIUtils.getDeviceManagementService();
FeatureManager fm;
try {
@ -1008,8 +1008,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
features = fm.getFeatures();
}
} catch (DeviceManagementException e) {
String msg = "Error occurred while retrieving the list of features of '" + type + "' device, which " +
"carries the id '" + id + "'";
String msg = "Error occurred while retrieving the list of features of '" + type + "'";
log.error(msg, e);
return Response.serverError().entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
@ -1360,7 +1359,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
* @return {@link Response} object
*/
@GET
@Path("/{type}/{id}/getstatushistory")
@Path("/{type}/{id}/status-history")
public Response getDeviceStatusHistory(@PathParam("type") @Size(max = 45) String type,
@PathParam("id") @Size(max = 45) String id) {
//TODO check authorization for this
@ -1392,7 +1391,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
* @return {@link Response} object
*/
@GET
@Path("/{type}/{id}/getenrolmentstatushistory")
@Path("/{type}/{id}/enrolment-status-history")
public Response getCurrentEnrolmentDeviceStatusHistory(@PathParam("type") @Size(max = 45) String type,
@PathParam("id") @Size(max = 45) String id) {
//TODO check authorization for this or current enrolment should be based on for the enrolment associated with the user

@ -48,6 +48,7 @@ import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceNotFoundException;
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup;
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroupConstants;
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceTypesOfGroups;
import org.wso2.carbon.device.mgt.common.group.mgt.GroupAlreadyExistException;
import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException;
import org.wso2.carbon.device.mgt.common.group.mgt.GroupNotExistException;
@ -66,6 +67,7 @@ import org.wso2.carbon.policy.mgt.common.PolicyManagementException;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
@ -429,4 +431,20 @@ public class GroupManagementServiceImpl implements GroupManagementService {
}
}
@POST
@Path("/device-types")
@Override
public Response getGroupHasDeviceTypes(List<String> identifiers) {
try {
DeviceTypesOfGroups deviceTypesOfGroups = DeviceMgtAPIUtils.getGroupManagementProviderService()
.getDeviceTypesOfGroups(identifiers);
return Response.status(Response.Status.OK).entity(deviceTypesOfGroups).build();
} catch (GroupManagementException e) {
String msg = "Only numbers can exists in a group ID or Invalid Group ID provided.";
log.error(msg, e);
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
}
}
}

@ -52,12 +52,15 @@ import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceNotFoundException;
import org.wso2.carbon.device.mgt.common.exceptions.InvalidDeviceException;
import org.wso2.carbon.device.mgt.common.exceptions.UserNotFoundException;
import org.wso2.carbon.device.mgt.common.PaginationResult;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceList;
import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse;
import org.wso2.carbon.device.mgt.jaxrs.service.api.admin.DeviceManagementAdminService;
import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil;
import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.core.service.RealmService;
import javax.validation.constraints.Size;
import javax.ws.rs.Consumes;
@ -71,6 +74,7 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.sql.Timestamp;
import java.util.List;
@Path("/admin/devices")
@ -147,7 +151,7 @@ public class DeviceManagementAdminServiceImpl implements DeviceManagementAdminSe
@Path("/device-owner")
public Response updateEnrollOwner(
@QueryParam("owner") String owner,
List<String> deviceIdentifiers){
List<String> deviceIdentifiers) {
try {
if (DeviceMgtAPIUtils.getDeviceManagementService().updateEnrollment(owner, true, deviceIdentifiers)) {
String msg = "Device owner is updated successfully.";
@ -190,8 +194,7 @@ public class DeviceManagementAdminServiceImpl implements DeviceManagementAdminSe
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
}
catch (InvalidDeviceException e) {
} catch (InvalidDeviceException e) {
String msg = "Found Invalid devices";
log.error(msg, e);
return Response.status(Response.Status.BAD_REQUEST).entity(
@ -205,7 +208,7 @@ public class DeviceManagementAdminServiceImpl implements DeviceManagementAdminSe
public Response triggerCorrectiveActions(
@PathParam("deviceId") String deviceIdentifier,
@PathParam("featureCode") String featureCode,
List<String> actions){
List<String> actions) {
DeviceManagementProviderService deviceManagementService = DeviceMgtAPIUtils.getDeviceManagementService();
PlatformConfigurationManagementService platformConfigurationManagementService = DeviceMgtAPIUtils
.getPlatformConfigurationManagementService();
@ -233,4 +236,51 @@ public class DeviceManagementAdminServiceImpl implements DeviceManagementAdminSe
}
return Response.status(Response.Status.OK).entity("Triggered action successfully").build();
}
@GET
@Override
@Path("/billing")
public Response getBilling(
@QueryParam("tenantDomain") String tenantDomain,
@QueryParam("startDate") Timestamp startDate,
@QueryParam("endDate") Timestamp endDate) {
try {
PaginationResult result;
int tenantId = 0;
RealmService realmService = DeviceMgtAPIUtils.getRealmService();
int tenantIdContext = CarbonContext.getThreadLocalCarbonContext().getTenantId();
if (!tenantDomain.isEmpty()) {
tenantId = realmService.getTenantManager().getTenantId(tenantDomain);
}
if (tenantIdContext != MultitenantConstants.SUPER_TENANT_ID && tenantIdContext != tenantId) {
String msg = "Current logged in user is not authorized to access billing details of other tenants";
log.error(msg);
return Response.status(Response.Status.UNAUTHORIZED).entity(msg).build();
} else {
DeviceList devices = new DeviceList();
DeviceManagementProviderService dms = DeviceMgtAPIUtils.getDeviceManagementService();
result = dms.createBillingFile(tenantId, tenantDomain, startDate, endDate);
devices.setList((List<Device>) result.getData());
devices.setDeviceCount(result.getTotalDeviceCount());
devices.setMessage(result.getMessage());
devices.setTotalCost(result.getTotalCost());
devices.setBillPeriod(startDate.toString() + " - " + endDate.toString());
return Response.status(Response.Status.OK).entity(devices).build();
}
} catch (BadRequestException e) {
String msg = "Bad request, can't proceed. Hence verify the request and re-try";
log.error(msg, e);
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
} catch (DeviceManagementException e) {
String msg = "Error occurred while retrieving billing data";
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
} catch (UserStoreException e) {
String msg = "Error occurred while processing tenant configuration.";
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
}
}
}

@ -59,6 +59,8 @@ public class Constants {
public static final String IOS = "ios";
public static final String WINDOWS = "windows";
public static final int MAX_REQUEST_FOR_PUBLISHER = 50;
public final class OperationStatus {
private OperationStatus () { throw new AssertionError(); }

@ -50,15 +50,12 @@ import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.CarbonConstants;
import org.wso2.carbon.analytics.api.AnalyticsDataAPI;
import org.wso2.carbon.analytics.stream.persistence.stub.EventStreamPersistenceAdminServiceStub;
import org.wso2.carbon.authenticator.stub.AuthenticationAdminStub;
import org.wso2.carbon.base.ServerConfiguration;
import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.core.util.Utils;
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.MonitoringOperation;
import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig;
import org.wso2.carbon.device.mgt.common.*;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService;
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry;
@ -95,8 +92,11 @@ import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.EventAttributeList;
import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.InputValidationException;
import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil;
import org.wso2.carbon.event.processor.stub.EventProcessorAdminServiceStub;
import org.wso2.carbon.event.publisher.core.EventPublisherService;
import org.wso2.carbon.event.publisher.stub.EventPublisherAdminServiceStub;
import org.wso2.carbon.event.receiver.core.EventReceiverService;
import org.wso2.carbon.event.receiver.stub.EventReceiverAdminServiceStub;
import org.wso2.carbon.event.stream.core.EventStreamService;
import org.wso2.carbon.event.stream.stub.EventStreamAdminServiceStub;
import org.wso2.carbon.identity.claim.metadata.mgt.dto.ClaimPropertyDTO;
import org.wso2.carbon.identity.jwt.client.extension.JWTClient;
@ -111,11 +111,7 @@ import org.wso2.carbon.policy.mgt.common.PolicyMonitoringTaskException;
import org.wso2.carbon.policy.mgt.core.PolicyManagerService;
import org.wso2.carbon.policy.mgt.core.task.TaskScheduleService;
import org.wso2.carbon.registry.core.service.RegistryService;
import org.wso2.carbon.user.api.AuthorizationManager;
import org.wso2.carbon.user.api.RealmConfiguration;
import org.wso2.carbon.user.api.UserRealm;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.api.UserStoreManager;
import org.wso2.carbon.user.api.*;
import org.wso2.carbon.user.core.jdbc.JDBCUserStoreManager;
import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.user.mgt.common.UIPermissionNode;
@ -128,11 +124,7 @@ import javax.net.ssl.TrustManagerFactory;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.*;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.LinkedList;
@ -172,7 +164,7 @@ public class DeviceMgtAPIUtils {
private static KeyStore trustStore;
private static char[] keyStorePassword;
// private static IntegrationClientService integrationClientService;
// private static IntegrationClientService integrationClientService;
private static MetadataManagementService metadataManagementService;
private static OTPManagementService otpManagementService;
@ -581,6 +573,36 @@ public class DeviceMgtAPIUtils {
return geoService;
}
public static EventStreamService getEventStreamService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
EventStreamService
eventStreamService = (EventStreamService) ctx.getOSGiService(EventStreamService.class, null);
if (eventStreamService == null) {
throw new IllegalStateException("Event Stream Service has not been initialized.");
}
return eventStreamService;
}
public static EventReceiverService getEventReceiverService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
EventReceiverService
eventReceiverService = (EventReceiverService) ctx.getOSGiService(EventReceiverService.class, null);
if (eventReceiverService == null) {
throw new IllegalStateException("Event Receiver Service has not been initialized.");
}
return eventReceiverService;
}
public static EventPublisherService getEventPublisherService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
EventPublisherService
eventPublisherService = (EventPublisherService) ctx.getOSGiService(EventPublisherService.class, null);
if (eventPublisherService == null) {
throw new IllegalStateException("Event Receiver Service has not been initialized.");
}
return eventPublisherService;
}
public static AnalyticsDataAPI getAnalyticsDataAPI() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
AnalyticsDataAPI analyticsDataAPI =
@ -642,10 +664,13 @@ public class DeviceMgtAPIUtils {
// return eventsPublisherService;
// }
public static String getStreamDefinition(String deviceType, String tenantDomain, String eventName) {
return getStreamDefinition(deviceType, tenantDomain) + "." + eventName;
}
public static String getStreamDefinition(String deviceType, String tenantDomain) {
return STREAM_DEFINITION_PREFIX + tenantDomain + "." + deviceType.replace(" ", ".");
}
public static EventStreamAdminServiceStub getEventStreamAdminServiceStub()
throws AxisFault, UserStoreException, JWTClientException {
EventStreamAdminServiceStub eventStreamAdminServiceStub = new EventStreamAdminServiceStub(

@ -0,0 +1,44 @@
package org.wso2.carbon.device.mgt.jaxrs.util;
import okhttp3.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.jaxrs.beans.BatchResponse;
import java.io.IOException;
import java.util.List;
public class RESTEndpointHandler {
private static final Log logger = LogFactory.getLog(RESTEndpointHandler.class);
// executes batch of requests to hosts indicate by requests
public BatchResponse batchExecute(List<Request> batch, int maxRequestsPerHost) {
BatchResponse batchResponse = new BatchResponse();
OkHttpClient client = new OkHttpClient();
client.dispatcher().setMaxRequestsPerHost(maxRequestsPerHost);
batch.forEach(request -> {
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
batchResponse.addRequest(call.request());
String msg = "Failed to execute request to "+call.request().url();
logger.error(msg, e);
}
@Override
public void onResponse(Call call, Response response) {
batchResponse.addResponse(response);
}
});
});
if(logger.isDebugEnabled()) {
logger.info(
"Batch execution is completed."+
"Executed : "+batch.size()+"\n"+
"Failed : "+batchResponse.getFailedRequests().size()+"\n"+
"Succeeded :"+batchResponse.getResponses().size()
);
}
return batchResponse;
}
}

@ -590,7 +590,7 @@ public class DeviceManagementServiceImplTest {
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService"))
.toReturn(this.deviceManagementProviderService);
Response response = this.deviceManagementService
.getFeaturesOfDevice(TEST_DEVICE_TYPE, UUID.randomUUID().toString(), null);
.getFeaturesOfDevice(TEST_DEVICE_TYPE, null);
Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());
}
@ -601,7 +601,7 @@ public class DeviceManagementServiceImplTest {
Mockito.when(this.deviceManagementProviderService.getFeatureManager(Mockito.anyString()))
.thenThrow(new DeviceTypeNotFoundException());
Response response = this.deviceManagementService
.getFeaturesOfDevice(TEST_DEVICE_TYPE, UUID.randomUUID().toString(), null);
.getFeaturesOfDevice(TEST_DEVICE_TYPE, null);
Assert.assertEquals(response.getStatus(), Response.Status.NOT_FOUND.getStatusCode());
Mockito.reset(this.deviceManagementProviderService);
}

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

@ -0,0 +1,123 @@
/*
* Copyright (c) 2022, 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.common;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.List;
@ApiModel(value = "BillingResponse", description = "This class carries all information related to a billing response.")
public class BillingResponse implements Serializable {
private static final long serialVersionUID = 1998101711L;
@ApiModelProperty(name = "year", value = "Year of the billed period",
required = false)
private String year;
@ApiModelProperty(name = "totalCostPerYear", value = "Bill for a period of year", required = false)
private double totalCostPerYear;
@ApiModelProperty(name = "devices", value = "Billed list of devices per year", required = false)
private List<Device> device;
@ApiModelProperty(name = "billPeriod", value = "Billed period", required = false)
private String billPeriod;
@ApiModelProperty(name = "startDate", value = "Start Date of period", required = false)
private String startDate;
@ApiModelProperty(name = "endDate", value = "End Date of period", required = false)
private String endDate;
@ApiModelProperty(name = "deviceCount", value = "Device count for a billing period",
required = false)
private int deviceCount;
public BillingResponse() {
}
public BillingResponse(String year, double totalCostPerYear, List<Device> device, String billPeriod, String startDate, String endDate, int deviceCount) {
this.year = year;
this.totalCostPerYear = totalCostPerYear;
this.device = device;
this.billPeriod = billPeriod;
this.startDate = startDate;
this.endDate = endDate;
this.deviceCount = deviceCount;
}
public String getStartDate() {
return startDate;
}
public void setStartDate(String startDate) {
this.startDate = startDate;
}
public String getEndDate() {
return endDate;
}
public void setEndDate(String endDate) {
this.endDate = endDate;
}
public double getTotalCostPerYear() {
return totalCostPerYear;
}
public void setTotalCostPerYear(double totalCostPerYear) {
this.totalCostPerYear = totalCostPerYear;
}
public String getYear() {
return year;
}
public void setYear(String year) {
this.year = year;
}
public List<Device> getDevice() {
return device;
}
public void setDevice(List<Device> device) {
this.device = device;
}
public String getBillPeriod() {
return billPeriod;
}
public void setBillPeriod(String billPeriod) {
this.billPeriod = billPeriod;
}
public int getDeviceCount() {
return deviceCount;
}
public void setDeviceCount(int deviceCount) {
this.deviceCount = deviceCount;
}
}

@ -44,6 +44,7 @@ public class PaginationRequest {
private Map<String, Object> property = new HashMap<>();
private List<String> statusList = new ArrayList<>();
private OperationLogFilters operationLogFilters = new OperationLogFilters();
private List<SortColumn> sortColumn = new ArrayList<>();
public OperationLogFilters getOperationLogFilters() {
return operationLogFilters;
}
@ -172,11 +173,38 @@ public class PaginationRequest {
this.filter = filter;
}
public void setSortColumn(List<SortColumn> sortColumn) { this.sortColumn = sortColumn; }
public List<SortColumn> getSortColumn() { return sortColumn; }
/**
* Convert SortColumns field parameter and splitting string into columnName and sortType
*
* @param sortColumns which is separated by a colon(:) and first will be the columnNane and the second will be type ASC or DESC,
* if there is no colon(:) detected, ASC will be default
* (Ex: sort=col1:ASC&sort=col2:DESC, sort=col1&sort=col2:DESC)
* @return sortColumnList as a list of sortColumn
*/
public void setSortColumns(List<String> sortColumns) {
List<SortColumn> sortColumnList = new ArrayList<>();
SortColumn sortColumn;
String[] sorting;
for (String sortBy: sortColumns) {
sortColumn = new SortColumn();
sorting = sortBy.split(":");
sortColumn.setName(sorting[0]);
sortColumn.setType(sorting.length >= 2 && (sorting[1].equalsIgnoreCase("desc"))
? SortColumn.types.DESC : SortColumn.types.ASC);
sortColumnList.add(sortColumn);
}
setSortColumn(sortColumnList);
}
@Override
public String toString() {
return "Device type '" + this.deviceType + "' Device Name '" + this.deviceName + "' row count: " + this.rowCount
+ " Owner role '" + this.ownerRole + "' owner pattern '" + this.ownerPattern + "' ownership "
+ this.ownership + "' Status '" + this.statusList + "' owner '" + this.owner + "' groupId: " + this.groupId
+ " start index: " + this.startIndex;
+ " start index: " + this.startIndex + ", SortColumns: " + this.sortColumn;
}
}

@ -47,18 +47,29 @@ public class PaginationResult implements Serializable {
@ApiModelProperty(name = "totalCost", value = "Total cost of all devices per tenant", required = false)
private double totalCost;
@ApiModelProperty(name = "billedDateIsValid", value = "Check if user entered date is valid", required = false)
private boolean billedDateIsValid;
@ApiModelProperty(name = "totalDeviceCount", value = "Total count of all devices per tenant", required = false)
private double totalDeviceCount;
@ApiModelProperty(name = "billPeriod", value = "Billed period", required = false)
private String billPeriod;
@ApiModelProperty(name = "message", value = "Send information text to the billing UI", required = false)
private String message;
public boolean isBilledDateIsValid() {
return billedDateIsValid;
public String getBillPeriod() {
return billPeriod;
}
public void setBillPeriod(String billPeriod) {
this.billPeriod = billPeriod;
}
public double getTotalDeviceCount() {
return totalDeviceCount;
}
public void setBilledDateIsValid(boolean billedDateIsValid) {
this.billedDateIsValid = billedDateIsValid;
public void setTotalDeviceCount(double totalDeviceCount) {
this.totalDeviceCount = totalDeviceCount;
}
public String getMessage() {

@ -0,0 +1,62 @@
/*
* Copyright (c) 2023, Entgra (pvt) Ltd. (https://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.common;
/**
* This class holds required parameters for a querying a sort by column in pagination.
*
*/
public class SortColumn {
String name;
SortColumn.types type;
public enum types {
ASC, DESC
}
/**
* ColumnName setter method
* @param name of the column
*/
public void setName(String name) { this.name = name; }
/**
* get the name of the column
* @return name
*/
public String getName() { return name; }
/**
* Column sort type
* @param type of sort as ASC or DESC
*/
public void setType(SortColumn.types type) { this.type = type; }
/**
* get column sort type
* @return type of sort
*/
public SortColumn.types getType() { return type; }
@Override
public String toString() {
return "Column Name - " + this.name + ", Type - " + this.type ;
}
}

@ -0,0 +1,60 @@
/*
* Copyright (c) 2022, Entgra (pvt) Ltd. (https://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.common.group.mgt;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
@ApiModel(value = "DeviceTypesOfGroups", description = "This class carries whether the groups has device type or not.")
public class DeviceTypesOfGroups implements Serializable {
private static final long serialVersionUID = 5562356373277828099L;
@ApiModelProperty(name = "hasAndroid", value = "groups has Android devices.")
private boolean hasAndroid;
@ApiModelProperty(name = "id", value = "groups has iOS devices.")
private boolean hasIos;
@ApiModelProperty(name = "hasAndroid", value = "groups has Windows devices.")
private boolean hasWindows;
public boolean isHasAndroid() {
return hasAndroid;
}
public void setHasAndroid(boolean hasAndroid) {
this.hasAndroid = hasAndroid;
}
public boolean isHasIos() {
return hasIos;
}
public void setHasIos(boolean hasIos) {
this.hasIos = hasIos;
}
public boolean isHasWindows() {
return hasWindows;
}
public void setHasWindows(boolean hasWindows) {
this.hasWindows = hasWindows;
}
}

@ -0,0 +1,49 @@
/* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.common.otp.mgt.wrapper;
public class DownloadURLDetails {
private String firstName;
private String URL;
private String email;
public String getURL() {
return URL;
}
public void setURL(String URL) {
this.URL = URL;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}

@ -22,6 +22,7 @@ import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.exceptions.OTPManagementException;
import org.wso2.carbon.device.mgt.common.invitation.mgt.DeviceEnrollmentInvitation;
import org.wso2.carbon.device.mgt.common.otp.mgt.dto.OneTimePinDTO;
import org.wso2.carbon.device.mgt.common.otp.mgt.wrapper.DownloadURLDetails;
import org.wso2.carbon.device.mgt.common.otp.mgt.wrapper.OTPWrapper;
import java.util.Map;
@ -62,4 +63,13 @@ public interface OTPManagementService {
*/
void sendDeviceEnrollmentInvitationMail(DeviceEnrollmentInvitation deviceEnrollmentInvitation)
throws OTPManagementException;
}
/**
* Send an e-mail to the requesting e-mail address with a product download URL
* @param downloadURLDetails Contains the details to send product download e-mail
* @throws OTPManagementException if request payload doesn't contains required details to send the product
* download mail.
*/
void shareProductDownloadUrl(DownloadURLDetails downloadURLDetails) throws OTPManagementException;
}

@ -5,6 +5,7 @@ import org.wso2.carbon.device.mgt.common.InitialOperationConfig;
import org.wso2.carbon.device.mgt.common.license.mgt.License;
import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationConfig;
import java.util.ArrayList;
import java.util.List;
public class DeviceTypeMetaDefinition {
@ -19,6 +20,10 @@ public class DeviceTypeMetaDefinition {
private String description;
private boolean isSharedWithAllTenants;
private List<String> mqttEventTopicStructures;
private boolean longLivedToken = false;
public String getDescription() {
return description;
}
@ -83,4 +88,20 @@ public class DeviceTypeMetaDefinition {
public void setSharedWithAllTenants(boolean sharedWithAllTenants) {
isSharedWithAllTenants = sharedWithAllTenants;
}
public List<String> getMqttEventTopicStructures() {
return mqttEventTopicStructures;
}
public void setMqttEventTopicStructures(List<String> mqttEventTopicStructures) {
this.mqttEventTopicStructures = mqttEventTopicStructures;
}
public boolean isLongLivedToken() {
return longLivedToken;
}
public void setLongLivedToken(boolean longLivedToken) {
this.longLivedToken = longLivedToken;
}
}

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>device-mgt</artifactId>
<version>5.0.16-SNAPSHOT</version>
<version>5.0.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -103,6 +103,7 @@
org.wso2.carbon.ndatasource.core,
org.wso2.carbon.ntask.core.*,
org.wso2.carbon.ntask.common,
io.entgra.task.mgt.common.*,
org.apache.commons.collections;version="${commons-collections.version.range}",
org.wso2.carbon.email.sender.*,
io.swagger.annotations.*;resolution:=optional,
@ -112,7 +113,9 @@
org.wso2.carbon.event.processor.stub,
org.wso2.carbon.identity.jwt.client.extension.service,
org.apache.commons.codec.binary,
io.entgra.server.bootup.heartbeat.beacon
io.entgra.server.bootup.heartbeat.beacon,
io.entgra.device.mgt.extensions.logger.*,
io.entgra.notification.logger.*
</Import-Package>
<Export-Package>
!org.wso2.carbon.device.mgt.core.internal,
@ -347,6 +350,14 @@
<artifactId>okhttp</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>io.entgra.task.mgt.common</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>io.entgra.notification.logger</artifactId>
</dependency>
</dependencies>
</project>

@ -44,6 +44,7 @@ public final class DeviceManagementConstants {
public static final String DEVICE_CACHE = "DEVICE_CACHE";
public static final String API_RESOURCE_PERMISSION_CACHE = "API_RESOURCE_CACHE_CACHE";
public static final String GEOFENCE_CACHE = "GEOFENCE_CACHE";
public static final String BILLING_CACHE = "BILLING_CACHE";
public static final String META_KEY = "PER_DEVICE_COST";
public static final String ACTIVE_STATUS = "ACTIVE";
public static final String ENROLLMENT_NOTIFICATION_API_ENDPOINT = "/api/device-mgt/enrollment-notification";
@ -131,9 +132,11 @@ public final class DeviceManagementConstants {
public static final String USER_REGISTRATION_TEMPLATE = "user-registration";
public static final String USER_ENROLLMENT_TEMPLATE = "user-enrollment";
public static final String USER_VERIFY_TEMPLATE = "user-verify";
public static final String PRODUCT_DOWNLOAD_LINK_SHARING_TEMPLATE = "share-product-download-url";
public static final String POLICY_VIOLATE_TEMPLATE = "policy-violating-notifier";
public static final String USER_WELCOME_TEMPLATE = "user-welcome";
public static final String DEFAULT_ENROLLMENT_TEMPLATE = "default-enrollment-invitation";
public static final String ENROLLMENT_GUIDE_TEMPLATE = "enrollment-guide";
}
public static final class OperationAttributes {

@ -0,0 +1,79 @@
/*
* Copyright (c) 2022, 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.cache;
import java.sql.Timestamp;
import java.util.Objects;
public class BillingCacheKey {
private String tenantDomain;
private Timestamp startDate;
private Timestamp endDate;
private volatile int hashCode;
public String getTenantDomain() {
return tenantDomain;
}
public void setTenantDomain(String tenantDomain) {
this.tenantDomain = tenantDomain;
}
public Timestamp getStartDate() {
return startDate;
}
public void setStartDate(Timestamp startDate) {
this.startDate = startDate;
}
public Timestamp getEndDate() {
return endDate;
}
public void setEndDate(Timestamp endDate) {
this.endDate = endDate;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (!BillingCacheKey.class.isAssignableFrom(obj.getClass())) {
return false;
}
final BillingCacheKey other = (BillingCacheKey) obj;
String thisId = this.tenantDomain + "_" + this.startDate + "_" + this.endDate;
String otherId = other.tenantDomain + "_" + other.startDate + "_" + this.endDate;
if (!thisId.equals(otherId)) {
return false;
}
return true;
}
@Override
public int hashCode() {
if (hashCode == 0) {
hashCode = Objects.hash(tenantDomain, startDate, endDate);
}
return hashCode;
}
}

@ -0,0 +1,73 @@
/*
* Copyright (c) 2022, 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.cache;
import org.wso2.carbon.device.mgt.common.PaginationResult;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
import java.sql.Timestamp;
import java.util.List;
public interface BillingCacheManager {
/**
* Adds a given billing object to the billing-cache.
* @param startDate - startDate of the billing period.
* @param endDate - endDate of the billing period.
* @param paginationResult - PaginationResult object to be added.
* @param tenantDomain - Owning tenant of the billing.
*
*/
void addBillingToCache(PaginationResult paginationResult, String tenantDomain, Timestamp startDate, Timestamp endDate) throws DeviceManagementException;
/**
* Removes a billing object from billing-cache.
* @param startDate - startDate of the billing period.
* @param endDate - endDate of the billing period.
* @param tenantDomain - Owning tenant of the billing.
*
*/
void removeBillingFromCache(String tenantDomain, Timestamp startDate, Timestamp endDate) throws DeviceManagementException;
/**
* Removes a list of devices from billing-cache.
* @param billingList - List of Cache-Keys of the billing objects to be removed.
*
*/
void removeBillingsFromCache(List<BillingCacheKey> billingList) throws DeviceManagementException;
/**
* Updates a given billing object in the billing-cache.
* @param startDate - startDate of the billing period.
* @param endDate - endDate of the billing period.
* @param paginationResult - PaginationResult object to be updated.
* @param tenantDomain - Owning tenant of the billing.
*
*/
void updateBillingInCache(PaginationResult paginationResult, String tenantDomain, Timestamp startDate, Timestamp endDate) throws DeviceManagementException;
/**
* Fetches a billing object from billing-cache.
* @param startDate - startDate of the billing period.
* @param endDate - endDate of the billing period.
* @param tenantDomain - Owning tenant of the billing.
* @return Device object
*
*/
PaginationResult getBillingFromCache(String tenantDomain, Timestamp startDate, Timestamp endDate);
}

@ -0,0 +1,135 @@
/*
* Copyright (c) 2022, 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.cache.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.common.PaginationResult;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
import org.wso2.carbon.device.mgt.core.cache.BillingCacheKey;
import org.wso2.carbon.device.mgt.core.cache.BillingCacheManager;
import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil;
import javax.cache.Cache;
import java.sql.Timestamp;
import java.util.List;
/**
* Implementation of BillingCacheManager.
*/
public class BillingCacheManagerImpl implements BillingCacheManager {
private static final Log log = LogFactory.getLog(BillingCacheManagerImpl.class);
private static BillingCacheManagerImpl billingCacheManager;
private BillingCacheManagerImpl() {
}
public static BillingCacheManagerImpl getInstance() {
if (billingCacheManager == null) {
synchronized (BillingCacheManagerImpl.class) {
if (billingCacheManager == null) {
billingCacheManager = new BillingCacheManagerImpl();
}
}
}
return billingCacheManager;
}
@Override
public void addBillingToCache(PaginationResult paginationResult, String tenantDomain, Timestamp startDate, Timestamp endDate) throws DeviceManagementException {
Cache<BillingCacheKey, PaginationResult> lCache = DeviceManagerUtil.getBillingCache();
if (lCache != null) {
BillingCacheKey cacheKey = getCacheKey(tenantDomain, startDate, endDate);
if (lCache.containsKey(cacheKey)) {
this.updateBillingInCache(paginationResult, tenantDomain, startDate, endDate);
} else {
lCache.put(cacheKey, paginationResult);
}
}
}
@Override
public void removeBillingFromCache(String tenantDomain, Timestamp startDate, Timestamp endDate) throws DeviceManagementException {
Cache<BillingCacheKey, PaginationResult> lCache = DeviceManagerUtil.getBillingCache();
if (lCache != null) {
BillingCacheKey cacheKey = getCacheKey(tenantDomain, startDate, endDate);
if (lCache.containsKey(cacheKey)) {
lCache.remove(cacheKey);
}
} else {
String msg = "Failed to remove selected billing from cache";
log.error(msg);
throw new DeviceManagementException(msg);
}
}
@Override
public void removeBillingsFromCache(List<BillingCacheKey> billingList) throws DeviceManagementException {
Cache<BillingCacheKey, PaginationResult> lCache = DeviceManagerUtil.getBillingCache();
if (lCache != null) {
for (BillingCacheKey cacheKey : billingList) {
if (lCache.containsKey(cacheKey)) {
lCache.remove(cacheKey);
}
}
} else {
String msg = "Failed to remove billing from cache";
log.error(msg);
throw new DeviceManagementException(msg);
}
}
@Override
public void updateBillingInCache(PaginationResult paginationResult, String tenantDomain, Timestamp startDate, Timestamp endDate) throws DeviceManagementException {
Cache<BillingCacheKey, PaginationResult> lCache = DeviceManagerUtil.getBillingCache();
if (lCache != null) {
BillingCacheKey cacheKey = getCacheKey(tenantDomain, startDate, endDate);
if (lCache.containsKey(cacheKey)) {
lCache.replace(cacheKey, paginationResult);
}
} else {
String msg = "Failed to update billing cache";
log.error(msg);
throw new DeviceManagementException(msg);
}
}
// TODO remove null check from here and do cache enable check in the methods calling this
@Override
public PaginationResult getBillingFromCache(String tenantDomain, Timestamp startDate, Timestamp endDate) {
Cache<BillingCacheKey, PaginationResult> lCache = DeviceManagerUtil.getBillingCache();
if (lCache != null) {
return lCache.get(getCacheKey(tenantDomain, startDate, endDate));
}
return null;
}
/**
* This method generates the billing CacheKey and returns it.
*/
private BillingCacheKey getCacheKey(String tenantDomain, Timestamp startDate, Timestamp endDate) {
BillingCacheKey billingCacheKey = new BillingCacheKey();
billingCacheKey.setTenantDomain(tenantDomain);
billingCacheKey.setStartDate(startDate);
billingCacheKey.setEndDate(endDate);
return billingCacheKey;
}
}

@ -24,4 +24,6 @@ public class Constants {
public static final String URI_SEPARATOR = "/";
public static final String BASIC_AUTH_HEADER_PREFIX = "Basic ";
public static final String BEARER = "Bearer ";
public static final String SEND_USERNAME = "SEND_USERNAME";
}

@ -21,9 +21,11 @@ import org.wso2.carbon.device.mgt.common.enrollment.notification.EnrollmentNotif
import org.wso2.carbon.device.mgt.common.roles.config.DefaultRoles;
import org.wso2.carbon.device.mgt.core.config.analytics.OperationAnalyticsConfiguration;
import org.wso2.carbon.device.mgt.core.config.archival.ArchivalConfiguration;
import org.wso2.carbon.device.mgt.core.config.cache.BillingCacheConfiguration;
import org.wso2.carbon.device.mgt.core.config.cache.CertificateCacheConfiguration;
import org.wso2.carbon.device.mgt.core.config.cache.DeviceCacheConfiguration;
import org.wso2.carbon.device.mgt.core.config.cache.GeoFenceCacheConfiguration;
import org.wso2.carbon.device.mgt.core.config.enrollment.guide.EnrollmentGuideConfiguration;
import org.wso2.carbon.device.mgt.core.config.operation.timeout.OperationTimeoutConfiguration;
import org.wso2.carbon.device.mgt.core.event.config.EventOperationTaskConfiguration;
import org.wso2.carbon.device.mgt.core.config.geo.location.GeoLocationConfiguration;
@ -58,6 +60,7 @@ public final class DeviceManagementConfig {
private DeviceStatusTaskConfig deviceStatusTaskConfig;
private DeviceCacheConfiguration deviceCacheConfiguration;
private GeoFenceCacheConfiguration geoFenceCacheConfiguration;
private BillingCacheConfiguration billingCacheConfiguration;
private EventOperationTaskConfiguration eventOperationTaskConfiguration;
private CertificateCacheConfiguration certificateCacheConfiguration;
private OperationAnalyticsConfiguration operationAnalyticsConfiguration;
@ -68,6 +71,7 @@ public final class DeviceManagementConfig {
private EnrollmentNotificationConfiguration enrollmentNotificationConfiguration;
private DefaultRoles defaultRoles;
private OperationTimeoutConfiguration operationTimeoutConfiguration;
private EnrollmentGuideConfiguration enrollmentGuideConfiguration;
@XmlElement(name = "ManagementRepository", required = true)
public DeviceManagementConfigRepository getDeviceManagementConfigRepository() {
@ -169,6 +173,15 @@ public final class DeviceManagementConfig {
this.geoFenceCacheConfiguration = geoFenceCacheConfiguration;
}
@XmlElement(name = "BillingCacheConfiguration", required = true)
public BillingCacheConfiguration getBillingCacheConfiguration() {
return billingCacheConfiguration;
}
public void setBillingCacheConfiguration(BillingCacheConfiguration billingCacheConfiguration) {
this.billingCacheConfiguration = billingCacheConfiguration;
}
@XmlElement(name = "EventOperationTaskConfiguration", required = true)
public EventOperationTaskConfiguration getEventOperationTaskConfiguration() {
return eventOperationTaskConfiguration;
@ -254,5 +267,14 @@ public final class DeviceManagementConfig {
public void setOperationTimeoutConfiguration(OperationTimeoutConfiguration operationTimeoutConfiguration) {
this.operationTimeoutConfiguration = operationTimeoutConfiguration;
}
@XmlElement(name = "EnrollmentGuideConfiguration", required = true)
public EnrollmentGuideConfiguration getEnrollmentGuideConfiguration() {
return enrollmentGuideConfiguration;
}
public void setEnrollmentGuideConfiguration(EnrollmentGuideConfiguration enrollmentGuideConfiguration) {
this.enrollmentGuideConfiguration = enrollmentGuideConfiguration;
}
}

@ -0,0 +1,56 @@
/*
* Copyright (c) 2022, 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.cache;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "BillingCacheConfiguration")
public class BillingCacheConfiguration {
private boolean isEnabled;
private int expiryTime;
private long capacity;
@XmlElement(name = "Enable", required = true)
public boolean isEnabled() {
return isEnabled;
}
public void setEnabled(boolean enabled) {
isEnabled = enabled;
}
@XmlElement(name = "ExpiryTime", required = true)
public int getExpiryTime() {
return expiryTime;
}
public void setExpiryTime(int expiryTime) {
this.expiryTime = expiryTime;
}
@XmlElement(name = "Capacity", required = true)
public long getCapacity() {
return capacity;
}
public void setCapacity(long capacity) {
this.capacity = capacity;
}
}

@ -0,0 +1,30 @@
package org.wso2.carbon.device.mgt.core.config.enrollment.guide;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "EnrollmentGuideConfiguration")
public class EnrollmentGuideConfiguration {
private boolean isEnabled;
private String mail;
@XmlElement(name = "Enable", required = true)
public boolean isEnabled() {
return isEnabled;
}
public void setEnabled(boolean enabled) {
isEnabled = enabled;
}
@XmlElement(name = "Mail", required = true)
public String getMail() {
return mail;
}
public void setMail(String mail) {
this.mail = mail;
}
}

@ -0,0 +1,63 @@
/*
* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.core.config.ui;
import javax.xml.bind.annotation.XmlElement;
public class HubspotChat {
private boolean isEnableHubspot;
private String trackingUrl;
private String accessToken;
private String senderActorId;
@XmlElement(name = "EnableHubspot")
public boolean isEnableHubspot() {
return isEnableHubspot;
}
public void setEnableHubspot(boolean enableHubspot) {
isEnableHubspot = enableHubspot;
}
@XmlElement(name = "TrackingUrl")
public String getTrackingUrl() {
return trackingUrl;
}
public void setTrackingUrl(String trackingUrl) {
this.trackingUrl = trackingUrl;
}
@XmlElement(name = "AccessToken")
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
@XmlElement(name = "SenderActorId")
public String getSenderActorId() {
return senderActorId;
}
public void setSenderActorId(String senderActorId) {
this.senderActorId = senderActorId;
}
}

@ -34,6 +34,7 @@ public class UIConfiguration {
private int sessionTimeOut;
private int loginCacheCapacity;
private Billing billing;
private HubspotChat hubspotChat;
@XmlElement(name = "AppRegistration", required=true)
public AppRegistration getAppRegistration() {
@ -63,6 +64,14 @@ public class UIConfiguration {
isSsoEnable = ssoEnable;
}
@XmlElement(name = "HubspotChat", required = true)
public HubspotChat getHubspotChat() {
return hubspotChat;
}
public void setHubspotChat(HubspotChat hubspotChat) {
this.hubspotChat = hubspotChat;
}
@XmlElement(name = "Billing", required=true)
public Billing getBilling() {
return billing;

@ -1,13 +0,0 @@
package org.wso2.carbon.device.mgt.core.dao;
import org.wso2.carbon.device.mgt.common.Billing;
import java.sql.Timestamp;
import java.util.List;
public interface BillingDAO {
void addBilling(int deviceId, int tenantId, Timestamp billingStart, Timestamp billingEnd) throws DeviceManagementDAOException;
List<Billing> getBilling(int deviceId, Timestamp billingStart, Timestamp billingEnd) throws DeviceManagementDAOException;
}

@ -293,6 +293,50 @@ public interface DeviceDAO {
*/
List<Device> getDevices(PaginationRequest request, int tenantId) throws DeviceManagementDAOException;
/**
* This method is used to retrieve the not removed device list in a year of a given tenant without pagination.
*
* @param tenantId tenant id.
* @param startDate start date of usage period.
* @param endDate end date of usage period.
* @return returns a list of not removed devices enrolled in that year.
* @throws DeviceManagementDAOException
*/
List<Device> getNonRemovedYearlyDeviceList(int tenantId, Timestamp startDate, Timestamp endDate) throws DeviceManagementDAOException;
/**
* This method is used to retrieve the removed device list in a year of a given tenant without pagination.
*
* @param tenantId tenant id.
* @param startDate start date of usage period.
* @param endDate end date of usage period.
* @return returns a list of removed devices enrolled in that year.
* @throws DeviceManagementDAOException
*/
List<Device> getRemovedYearlyDeviceList(int tenantId, Timestamp startDate, Timestamp endDate) throws DeviceManagementDAOException;
/**
* This method is used to retrieve the not removed device list in the prior year of a given tenant without pagination.
*
* @param tenantId tenant id.
* @param startDate start date of usage period.
* @param endDate end date of usage period.
* @return returns a list of not removed devices enrolled prior to that year.
* @throws DeviceManagementDAOException
*/
List<Device> getNonRemovedPriorYearsDeviceList(int tenantId, Timestamp startDate, Timestamp endDate) throws DeviceManagementDAOException;
/**
* This method is used to retrieve the removed device list in the prior year of a given tenant without pagination.
*
* @param tenantId tenant id.
* @param startDate start date of usage period.
* @param endDate end date of usage period.
* @return returns a list of removed devices enrolled prior to that year.
* @throws DeviceManagementDAOException
*/
List<Device> getRemovedPriorYearsDeviceList(int tenantId, Timestamp startDate, Timestamp endDate) throws DeviceManagementDAOException;
/**
* This method is used to retrieve the devices of a given tenant without pagination.
* @param tenantId tenant id.

@ -125,11 +125,6 @@ public class DeviceManagementDAOFactory {
return new EnrollmentDAOImpl();
}
public static BillingDAO getBillingDAO() {
return new BillingDAOImpl();
}
public static TrackerDAO getTrackerDAO() {
if (databaseEngine != null) {
switch (databaseEngine) {

@ -33,8 +33,6 @@ public interface EnrollmentDAO {
boolean updateEnrollmentStatus(List<EnrolmentInfo> enrolmentInfos) throws DeviceManagementDAOException;
boolean updateEnrollmentLastBilledDate(EnrolmentInfo enrolmentInfos, Timestamp lastBilledDate, int tenantId) throws DeviceManagementDAOException;
int removeEnrollment(int deviceId, String currentOwner, int tenantId) throws DeviceManagementDAOException;
@Deprecated

@ -1,71 +0,0 @@
package org.wso2.carbon.device.mgt.core.dao.impl;
import org.wso2.carbon.device.mgt.common.Billing;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.core.dao.BillingDAO;
import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException;
import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory;
import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class BillingDAOImpl implements BillingDAO {
@Override
public void addBilling(int deviceId, int tenantId, Timestamp billingStart, Timestamp billingEnd) throws DeviceManagementDAOException {
Connection conn;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = this.getConnection();
String sql = "INSERT INTO DM_BILLING(DEVICE_ID, TENANT_ID, BILLING_START, BILLING_END) VALUES(?, ?, ?, ?)";
stmt = conn.prepareStatement(sql, new String[] {"invoice_id"});
stmt.setInt(1, deviceId);
stmt.setInt(2,tenantId);
stmt.setTimestamp(3, billingStart);
stmt.setTimestamp(4, billingEnd);
stmt.execute();
} catch (SQLException e) {
e.printStackTrace();
throw new DeviceManagementDAOException("Error occurred while adding billing period", e);
} finally {
DeviceManagementDAOUtil.cleanupResources(stmt, rs);
}
}
@Override
public List<Billing> getBilling(int deviceId, Timestamp billingStart, Timestamp billingEnd) throws DeviceManagementDAOException {
List<Billing> billings = new ArrayList<>();
Connection conn;
PreparedStatement stmt = null;
ResultSet rs = null;
EnrolmentInfo.Status status = null;
try {
conn = this.getConnection();
String sql;
sql = "SELECT * FROM DM_BILLING WHERE DEVICE_ID = ?";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, deviceId);
rs = stmt.executeQuery();
while (rs.next()) {
Billing bill = new Billing(rs.getInt("INVOICE_ID"), rs.getInt("DEVICE_ID"),rs.getInt("TENANT_ID"),
(rs.getTimestamp("BILLING_START").getTime()), (rs.getTimestamp("BILLING_END").getTime()));
billings.add(bill);
}
} catch (SQLException e) {
throw new DeviceManagementDAOException("Error occurred getting billing periods", e);
} finally {
DeviceManagementDAOUtil.cleanupResources(stmt, null);
}
return billings;
}
private Connection getConnection() throws SQLException {
return DeviceManagementDAOFactory.getConnection();
}
}

@ -25,13 +25,7 @@ public class DeviceStatusDAOImpl implements DeviceStatusDAO {
conn = this.getConnection();
// either we list all status values for the device using the device id or only get status values for the given enrolment id
String idType = isDeviceId ? "DEVICE_ID" : "ENROLMENT_ID";
String sql;
if (billingStatus) {
sql = "SELECT ENROLMENT_ID, DEVICE_ID, UPDATE_TIME, STATUS, CHANGED_BY FROM DM_DEVICE_STATUS WHERE STATUS IN ('ACTIVE','REMOVED') AND " + idType + " = ?";
} else {
sql = "SELECT ENROLMENT_ID, DEVICE_ID, UPDATE_TIME, STATUS, CHANGED_BY FROM DM_DEVICE_STATUS WHERE " + idType + " = ?";
}
String sql = "SELECT ENROLMENT_ID, DEVICE_ID, UPDATE_TIME, STATUS, CHANGED_BY FROM DM_DEVICE_STATUS WHERE " + idType + " = ?";
// filter the data based on a date range if specified
if (fromDate != null){
@ -41,6 +35,10 @@ public class DeviceStatusDAOImpl implements DeviceStatusDAO {
sql += " AND UPDATE_TIME <= ?";
}
if (billingStatus) {
sql += " ORDER BY UPDATE_TIME DESC";
}
stmt = conn.prepareStatement(sql);
int i = 1;

@ -144,28 +144,6 @@ public class EnrollmentDAOImpl implements EnrollmentDAO {
return status;
}
@Override
public boolean updateEnrollmentLastBilledDate(EnrolmentInfo enrolmentInfo, Timestamp lastBilledDate, int tenantId) throws DeviceManagementDAOException {
Connection conn;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = this.getConnection();
String sql = "UPDATE DM_ENROLMENT SET LAST_BILLED_DATE = ? WHERE ID = ? AND TENANT_ID = ?";
stmt = conn.prepareStatement(sql);
stmt.setLong(1, lastBilledDate.getTime());
stmt.setInt(2, enrolmentInfo.getId());
stmt.setInt(3, tenantId);
stmt.executeUpdate();
return true;
} catch (SQLException e) {
throw new DeviceManagementDAOException("Error occurred while updating enrolment last billed date.", e);
} finally {
DeviceManagementDAOUtil.cleanupResources(stmt, rs);
}
}
@Override
public int removeEnrollment(int deviceId, String currentOwner,
int tenantId) throws DeviceManagementDAOException {

@ -84,7 +84,6 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl {
"e.IS_TRANSFERRED, " +
"e.DATE_OF_LAST_UPDATE, " +
"e.DATE_OF_ENROLMENT, " +
"e.LAST_BILLED_DATE, " +
"e.ID AS ENROLMENT_ID " +
"FROM DM_ENROLMENT e, " +
"(SELECT d.ID, " +
@ -188,6 +187,169 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl {
}
}
@Override
public List<Device> getNonRemovedYearlyDeviceList(int tenantId, Timestamp startDate, Timestamp endDate)
throws DeviceManagementDAOException {
List<Device> devices = new ArrayList<>();
try {
Connection conn = getConnection();
String sql = "SELECT d.ID AS DEVICE_ID, " +
"DEVICE_IDENTIFICATION, " +
"DESCRIPTION, " +
"NAME, " +
"DATE_OF_ENROLMENT, " +
"STATUS, " +
"DATE_OF_LAST_UPDATE, " +
"TIMESTAMPDIFF(DAY, ?, DATE_OF_ENROLMENT) as DAYS_SINCE_ENROLLED " +
"FROM DM_DEVICE d, DM_ENROLMENT e " +
"WHERE " +
"e.TENANT_ID=? AND " +
"d.ID=e.DEVICE_ID AND " +
"STATUS !='REMOVED' AND " +
"(" +
"DATE_OF_ENROLMENT BETWEEN ? AND ? " +
")";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, String.valueOf(endDate));
stmt.setInt(2, tenantId);
stmt.setString(3, String.valueOf(startDate));
stmt.setString(4, String.valueOf(endDate));
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
devices.add(DeviceManagementDAOUtil.loadDeviceBilling(rs));
}
}
} catch (SQLException e) {
throw new DeviceManagementDAOException("Error occurred while fetching the list of NonRemovedYearly device billing ", e);
}
return devices;
}
@Override
public List<Device> getRemovedYearlyDeviceList(int tenantId, Timestamp startDate, Timestamp endDate)
throws DeviceManagementDAOException {
Connection conn;
List<Device> devices = new ArrayList<>();
try {
conn = this.getConnection();
String sql = "select d.ID AS DEVICE_ID, " +
"DEVICE_IDENTIFICATION, " +
"DESCRIPTION, " +
"NAME, " +
"DATE_OF_ENROLMENT, " +
"DATE_OF_LAST_UPDATE, " +
"STATUS, " +
"TIMESTAMPDIFF(DAY, DATE_OF_LAST_UPDATE, DATE_OF_ENROLMENT) AS DAYS_USED " +
"from DM_DEVICE d, DM_ENROLMENT e " +
"where " +
"e.TENANT_ID=? and d.ID=e.DEVICE_ID and " +
"STATUS ='REMOVED' and " +
"(" +
"DATE_OF_ENROLMENT between ? and ? " +
") and " +
"(" +
"DATE_OF_LAST_UPDATE >= ? " +
")";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, tenantId);
stmt.setString(2, String.valueOf(startDate));
stmt.setString(3, String.valueOf(endDate));
stmt.setString(4, String.valueOf(startDate));
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
devices.add(DeviceManagementDAOUtil.loadDeviceBilling(rs));
}
}
} catch (SQLException e) {
throw new DeviceManagementDAOException("Error occurred while fetching the list of RemovedYearly device billing ", e);
}
return devices;
}
@Override
public List<Device> getNonRemovedPriorYearsDeviceList(int tenantId, Timestamp startDate, Timestamp endDate)
throws DeviceManagementDAOException {
Connection conn;
List<Device> devices = new ArrayList<>();
try {
conn = this.getConnection();
String sql = "select d.ID AS DEVICE_ID, " +
"DEVICE_IDENTIFICATION, " +
"DESCRIPTION, " +
"NAME, " +
"DATE_OF_ENROLMENT, " +
"STATUS, " +
"DATE_OF_LAST_UPDATE, " +
"TIMESTAMPDIFF(DAY, ?, ?) as DAYS_SINCE_ENROLLED " +
"from DM_DEVICE d, DM_ENROLMENT e " +
"where " +
"e.TENANT_ID=? and " +
"d.ID=e.DEVICE_ID and " +
"STATUS !='REMOVED' and " +
"(" +
"DATE_OF_ENROLMENT < ? " +
")";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, String.valueOf(endDate));
stmt.setString(2, String.valueOf(startDate));
stmt.setInt(3, tenantId);
stmt.setString(4, String.valueOf(startDate));
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
devices.add(DeviceManagementDAOUtil.loadDeviceBilling(rs));
}
}
} catch (SQLException e) {
throw new DeviceManagementDAOException("Error occurred while fetching the list of NonRemovedPriorYears device billing ", e);
}
return devices;
}
@Override
public List<Device> getRemovedPriorYearsDeviceList(int tenantId, Timestamp startDate, Timestamp endDate)
throws DeviceManagementDAOException {
Connection conn;
List<Device> devices = new ArrayList<>();
try {
conn = this.getConnection();
String sql = "select d.ID AS DEVICE_ID, " +
"DEVICE_IDENTIFICATION, " +
"DESCRIPTION, " +
"NAME, " +
"DATE_OF_ENROLMENT, " +
"DATE_OF_LAST_UPDATE, " +
"STATUS, " +
"TIMESTAMPDIFF(DAY, DATE_OF_LAST_UPDATE, ?) AS DAYS_USED " +
"from DM_DEVICE d, DM_ENROLMENT e " +
"where " +
"e.TENANT_ID=? and d.ID=e.DEVICE_ID and " +
"STATUS ='REMOVED' and " +
"(" +
"DATE_OF_ENROLMENT < ? " +
") and " +
"(" +
"DATE_OF_LAST_UPDATE >= ? " +
")";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, String.valueOf(startDate));
stmt.setInt(2, tenantId);
stmt.setString(3, String.valueOf(startDate));
stmt.setString(4, String.valueOf(startDate));
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
devices.add(DeviceManagementDAOUtil.loadDeviceBilling(rs));
}
}
} catch (SQLException e) {
throw new DeviceManagementDAOException("Error occurred while fetching the list of RemovedPriorYears device billing ", e);
}
return devices;
}
//Return only not removed id list
@Override
public List<Device> getDeviceListWithoutPagination(int tenantId)
@ -197,10 +359,26 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl {
List<Device> devices = new ArrayList<>();
try {
conn = this.getConnection();
String sql = "SELECT DM_DEVICE.ID AS DEVICE_ID, DEVICE_IDENTIFICATION, DESCRIPTION, DM_DEVICE.NAME AS DEVICE_NAME, DM_DEVICE_TYPE.NAME AS DEVICE_TYPE,\n" +
"DM_ENROLMENT.ID AS ENROLMENT_ID, DATE_OF_ENROLMENT,OWNER, OWNERSHIP,IS_TRANSFERRED, STATUS, DATE_OF_LAST_UPDATE, LAST_BILLED_DATE,\n" +
"TIMESTAMPDIFF(DAY, DATE_OF_ENROLMENT, CURDATE()) as DAYS_SINCE_ENROLLED FROM DM_DEVICE JOIN DM_ENROLMENT\n" +
"ON (DM_DEVICE.ID = DM_ENROLMENT.DEVICE_ID) JOIN DM_DEVICE_TYPE ON (DM_DEVICE.DEVICE_TYPE_ID = DM_DEVICE_TYPE.ID) WHERE DM_ENROLMENT.TENANT_ID=?";
String sql = "SELECT " +
"DM_DEVICE.ID AS DEVICE_ID, " +
"DEVICE_IDENTIFICATION, " +
"DESCRIPTION, " +
"DM_DEVICE.NAME AS DEVICE_NAME, " +
"DM_DEVICE_TYPE.NAME AS DEVICE_TYPE, " +
"DM_ENROLMENT.ID AS ENROLMENT_ID, " +
"DATE_OF_ENROLMENT, " +
"OWNER, " +
"OWNERSHIP, " +
"IS_TRANSFERRED, " +
"STATUS, " +
"DATE_OF_LAST_UPDATE, " +
"TIMESTAMPDIFF(DAY, DATE_OF_ENROLMENT, CURDATE()) as DAYS_SINCE_ENROLLED " +
"FROM " +
"DM_DEVICE " +
"JOIN DM_ENROLMENT ON (DM_DEVICE.ID = DM_ENROLMENT.DEVICE_ID) " +
"JOIN DM_DEVICE_TYPE ON (DM_DEVICE.DEVICE_TYPE_ID = DM_DEVICE_TYPE.ID) " +
"WHERE " +
"DM_ENROLMENT.TENANT_ID = ? ";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, tenantId);
ResultSet rs = stmt.executeQuery();

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

Loading…
Cancel
Save