diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/main/java/org/wso2/carbon/certificate/mgt/core/impl/CertificateGenerator.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/main/java/org/wso2/carbon/certificate/mgt/core/impl/CertificateGenerator.java index 20b4833d56..d686ff5115 100755 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/main/java/org/wso2/carbon/certificate/mgt/core/impl/CertificateGenerator.java +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/main/java/org/wso2/carbon/certificate/mgt/core/impl/CertificateGenerator.java @@ -97,10 +97,7 @@ import java.security.cert.CertificateNotYetValidException; import java.security.cert.X509Certificate; import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.List; +import java.util.*; import java.util.concurrent.TimeUnit; public class CertificateGenerator { @@ -798,8 +795,16 @@ public class CertificateGenerator { BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis()); - X500Name issuerName = new X500Name(certCA.getSubjectDN().getName()); - + //Reversing the order of components of the subject DN due to Nginx not verifying the client certificate + //generated by Java using this subject DN. + //Ref: https://stackoverflow.com/questions/33769978 & engineering mail SCEP implementation for Android + String[] dnParts = certCA.getSubjectDN().getName().split(","); + StringJoiner joiner = new StringJoiner(","); + for (int i = (dnParts.length - 1); i >= 0; i--) { + joiner.add(dnParts[i]); + } + String subjectDn = joiner.toString(); + X500Name issuerName = new X500Name(subjectDn); String commonName = certificationRequest.getSubject().getRDNs(BCStyle.CN)[0].getFirst() .getValue().toString(); X500Name subjectName = new X500Name("O=" + commonName + "O=AndroidDevice,CN=" + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java index 46a37b9f59..f90c45e106 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java @@ -826,8 +826,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { deviceConfig.setClientId(dcrResponse.getClientId()); deviceConfig.setClientSecret(dcrResponse.getClientSecret()); - StringBuilder scopes = new StringBuilder("device_" + type.replace(" ", "") - .replace("_", "") + "_" + id); + StringBuilder scopes = new StringBuilder("device:" + type.replace(" ", "") + ":" + id); for (String topic : mqttEventTopicStructure) { if (topic.contains("${deviceId}")) { topic = topic.replace("${deviceId}", id); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java index cbd7c697f4..b6aadb113f 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java @@ -31,6 +31,8 @@ import org.wso2.carbon.device.mgt.core.dao.impl.device.GenericDeviceDAOImpl; import org.wso2.carbon.device.mgt.core.dao.impl.device.OracleDeviceDAOImpl; import org.wso2.carbon.device.mgt.core.dao.impl.device.PostgreSQLDeviceDAOImpl; import org.wso2.carbon.device.mgt.core.dao.impl.device.SQLServerDeviceDAOImpl; +import org.wso2.carbon.device.mgt.core.dao.impl.enrolment.GenericEnrollmentDAOImpl; +import org.wso2.carbon.device.mgt.core.dao.impl.enrolment.SQLServerEnrollmentDAOImpl; import org.wso2.carbon.device.mgt.core.dao.impl.tracker.TrackerDAOImpl; import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil; import org.wso2.carbon.device.mgt.core.device.details.mgt.dao.DeviceDetailsDAO; @@ -41,7 +43,6 @@ import org.wso2.carbon.device.mgt.core.privacy.dao.impl.PrivacyComplianceDAOImpl import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; -import java.sql.Timestamp; import java.util.Hashtable; import java.util.List; @@ -122,7 +123,20 @@ public class DeviceManagementDAOFactory { } public static EnrollmentDAO getEnrollmentDAO() { - return new EnrollmentDAOImpl(); + if (databaseEngine != null) { + switch (databaseEngine) { + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_MSSQL: + return new SQLServerEnrollmentDAOImpl(); + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_POSTGRESQL: + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_ORACLE: + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_H2: + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_MYSQL: + return new GenericEnrollmentDAOImpl(); + default: + throw new UnsupportedDatabaseEngineException("Unsupported database engine : " + databaseEngine); + } + } + throw new IllegalStateException("Database engine has not initialized properly."); } public static TrackerDAO getTrackerDAO() { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EventManagementDAOFactory.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EventManagementDAOFactory.java index 754b519004..09e5353fa6 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EventManagementDAOFactory.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EventManagementDAOFactory.java @@ -29,6 +29,8 @@ import org.wso2.carbon.device.mgt.core.config.datasource.JNDILookupDefinition; import org.wso2.carbon.device.mgt.core.dao.impl.*; import org.wso2.carbon.device.mgt.core.dao.impl.event.GenericEventConfigDAOImpl; import org.wso2.carbon.device.mgt.core.dao.impl.event.H2EventConfigDAOImpl; +import org.wso2.carbon.device.mgt.core.dao.impl.geofence.GenericGeofenceDAOImpl; +import org.wso2.carbon.device.mgt.core.dao.impl.geofence.SQLServerGeofenceDAOImpl; import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil; import javax.sql.DataSource; @@ -45,7 +47,20 @@ public class EventManagementDAOFactory { public static GeofenceDAO getGeofenceDAO() { - return new GeofenceDAOImpl(); + if (databaseEngine != null) { + switch (databaseEngine) { + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_MSSQL: + return new SQLServerGeofenceDAOImpl(); + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_POSTGRESQL: + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_ORACLE: + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_MYSQL: + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_H2: + return new GenericGeofenceDAOImpl(); + default: + throw new UnsupportedDatabaseEngineException("Unsupported database engine : " + databaseEngine); + } + } + throw new IllegalStateException("Database engine has not initialized properly."); } public static EventConfigDAO getEventConfigDAO() { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/EnrollmentDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractEnrollmentDAOImpl.java similarity index 99% rename from components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/EnrollmentDAOImpl.java rename to components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractEnrollmentDAOImpl.java index 7b3e08cd50..a3757bc523 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/EnrollmentDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractEnrollmentDAOImpl.java @@ -37,7 +37,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; -public class EnrollmentDAOImpl implements EnrollmentDAO { +public abstract class AbstractEnrollmentDAOImpl implements EnrollmentDAO { @Override public EnrolmentInfo addEnrollment(int deviceId, EnrolmentInfo enrolmentInfo, diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/GeofenceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractGeofenceDAOImpl.java similarity index 99% rename from components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/GeofenceDAOImpl.java rename to components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractGeofenceDAOImpl.java index e845a43da9..4c8cd12e7e 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/GeofenceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractGeofenceDAOImpl.java @@ -25,7 +25,6 @@ import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.event.config.EventConfig; import org.wso2.carbon.device.mgt.common.geo.service.GeofenceData; 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.EventManagementDAOFactory; import org.wso2.carbon.device.mgt.core.dao.GeofenceDAO; import org.wso2.carbon.device.mgt.core.dto.event.config.GeoFenceGroupMap; @@ -45,8 +44,8 @@ import java.util.List; import java.util.Map; import java.util.Set; -public class GeofenceDAOImpl implements GeofenceDAO { - private static final Log log = LogFactory.getLog(GeofenceDAOImpl.class); +public abstract class AbstractGeofenceDAOImpl implements GeofenceDAO { + private static final Log log = LogFactory.getLog(AbstractGeofenceDAOImpl.class); @Override public GeofenceData saveGeofence(GeofenceData geofenceData) throws DeviceManagementDAOException { try { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/enrolment/GenericEnrollmentDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/enrolment/GenericEnrollmentDAOImpl.java new file mode 100644 index 0000000000..041efbf285 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/enrolment/GenericEnrollmentDAOImpl.java @@ -0,0 +1,555 @@ +/* + * Copyright (c) 2023, 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.dao.impl.enrolment; + +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; +import org.wso2.carbon.device.mgt.common.EnrolmentInfo; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.dao.impl.AbstractEnrollmentDAOImpl; +import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil; + +import java.sql.*; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class GenericEnrollmentDAOImpl extends AbstractEnrollmentDAOImpl { + + @Override + public EnrolmentInfo addEnrollment(int deviceId, EnrolmentInfo enrolmentInfo, + int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + String sql = "INSERT INTO DM_ENROLMENT(DEVICE_ID, OWNER, OWNERSHIP, STATUS, " + + "DATE_OF_ENROLMENT, DATE_OF_LAST_UPDATE, TENANT_ID) VALUES(?, ?, ?, ?, ?, ?, ?)"; + stmt = conn.prepareStatement(sql, new String[] {"id"}); + Timestamp enrollmentTime = new Timestamp(new Date().getTime()); + stmt.setInt(1, deviceId); + stmt.setString(2, enrolmentInfo.getOwner()); + stmt.setString(3, enrolmentInfo.getOwnership().toString()); + stmt.setString(4, enrolmentInfo.getStatus().toString()); + stmt.setTimestamp(5, enrollmentTime); + stmt.setTimestamp(6, enrollmentTime); + stmt.setInt(7, tenantId); + stmt.execute(); + + rs = stmt.getGeneratedKeys(); + if (rs.next()) { + int enrolmentId = rs.getInt(1); + enrolmentInfo.setId(enrolmentId); + enrolmentInfo.setDateOfEnrolment(enrollmentTime.getTime()); + enrolmentInfo.setDateOfLastUpdate(enrollmentTime.getTime()); + addDeviceStatus(enrolmentId, enrolmentInfo.getStatus()); + return enrolmentInfo; + } + return null; + } catch (SQLException e) { + e.printStackTrace(); + throw new DeviceManagementDAOException("Error occurred while adding enrolment configuration", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public int updateEnrollment(EnrolmentInfo enrolmentInfo, int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + String sql = "UPDATE DM_ENROLMENT SET OWNERSHIP = ?, STATUS = ?, DATE_OF_LAST_UPDATE = ? " + + "WHERE ID = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setString(1, enrolmentInfo.getOwnership().toString()); + stmt.setString(2, enrolmentInfo.getStatus().toString()); + stmt.setTimestamp(3, new Timestamp(new Date().getTime())); + stmt.setInt(4, enrolmentInfo.getId()); + stmt.setInt(5, tenantId); + int updatedCount = stmt.executeUpdate(); + if (updatedCount == 1){ + addDeviceStatus(enrolmentInfo.getId(), enrolmentInfo.getStatus()); + } + return updatedCount; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while updating enrolment configuration", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public boolean updateEnrollmentStatus(List enrolmentInfos) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + boolean status = false; + int updateStatus = -1; + try { + conn = this.getConnection(); + String sql = "UPDATE DM_ENROLMENT SET STATUS = ? WHERE ID = ?"; + stmt = conn.prepareStatement(sql); + if (conn.getMetaData().supportsBatchUpdates()) { + for (EnrolmentInfo enrolmentInfo : enrolmentInfos) { + stmt.setString(1, enrolmentInfo.getStatus().toString()); + stmt.setInt(2, enrolmentInfo.getId()); + stmt.addBatch(); + } + updateStatus = stmt.executeBatch().length; + } else { + for (EnrolmentInfo enrolmentInfo : enrolmentInfos) { + stmt.setString(1, enrolmentInfo.getStatus().toString()); + stmt.setInt(2, enrolmentInfo.getId()); + updateStatus = stmt.executeUpdate(); + } + } + if (updateStatus > 0) { + status = true; + for (EnrolmentInfo enrolmentInfo : enrolmentInfos) { + addDeviceStatus(enrolmentInfo); + } + } + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while updating enrolment status of given device-list.", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + return status; + } + + @Override + public int removeEnrollment(int deviceId, String currentOwner, + int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + int status = -1; + try { + conn = this.getConnection(); + String sql = "DELETE FROM DM_ENROLMENT WHERE DEVICE_ID = ? AND OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql, new String[] {"id"}); + stmt.setInt(1, deviceId); + stmt.setString(2, currentOwner); + stmt.setInt(3, tenantId); + stmt.executeUpdate(); + + rs = stmt.getGeneratedKeys(); + if (rs.next()) { + status = 1; + } + return status; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while removing device enrolment", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + private int getCountOfDevicesOfOwner(String owner, int tenantID) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + int count = 0; + try { + conn = this.getConnection(); + String checkQuery = "SELECT COUNT(ID) AS COUNT FROM DM_ENROLMENT WHERE OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(checkQuery); + stmt.setString(1, owner); + stmt.setInt(2, tenantID); + rs = stmt.executeQuery(); + if(rs.next()){ + count = rs.getInt("COUNT"); + } + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while trying to get device " + + "count of Owner : "+owner, e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + return count; + } + + @Override + public boolean setStatus(String currentOwner, EnrolmentInfo.Status status, + int tenantId) throws DeviceManagementDAOException { + return setStatusAllDevices(currentOwner, status, tenantId); + } + + @Override + public boolean setStatusAllDevices(String currentOwner, EnrolmentInfo.Status status, int tenantId) + throws DeviceManagementDAOException{ + Connection conn; + PreparedStatement stmt = null; + Timestamp updateTime = new Timestamp(new Date().getTime()); + if(getCountOfDevicesOfOwner(currentOwner, tenantId) > 0){ + try { + conn = this.getConnection(); + String sql = "UPDATE DM_ENROLMENT SET STATUS = ?, DATE_OF_LAST_UPDATE = ? WHERE OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setString(1, status.toString()); + stmt.setTimestamp(2, updateTime); + stmt.setString(3, currentOwner); + stmt.setInt(4, tenantId); + stmt.executeUpdate(); + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while setting the status of device enrolment", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + return addDeviceStatus(currentOwner, status, tenantId); + } else { + return false; + } + } + + @Override + public boolean setStatus(int enrolmentID, EnrolmentInfo.Status status, int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + Timestamp updateTime = new Timestamp(new Date().getTime()); + try { + conn = this.getConnection(); + String sql = "UPDATE DM_ENROLMENT SET STATUS = ?, DATE_OF_LAST_UPDATE = ? WHERE ID = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setString(1, status.toString()); + stmt.setTimestamp(2, updateTime); + stmt.setInt(3, enrolmentID); + stmt.setInt(4, tenantId); + int updatedRowCount = stmt.executeUpdate(); + if (updatedRowCount != 1){ + throw new DeviceManagementDAOException("Error occurred while setting the status of device enrolment: "+ + updatedRowCount + " rows were updated instead of one row!!!"); + } + // save the device status history + addDeviceStatus(enrolmentID, status); + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while setting the status of device enrolment", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + return true; + } + + private boolean addDeviceStatus(EnrolmentInfo config) throws DeviceManagementDAOException { + return addDeviceStatus(config.getId(), config.getStatus()); + } + + private boolean addDeviceStatus(String currentOwner, EnrolmentInfo.Status status, int tenantId) throws DeviceManagementDAOException { + Connection conn; + String changedBy = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + if (changedBy == null){ + changedBy = DeviceManagementConstants.MaintenanceProperties.MAINTENANCE_USER; + } + PreparedStatement stmt = null; + ResultSet rs = null; + List enrolmentInfoList = new ArrayList<>(); + try { + conn = this.getConnection(); + String sql = "SELECT ID, DEVICE_ID, OWNER, OWNERSHIP, STATUS, IS_TRANSFERRED, DATE_OF_ENROLMENT, " + + "DATE_OF_LAST_UPDATE, TENANT_ID FROM DM_ENROLMENT WHERE OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setString(1, currentOwner); + stmt.setInt(2, tenantId); + rs = stmt.executeQuery(); + while (rs.next()) { + int enrolmentId = rs.getInt("ID"); + int deviceId = rs.getInt("DEVICE_ID"); + enrolmentInfoList.add(new int[]{enrolmentId, deviceId}); + } + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + Timestamp updateTime = new Timestamp(new Date().getTime()); + sql = "INSERT INTO DM_DEVICE_STATUS (ENROLMENT_ID, DEVICE_ID, STATUS, UPDATE_TIME, CHANGED_BY) VALUES(?, ?, ?, ?, ?)"; + try (PreparedStatement ps = conn.prepareStatement(sql)) { + if (conn.getMetaData().supportsBatchUpdates()) { + for(int[] info: enrolmentInfoList){ + ps.setInt(1, info[0]); + ps.setInt(2, info[1]); + ps.setString(3, status.toString()); + ps.setTimestamp(4, updateTime); + ps.setString(5, changedBy); + ps.addBatch(); + } + int[] batchResult = ps.executeBatch(); + for (int i : batchResult) { + if (i == 0 || i == Statement.SUCCESS_NO_INFO || i == Statement.EXECUTE_FAILED) { + return false; + } + } + } else { + for(int[] info: enrolmentInfoList){ + ps.setInt(1, info[0]); + ps.setInt(2, info[1]); + ps.setString(3, status.toString()); + ps.setTimestamp(4, updateTime); + ps.setString(5, changedBy); + ps.execute(); + } + + } + } + + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the enrolments " + + "information of owner '" + currentOwner + "'", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + return true; + } + + private boolean addDeviceStatus(int enrolmentId, EnrolmentInfo.Status status) throws DeviceManagementDAOException { + Connection conn; + String changedBy = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + if (changedBy == null){ + changedBy = DeviceManagementConstants.MaintenanceProperties.MAINTENANCE_USER; + } + PreparedStatement stmt = null; + try { + conn = this.getConnection(); + // get the device id and last udpated status from the device status table + String sql = "SELECT DEVICE_ID, STATUS FROM DM_DEVICE_STATUS WHERE ENROLMENT_ID = ? ORDER BY UPDATE_TIME DESC LIMIT 1"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, enrolmentId); + ResultSet rs = stmt.executeQuery(); + int deviceId = -1; + EnrolmentInfo.Status previousStatus = null; + if (rs.next()) { + // if there is a record corresponding to the enrolment we save the status and the device id + previousStatus = EnrolmentInfo.Status.valueOf(rs.getString("STATUS")); + deviceId = rs.getInt("DEVICE_ID"); + } + DeviceManagementDAOUtil.cleanupResources(stmt, null); + // if there was no record for the enrolment or the previous status is not the same as the current status + // we'll add a record + if (previousStatus == null || previousStatus != status){ + if (deviceId == -1) { + // we need the device id in order to add a new record, therefore we get it from the enrolment table + sql = "SELECT DEVICE_ID FROM DM_ENROLMENT WHERE ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, enrolmentId); + rs = stmt.executeQuery(); + if (rs.next()) { + deviceId = rs.getInt("DEVICE_ID"); + } else { + // if there were no records corresponding to the enrolment id this is a problem. i.e. enrolment + // id is invalid + throw new DeviceManagementDAOException("Error occurred while setting the status of device enrolment: no record for enrolment id " + enrolmentId); + } + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + + sql = "INSERT INTO DM_DEVICE_STATUS (ENROLMENT_ID, DEVICE_ID, STATUS, UPDATE_TIME, CHANGED_BY) VALUES(?, ?, ?, ?, ?)"; + stmt = conn.prepareStatement(sql); + Timestamp updateTime = new Timestamp(new Date().getTime()); + stmt.setInt(1, enrolmentId); + stmt.setInt(2, deviceId); + stmt.setString(3, status.toString()); + stmt.setTimestamp(4, updateTime); + stmt.setString(5, changedBy); + stmt.execute(); + } else { + // no need to update status since the last recorded status is the same as the current status + } + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while setting the status of device", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + return true; + } + @Override + public EnrolmentInfo.Status getStatus(int deviceId, String currentOwner, + int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + EnrolmentInfo.Status status = null; + try { + conn = this.getConnection(); + String sql = "SELECT STATUS FROM DM_ENROLMENT WHERE DEVICE_ID = ? AND OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + stmt.setString(2, currentOwner); + stmt.setInt(3, tenantId); + rs = stmt.executeQuery(); + if (rs.next()) { + status = EnrolmentInfo.Status.valueOf(rs.getString("STATUS")); + } + return status; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while setting the status of device enrolment", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public EnrolmentInfo getEnrollment(int deviceId, String currentOwner, + int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + EnrolmentInfo enrolmentInfo = null; + try { + conn = this.getConnection(); + String sql = "SELECT ID, DEVICE_ID, OWNER, OWNERSHIP, STATUS, IS_TRANSFERRED, DATE_OF_ENROLMENT, " + + "DATE_OF_LAST_UPDATE, TENANT_ID FROM DM_ENROLMENT WHERE DEVICE_ID = ? AND OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + stmt.setString(2, currentOwner); + stmt.setInt(3, tenantId); + rs = stmt.executeQuery(); + if (rs.next()) { + enrolmentInfo = this.loadEnrolment(rs); + } + return enrolmentInfo; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the enrolment " + + "information of user '" + currentOwner + "' upon device '" + deviceId + "'", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public EnrolmentInfo getEnrollment(int deviceId, int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + EnrolmentInfo enrolmentInfo = null; + try { + conn = this.getConnection(); + String sql = "SELECT ID, DEVICE_ID, OWNER, OWNERSHIP, STATUS, IS_TRANSFERRED, DATE_OF_ENROLMENT, " + + "DATE_OF_LAST_UPDATE, TENANT_ID FROM DM_ENROLMENT WHERE DEVICE_ID = ? AND TENANT_ID = ? " + + "ORDER BY DATE_OF_LAST_UPDATE DESC"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + stmt.setInt(2, tenantId); + rs = stmt.executeQuery(); + if (rs.next()) { + enrolmentInfo = this.loadEnrolment(rs); + } + return enrolmentInfo; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the enrolment " + + "information of device '" + deviceId + "'", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public List getEnrollmentsOfUser(int deviceId, String user, int tenantId) + throws DeviceManagementDAOException { + List enrolmentInfos = new ArrayList<>(); + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + EnrolmentInfo enrolmentInfo = null; + try { + conn = this.getConnection(); + String sql = "SELECT ID, DEVICE_ID, OWNER, OWNERSHIP, STATUS, IS_TRANSFERRED, DATE_OF_ENROLMENT, " + + "DATE_OF_LAST_UPDATE, TENANT_ID FROM DM_ENROLMENT WHERE DEVICE_ID = ? AND OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + stmt.setString(2, user); + stmt.setInt(3, tenantId); + rs = stmt.executeQuery(); + while (rs.next()) { + enrolmentInfo = this.loadEnrolment(rs); + enrolmentInfos.add(enrolmentInfo); + } + return enrolmentInfos; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the enrolments " + + "information of user '" + user + "' upon device '" + deviceId + "'", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public boolean updateOwnerOfEnrollment(List devices, String owner, int tenantId) + throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + boolean updateStatus = true; + String sql = "UPDATE DM_ENROLMENT " + + "SET OWNER = ?, IS_TRANSFERRED = ?, DATE_OF_LAST_UPDATE = ? " + + "WHERE ID = ? AND TENANT_ID = ?"; + try (PreparedStatement ps = conn.prepareStatement(sql)) { + if (conn.getMetaData().supportsBatchUpdates()) { + for (Device device : devices) { + ps.setString(1, owner); + ps.setBoolean(2, device.getEnrolmentInfo().isTransferred()); + ps.setTimestamp(3, new Timestamp(new Date().getTime())); + ps.setInt(4, device.getEnrolmentInfo().getId()); + ps.setInt(5, tenantId); + ps.addBatch(); + } + int[] batchResult = ps.executeBatch(); + for (int i : batchResult) { + if (i == 0 || i == Statement.SUCCESS_NO_INFO || i == Statement.EXECUTE_FAILED) { + updateStatus = false; + break; + } + } + } else { + for (Device device : devices) { + ps.setString(1, owner); + ps.setBoolean(2, device.getEnrolmentInfo().isTransferred()); + ps.setInt(3, device.getId()); + ps.setInt(4, tenantId); + if (ps.executeUpdate() == 0) { + updateStatus = false; + break; + } + } + } + } + return updateStatus; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while obtaining the DB connection to update the " + + "owner of the device enrollment.", e); + } + } + + private Connection getConnection() throws SQLException { + return DeviceManagementDAOFactory.getConnection(); + } + + private EnrolmentInfo loadEnrolment(ResultSet rs) throws SQLException { + EnrolmentInfo enrolmentInfo = new EnrolmentInfo(); + enrolmentInfo.setOwner(rs.getString("OWNER")); + enrolmentInfo.setOwnership(EnrolmentInfo.OwnerShip.valueOf(rs.getString("OWNERSHIP"))); + enrolmentInfo.setTransferred(rs.getBoolean("IS_TRANSFERRED")); + enrolmentInfo.setDateOfEnrolment(rs.getTimestamp("DATE_OF_ENROLMENT").getTime()); + enrolmentInfo.setDateOfLastUpdate(rs.getTimestamp("DATE_OF_LAST_UPDATE").getTime()); + enrolmentInfo.setStatus(EnrolmentInfo.Status.valueOf(rs.getString("STATUS"))); + enrolmentInfo.setId(rs.getInt("ID")); + return enrolmentInfo; + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/enrolment/SQLServerEnrollmentDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/enrolment/SQLServerEnrollmentDAOImpl.java new file mode 100644 index 0000000000..8041d07a59 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/enrolment/SQLServerEnrollmentDAOImpl.java @@ -0,0 +1,554 @@ +/* + * Copyright (c) 2023, 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.dao.impl.enrolment; + +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; +import org.wso2.carbon.device.mgt.common.EnrolmentInfo; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.dao.impl.AbstractEnrollmentDAOImpl; +import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil; +import java.sql.*; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class SQLServerEnrollmentDAOImpl extends AbstractEnrollmentDAOImpl { + + @Override + public EnrolmentInfo addEnrollment(int deviceId, EnrolmentInfo enrolmentInfo, + int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + String sql = "INSERT INTO DM_ENROLMENT(DEVICE_ID, OWNER, OWNERSHIP, STATUS, " + + "DATE_OF_ENROLMENT, DATE_OF_LAST_UPDATE, TENANT_ID) VALUES(?, ?, ?, ?, ?, ?, ?)"; + stmt = conn.prepareStatement(sql, new String[] {"id"}); + Timestamp enrollmentTime = new Timestamp(new Date().getTime()); + stmt.setInt(1, deviceId); + stmt.setString(2, enrolmentInfo.getOwner()); + stmt.setString(3, enrolmentInfo.getOwnership().toString()); + stmt.setString(4, enrolmentInfo.getStatus().toString()); + stmt.setTimestamp(5, enrollmentTime); + stmt.setTimestamp(6, enrollmentTime); + stmt.setInt(7, tenantId); + stmt.execute(); + + rs = stmt.getGeneratedKeys(); + if (rs.next()) { + int enrolmentId = rs.getInt(1); + enrolmentInfo.setId(enrolmentId); + enrolmentInfo.setDateOfEnrolment(enrollmentTime.getTime()); + enrolmentInfo.setDateOfLastUpdate(enrollmentTime.getTime()); + addDeviceStatus(enrolmentId, enrolmentInfo.getStatus()); + return enrolmentInfo; + } + return null; + } catch (SQLException e) { + e.printStackTrace(); + throw new DeviceManagementDAOException("Error occurred while adding enrolment configuration", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public int updateEnrollment(EnrolmentInfo enrolmentInfo, int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + String sql = "UPDATE DM_ENROLMENT SET OWNERSHIP = ?, STATUS = ?, DATE_OF_LAST_UPDATE = ? " + + "WHERE ID = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setString(1, enrolmentInfo.getOwnership().toString()); + stmt.setString(2, enrolmentInfo.getStatus().toString()); + stmt.setTimestamp(3, new Timestamp(new Date().getTime())); + stmt.setInt(4, enrolmentInfo.getId()); + stmt.setInt(5, tenantId); + int updatedCount = stmt.executeUpdate(); + if (updatedCount == 1){ + addDeviceStatus(enrolmentInfo.getId(), enrolmentInfo.getStatus()); + } + return updatedCount; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while updating enrolment configuration", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public boolean updateEnrollmentStatus(List enrolmentInfos) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + boolean status = false; + int updateStatus = -1; + try { + conn = this.getConnection(); + String sql = "UPDATE DM_ENROLMENT SET STATUS = ? WHERE ID = ?"; + stmt = conn.prepareStatement(sql); + if (conn.getMetaData().supportsBatchUpdates()) { + for (EnrolmentInfo enrolmentInfo : enrolmentInfos) { + stmt.setString(1, enrolmentInfo.getStatus().toString()); + stmt.setInt(2, enrolmentInfo.getId()); + stmt.addBatch(); + } + updateStatus = stmt.executeBatch().length; + } else { + for (EnrolmentInfo enrolmentInfo : enrolmentInfos) { + stmt.setString(1, enrolmentInfo.getStatus().toString()); + stmt.setInt(2, enrolmentInfo.getId()); + updateStatus = stmt.executeUpdate(); + } + } + if (updateStatus > 0) { + status = true; + for (EnrolmentInfo enrolmentInfo : enrolmentInfos) { + addDeviceStatus(enrolmentInfo); + } + } + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while updating enrolment status of given device-list.", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + return status; + } + + @Override + public int removeEnrollment(int deviceId, String currentOwner, + int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + int status = -1; + try { + conn = this.getConnection(); + String sql = "DELETE FROM DM_ENROLMENT WHERE DEVICE_ID = ? AND OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql, new String[] {"id"}); + stmt.setInt(1, deviceId); + stmt.setString(2, currentOwner); + stmt.setInt(3, tenantId); + stmt.executeUpdate(); + + rs = stmt.getGeneratedKeys(); + if (rs.next()) { + status = 1; + } + return status; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while removing device enrolment", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + private int getCountOfDevicesOfOwner(String owner, int tenantID) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + int count = 0; + try { + conn = this.getConnection(); + String checkQuery = "SELECT COUNT(ID) AS COUNT FROM DM_ENROLMENT WHERE OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(checkQuery); + stmt.setString(1, owner); + stmt.setInt(2, tenantID); + rs = stmt.executeQuery(); + if(rs.next()){ + count = rs.getInt("COUNT"); + } + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while trying to get device " + + "count of Owner : "+owner, e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + return count; + } + + @Override + public boolean setStatus(String currentOwner, EnrolmentInfo.Status status, + int tenantId) throws DeviceManagementDAOException { + return setStatusAllDevices(currentOwner, status, tenantId); + } + + @Override + public boolean setStatusAllDevices(String currentOwner, EnrolmentInfo.Status status, int tenantId) + throws DeviceManagementDAOException{ + Connection conn; + PreparedStatement stmt = null; + Timestamp updateTime = new Timestamp(new Date().getTime()); + if(getCountOfDevicesOfOwner(currentOwner, tenantId) > 0){ + try { + conn = this.getConnection(); + String sql = "UPDATE DM_ENROLMENT SET STATUS = ?, DATE_OF_LAST_UPDATE = ? WHERE OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setString(1, status.toString()); + stmt.setTimestamp(2, updateTime); + stmt.setString(3, currentOwner); + stmt.setInt(4, tenantId); + stmt.executeUpdate(); + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while setting the status of device enrolment", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + return addDeviceStatus(currentOwner, status, tenantId); + } else { + return false; + } + } + + @Override + public boolean setStatus(int enrolmentID, EnrolmentInfo.Status status, int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + Timestamp updateTime = new Timestamp(new Date().getTime()); + try { + conn = this.getConnection(); + String sql = "UPDATE DM_ENROLMENT SET STATUS = ?, DATE_OF_LAST_UPDATE = ? WHERE ID = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setString(1, status.toString()); + stmt.setTimestamp(2, updateTime); + stmt.setInt(3, enrolmentID); + stmt.setInt(4, tenantId); + int updatedRowCount = stmt.executeUpdate(); + if (updatedRowCount != 1){ + throw new DeviceManagementDAOException("Error occurred while setting the status of device enrolment: "+ + updatedRowCount + " rows were updated instead of one row!!!"); + } + // save the device status history + addDeviceStatus(enrolmentID, status); + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while setting the status of device enrolment", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + return true; + } + + private boolean addDeviceStatus(EnrolmentInfo config) throws DeviceManagementDAOException { + return addDeviceStatus(config.getId(), config.getStatus()); + } + + private boolean addDeviceStatus(String currentOwner, EnrolmentInfo.Status status, int tenantId) throws DeviceManagementDAOException { + Connection conn; + String changedBy = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + if (changedBy == null){ + changedBy = DeviceManagementConstants.MaintenanceProperties.MAINTENANCE_USER; + } + PreparedStatement stmt = null; + ResultSet rs = null; + List enrolmentInfoList = new ArrayList<>(); + try { + conn = this.getConnection(); + String sql = "SELECT ID, DEVICE_ID, OWNER, OWNERSHIP, STATUS, IS_TRANSFERRED, DATE_OF_ENROLMENT, " + + "DATE_OF_LAST_UPDATE, TENANT_ID FROM DM_ENROLMENT WHERE OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setString(1, currentOwner); + stmt.setInt(2, tenantId); + rs = stmt.executeQuery(); + while (rs.next()) { + int enrolmentId = rs.getInt("ID"); + int deviceId = rs.getInt("DEVICE_ID"); + enrolmentInfoList.add(new int[]{enrolmentId, deviceId}); + } + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + Timestamp updateTime = new Timestamp(new Date().getTime()); + sql = "INSERT INTO DM_DEVICE_STATUS (ENROLMENT_ID, DEVICE_ID, STATUS, UPDATE_TIME, CHANGED_BY) VALUES(?, ?, ?, ?, ?)"; + try (PreparedStatement ps = conn.prepareStatement(sql)) { + if (conn.getMetaData().supportsBatchUpdates()) { + for(int[] info: enrolmentInfoList){ + ps.setInt(1, info[0]); + ps.setInt(2, info[1]); + ps.setString(3, status.toString()); + ps.setTimestamp(4, updateTime); + ps.setString(5, changedBy); + ps.addBatch(); + } + int[] batchResult = ps.executeBatch(); + for (int i : batchResult) { + if (i == 0 || i == Statement.SUCCESS_NO_INFO || i == Statement.EXECUTE_FAILED) { + return false; + } + } + } else { + for(int[] info: enrolmentInfoList){ + ps.setInt(1, info[0]); + ps.setInt(2, info[1]); + ps.setString(3, status.toString()); + ps.setTimestamp(4, updateTime); + ps.setString(5, changedBy); + ps.execute(); + } + + } + } + + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the enrolments " + + "information of owner '" + currentOwner + "'", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + return true; + } + + private boolean addDeviceStatus(int enrolmentId, EnrolmentInfo.Status status) throws DeviceManagementDAOException { + Connection conn; + String changedBy = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + if (changedBy == null){ + changedBy = DeviceManagementConstants.MaintenanceProperties.MAINTENANCE_USER; + } + PreparedStatement stmt = null; + try { + conn = this.getConnection(); + // get the device id and last udpated status from the device status table + String sql = "SELECT TOP 1 DEVICE_ID, STATUS FROM DM_DEVICE_STATUS WHERE ENROLMENT_ID = ? ORDER BY UPDATE_TIME DESC"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, enrolmentId); + ResultSet rs = stmt.executeQuery(); + int deviceId = -1; + EnrolmentInfo.Status previousStatus = null; + if (rs.next()) { + // if there is a record corresponding to the enrolment we save the status and the device id + previousStatus = EnrolmentInfo.Status.valueOf(rs.getString("STATUS")); + deviceId = rs.getInt("DEVICE_ID"); + } + DeviceManagementDAOUtil.cleanupResources(stmt, null); + // if there was no record for the enrolment or the previous status is not the same as the current status + // we'll add a record + if (previousStatus == null || previousStatus != status){ + if (deviceId == -1) { + // we need the device id in order to add a new record, therefore we get it from the enrolment table + sql = "SELECT DEVICE_ID FROM DM_ENROLMENT WHERE ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, enrolmentId); + rs = stmt.executeQuery(); + if (rs.next()) { + deviceId = rs.getInt("DEVICE_ID"); + } else { + // if there were no records corresponding to the enrolment id this is a problem. i.e. enrolment + // id is invalid + throw new DeviceManagementDAOException("Error occurred while setting the status of device enrolment: no record for enrolment id " + enrolmentId); + } + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + + sql = "INSERT INTO DM_DEVICE_STATUS (ENROLMENT_ID, DEVICE_ID, STATUS, UPDATE_TIME, CHANGED_BY) VALUES(?, ?, ?, ?, ?)"; + stmt = conn.prepareStatement(sql); + Timestamp updateTime = new Timestamp(new Date().getTime()); + stmt.setInt(1, enrolmentId); + stmt.setInt(2, deviceId); + stmt.setString(3, status.toString()); + stmt.setTimestamp(4, updateTime); + stmt.setString(5, changedBy); + stmt.execute(); + } else { + // no need to update status since the last recorded status is the same as the current status + } + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while setting the status of device", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + return true; + } + @Override + public EnrolmentInfo.Status getStatus(int deviceId, String currentOwner, + int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + EnrolmentInfo.Status status = null; + try { + conn = this.getConnection(); + String sql = "SELECT STATUS FROM DM_ENROLMENT WHERE DEVICE_ID = ? AND OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + stmt.setString(2, currentOwner); + stmt.setInt(3, tenantId); + rs = stmt.executeQuery(); + if (rs.next()) { + status = EnrolmentInfo.Status.valueOf(rs.getString("STATUS")); + } + return status; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while setting the status of device enrolment", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public EnrolmentInfo getEnrollment(int deviceId, String currentOwner, + int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + EnrolmentInfo enrolmentInfo = null; + try { + conn = this.getConnection(); + String sql = "SELECT ID, DEVICE_ID, OWNER, OWNERSHIP, STATUS, IS_TRANSFERRED, DATE_OF_ENROLMENT, " + + "DATE_OF_LAST_UPDATE, TENANT_ID FROM DM_ENROLMENT WHERE DEVICE_ID = ? AND OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + stmt.setString(2, currentOwner); + stmt.setInt(3, tenantId); + rs = stmt.executeQuery(); + if (rs.next()) { + enrolmentInfo = this.loadEnrolment(rs); + } + return enrolmentInfo; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the enrolment " + + "information of user '" + currentOwner + "' upon device '" + deviceId + "'", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public EnrolmentInfo getEnrollment(int deviceId, int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + EnrolmentInfo enrolmentInfo = null; + try { + conn = this.getConnection(); + String sql = "SELECT ID, DEVICE_ID, OWNER, OWNERSHIP, STATUS, IS_TRANSFERRED, DATE_OF_ENROLMENT, " + + "DATE_OF_LAST_UPDATE, TENANT_ID FROM DM_ENROLMENT WHERE DEVICE_ID = ? AND TENANT_ID = ? " + + "ORDER BY DATE_OF_LAST_UPDATE DESC"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + stmt.setInt(2, tenantId); + rs = stmt.executeQuery(); + if (rs.next()) { + enrolmentInfo = this.loadEnrolment(rs); + } + return enrolmentInfo; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the enrolment " + + "information of device '" + deviceId + "'", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public List getEnrollmentsOfUser(int deviceId, String user, int tenantId) + throws DeviceManagementDAOException { + List enrolmentInfos = new ArrayList<>(); + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + EnrolmentInfo enrolmentInfo = null; + try { + conn = this.getConnection(); + String sql = "SELECT ID, DEVICE_ID, OWNER, OWNERSHIP, STATUS, IS_TRANSFERRED, DATE_OF_ENROLMENT, " + + "DATE_OF_LAST_UPDATE, TENANT_ID FROM DM_ENROLMENT WHERE DEVICE_ID = ? AND OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + stmt.setString(2, user); + stmt.setInt(3, tenantId); + rs = stmt.executeQuery(); + while (rs.next()) { + enrolmentInfo = this.loadEnrolment(rs); + enrolmentInfos.add(enrolmentInfo); + } + return enrolmentInfos; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the enrolments " + + "information of user '" + user + "' upon device '" + deviceId + "'", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public boolean updateOwnerOfEnrollment(List devices, String owner, int tenantId) + throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + boolean updateStatus = true; + String sql = "UPDATE DM_ENROLMENT " + + "SET OWNER = ?, IS_TRANSFERRED = ?, DATE_OF_LAST_UPDATE = ? " + + "WHERE ID = ? AND TENANT_ID = ?"; + try (PreparedStatement ps = conn.prepareStatement(sql)) { + if (conn.getMetaData().supportsBatchUpdates()) { + for (Device device : devices) { + ps.setString(1, owner); + ps.setBoolean(2, device.getEnrolmentInfo().isTransferred()); + ps.setTimestamp(3, new Timestamp(new Date().getTime())); + ps.setInt(4, device.getEnrolmentInfo().getId()); + ps.setInt(5, tenantId); + ps.addBatch(); + } + int[] batchResult = ps.executeBatch(); + for (int i : batchResult) { + if (i == 0 || i == Statement.SUCCESS_NO_INFO || i == Statement.EXECUTE_FAILED) { + updateStatus = false; + break; + } + } + } else { + for (Device device : devices) { + ps.setString(1, owner); + ps.setBoolean(2, device.getEnrolmentInfo().isTransferred()); + ps.setInt(3, device.getId()); + ps.setInt(4, tenantId); + if (ps.executeUpdate() == 0) { + updateStatus = false; + break; + } + } + } + } + return updateStatus; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while obtaining the DB connection to update the " + + "owner of the device enrollment.", e); + } + } + + private Connection getConnection() throws SQLException { + return DeviceManagementDAOFactory.getConnection(); + } + + private EnrolmentInfo loadEnrolment(ResultSet rs) throws SQLException { + EnrolmentInfo enrolmentInfo = new EnrolmentInfo(); + enrolmentInfo.setOwner(rs.getString("OWNER")); + enrolmentInfo.setOwnership(EnrolmentInfo.OwnerShip.valueOf(rs.getString("OWNERSHIP"))); + enrolmentInfo.setTransferred(rs.getBoolean("IS_TRANSFERRED")); + enrolmentInfo.setDateOfEnrolment(rs.getTimestamp("DATE_OF_ENROLMENT").getTime()); + enrolmentInfo.setDateOfLastUpdate(rs.getTimestamp("DATE_OF_LAST_UPDATE").getTime()); + enrolmentInfo.setStatus(EnrolmentInfo.Status.valueOf(rs.getString("STATUS"))); + enrolmentInfo.setId(rs.getInt("ID")); + return enrolmentInfo; + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/geofence/GenericGeofenceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/geofence/GenericGeofenceDAOImpl.java new file mode 100644 index 0000000000..b7784a3480 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/geofence/GenericGeofenceDAOImpl.java @@ -0,0 +1,637 @@ +/* + * Copyright (c) 2020, 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.dao.impl.geofence; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; +import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.event.config.EventConfig; +import org.wso2.carbon.device.mgt.common.geo.service.GeofenceData; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; +import org.wso2.carbon.device.mgt.core.dao.EventManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.dao.GeofenceDAO; +import org.wso2.carbon.device.mgt.core.dao.impl.AbstractGeofenceDAOImpl; +import org.wso2.carbon.device.mgt.core.dto.event.config.GeoFenceGroupMap; + +import java.sql.*; +import java.util.Date; +import java.util.*; + +public class GenericGeofenceDAOImpl extends AbstractGeofenceDAOImpl { + private static final Log log = LogFactory.getLog(GenericGeofenceDAOImpl.class); + @Override + public GeofenceData saveGeofence(GeofenceData geofenceData) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "INSERT INTO DM_GEOFENCE(" + + "FENCE_NAME, " + + "DESCRIPTION, " + + "LATITUDE, " + + "LONGITUDE, " + + "RADIUS, " + + "GEO_JSON, " + + "FENCE_SHAPE, " + + "CREATED_TIMESTAMP, " + + "OWNER, " + + "TENANT_ID) " + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setString(1, geofenceData.getFenceName()); + stmt.setString(2, geofenceData.getDescription()); + stmt.setDouble(3, geofenceData.getLatitude()); + stmt.setDouble(4, geofenceData.getLongitude()); + stmt.setFloat(5, geofenceData.getRadius()); + stmt.setString(6, geofenceData.getGeoJson()); + stmt.setString(7, geofenceData.getFenceShape()); + stmt.setTimestamp(8, new Timestamp(new Date().getTime())); + stmt.setString(9, geofenceData.getOwner()); + stmt.setInt(10, geofenceData.getTenantId()); + if (stmt.executeUpdate() > 0) { + ResultSet generatedKeys = stmt.getGeneratedKeys(); + if (generatedKeys.next()) { + geofenceData.setId(generatedKeys.getInt(1)); + } + } + return geofenceData; + } + } catch (SQLException e) { + String msg = "Error occurred while creating Geofence for the tenant id "+geofenceData.getTenantId(); + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public GeofenceData getGeofence(int fenceId) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + GeofenceData geofenceData = null; + String sql = "SELECT " + + "ID, " + + "FENCE_NAME, " + + "DESCRIPTION, " + + "LATITUDE, " + + "LONGITUDE, " + + "RADIUS, " + + "GEO_JSON, " + + "FENCE_SHAPE, " + + "OWNER, " + + "TENANT_ID " + + "FROM DM_GEOFENCE " + + "WHERE ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, fenceId); + try (ResultSet rst = stmt.executeQuery()) { + List geofenceDataList = extractGeofenceData(rst); + if (!geofenceDataList.isEmpty()) { + geofenceData = geofenceDataList.get(0); + } + } + } + return geofenceData; + } catch (SQLException e) { + String msg = "Error occurred while retrieving Geofence with id "+fenceId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public List getGeoFencesOfTenant(PaginationRequest request, int tenantId) + throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + boolean isNameProvided = false; + List geofenceData; + String sql = "SELECT " + + "ID, " + + "FENCE_NAME, " + + "DESCRIPTION, " + + "LATITUDE, " + + "LONGITUDE, " + + "RADIUS, " + + "GEO_JSON, " + + "FENCE_SHAPE, " + + "OWNER, " + + "TENANT_ID " + + "FROM DM_GEOFENCE " + + "WHERE TENANT_ID = ? "; + + if (request.getProperty(DeviceManagementConstants.GeoServices.FENCE_NAME) != null) { + sql += "AND FENCE_NAME LIKE ?"; + isNameProvided = true; + } + sql += "LIMIT ? OFFSET ?"; + int index = 1; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(index++, tenantId); + if (isNameProvided) { + stmt.setString(index++, request.getProperty(DeviceManagementConstants.GeoServices.FENCE_NAME).toString() + "%"); + } + stmt.setInt(index++, request.getRowCount()); + stmt.setInt(index, request.getStartIndex()); + try (ResultSet rst = stmt.executeQuery()) { + geofenceData = extractGeofenceData(rst); + } + } + return geofenceData; + } catch (SQLException e) { + String msg = "Error occurred while retrieving Geofence of the tenant " + tenantId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public List getGeoFencesOfTenant(String fenceName, int tenantId) + throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + List geofenceData; + String sql = "SELECT " + + "ID, " + + "FENCE_NAME, " + + "DESCRIPTION, " + + "LATITUDE, " + + "LONGITUDE, " + + "RADIUS, " + + "GEO_JSON, " + + "FENCE_SHAPE, " + + "OWNER, " + + "TENANT_ID " + + "FROM DM_GEOFENCE " + + "WHERE FENCE_NAME LIKE ?" + + "AND TENANT_ID = ? "; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setString(1, fenceName + "%"); + stmt.setInt(2, tenantId); + try (ResultSet rst = stmt.executeQuery()) { + geofenceData = extractGeofenceData(rst); + } + } + return geofenceData; + } catch (SQLException e) { + String msg = "Error occurred while retrieving Geofence of the tenant " + tenantId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public List getGeoFencesOfTenant(int tenantId) + throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + List geofenceData; + String sql = "SELECT " + + "ID, " + + "FENCE_NAME, " + + "DESCRIPTION, " + + "LATITUDE, " + + "LONGITUDE, " + + "RADIUS, " + + "GEO_JSON, " + + "FENCE_SHAPE, " + + "OWNER, " + + "TENANT_ID " + + "FROM DM_GEOFENCE " + + "WHERE TENANT_ID = ? "; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, tenantId); + try (ResultSet rst = stmt.executeQuery()) { + geofenceData = extractGeofenceData(rst); + } + } + return geofenceData; + } catch (SQLException e) { + String msg = "Error occurred while retrieving Geofence of the tenant " + tenantId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public int deleteGeofenceById(int fenceId) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "DELETE FROM DM_GEOFENCE WHERE ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, fenceId); + return stmt.executeUpdate(); + } + } catch (SQLException e) { + String msg = "Error occurred while deleting Geofence with ID " + fenceId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public int updateGeofence(GeofenceData geofenceData, int fenceId) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "UPDATE DM_GEOFENCE SET " + + "FENCE_NAME = ?, " + + "DESCRIPTION = ?, " + + "LATITUDE = ?, " + + "LONGITUDE = ?, " + + "RADIUS = ?, " + + "GEO_JSON = ?, " + + "FENCE_SHAPE = ? " + + "WHERE ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setString(1, geofenceData.getFenceName()); + stmt.setString(2, geofenceData.getDescription()); + stmt.setDouble(3, geofenceData.getLatitude()); + stmt.setDouble(4, geofenceData.getLongitude()); + stmt.setFloat(5, geofenceData.getRadius()); + stmt.setString(6, geofenceData.getGeoJson()); + stmt.setString(7, geofenceData.getFenceShape()); + stmt.setInt(8, fenceId); + return stmt.executeUpdate(); + } + } catch (SQLException e) { + String msg = "Error occurred while updating Geofence record with id " + fenceId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public boolean createGeofenceGroupMapping(GeofenceData geofenceData, List groupIds) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "INSERT INTO DM_GEOFENCE_GROUP_MAPPING(" + + "FENCE_ID, " + + "GROUP_ID) " + + "VALUES (?, ?)"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (Integer groupId : groupIds) { + stmt.setInt(1, geofenceData.getId()); + stmt.setInt(2, groupId); + stmt.addBatch(); + } + return stmt.executeBatch().length > 0; + } + } catch (SQLException e) { + String msg = "Error occurred while creating geofence group mapping records"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + private Connection getConnection() throws SQLException { + return EventManagementDAOFactory.getConnection(); + } + + private List extractGeofenceData(ResultSet rst) throws SQLException { + List geofenceDataList = new ArrayList<>(); + while (rst.next()) { + GeofenceData geofenceData = new GeofenceData(); + geofenceData.setId(rst.getInt("ID")); + geofenceData.setFenceName(rst.getString("FENCE_NAME")); + geofenceData.setDescription(rst.getString("DESCRIPTION")); + geofenceData.setLatitude(rst.getDouble("LATITUDE")); + geofenceData.setLongitude(rst.getDouble("LONGITUDE")); + geofenceData.setRadius(rst.getFloat("RADIUS")); + geofenceData.setGeoJson(rst.getString("GEO_JSON")); + geofenceData.setFenceShape(rst.getString("FENCE_SHAPE")); + geofenceData.setOwner(rst.getString("OWNER")); + geofenceData.setTenantId(rst.getInt("TENANT_ID")); + geofenceDataList.add(geofenceData); + } + return geofenceDataList; + } + + @Override + public List getGroupIdsOfGeoFence(int fenceId) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "SELECT " + + "GROUP_ID " + + "FROM DM_GEOFENCE_GROUP_MAPPING " + + "WHERE FENCE_ID = ? "; + List groupIds = new ArrayList<>(); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, fenceId); + try (ResultSet rst = stmt.executeQuery()) { + while (rst.next()) { + groupIds.add(rst.getInt(1)); + } + } + } + return groupIds; + } catch (SQLException e) { + String msg = "Error occurred while fetching group IDs of the fence " + fenceId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public void deleteGeofenceGroupMapping(List groupIdsToDelete, int fenceId) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "DELETE FROM DM_GEOFENCE_GROUP_MAPPING WHERE GROUP_ID = ? AND FENCE_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (Integer groupId : groupIdsToDelete) { + stmt.setInt(1, groupId); + stmt.setInt(2, fenceId); + stmt.addBatch(); + } + stmt.executeBatch(); + } + } catch (SQLException e) { + String msg = "Error occurred while deleting Geofence group mapping records"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public void createGeofenceEventMapping(int fenceId, List eventIds) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "INSERT INTO DM_GEOFENCE_EVENT_MAPPING(" + + "FENCE_ID, "+ + "EVENT_ID) " + + "VALUES (?, ?)"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (Integer createdEventId : eventIds) { + stmt.setInt(1, fenceId); + stmt.setInt(2, createdEventId); + stmt.addBatch(); + } + stmt.executeBatch(); + } + } catch (SQLException e) { + String msg = "Error occurred while creating geofence event group mapping records"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public void deleteGeofenceEventMapping(List removedEventIdList) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "DELETE FROM DM_GEOFENCE_EVENT_MAPPING WHERE EVENT_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (Integer eventId : removedEventIdList) { + stmt.setInt(1, eventId); + stmt.addBatch(); + } + stmt.executeBatch(); + } + } catch (SQLException e) { + String msg = "Error occurred while deleting Geofence event mapping records"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public Map> getEventsOfGeoFences(List geofenceIds) throws DeviceManagementDAOException { + try { + Map> geoFenceEventMap = new HashMap<>(); + if (geofenceIds.isEmpty()) { + return geoFenceEventMap; + } + Connection conn = this.getConnection(); + String sql = "SELECT " + + "E.ID AS EVENT_ID, " + + "M.FENCE_ID AS FENCE_ID, " + + "EVENT_SOURCE, " + + "EVENT_LOGIC, " + + "ACTIONS " + + "FROM DM_DEVICE_EVENT E, DM_GEOFENCE_EVENT_MAPPING M " + + "WHERE E.ID = M.EVENT_ID " + + "AND M.FENCE_ID IN (%s)"; + String inClause = String.join(", ", Collections.nCopies(geofenceIds.size(), "?")); + sql = String.format(sql, inClause); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + int index = 1; + for (Integer geofenceId : geofenceIds) { + stmt.setInt(index++, geofenceId); + } + ResultSet resultSet = stmt.executeQuery(); + while (resultSet.next()) { + int fenceId = resultSet.getInt("FENCE_ID"); + List eventConfigList = geoFenceEventMap.get(fenceId); + if (eventConfigList == null) { + eventConfigList = new ArrayList<>(); + } + EventConfig event = new EventConfig(); + event.setEventId(resultSet.getInt("EVENT_ID")); + event.setEventSource(resultSet.getString("EVENT_SOURCE")); + event.setEventLogic(resultSet.getString("EVENT_LOGIC")); + event.setActions(resultSet.getString("ACTIONS")); + eventConfigList.add(event); + geoFenceEventMap.put(fenceId, eventConfigList); + } + return geoFenceEventMap; + } + } catch (SQLException e) { + String msg = "Error occurred while updating Geofence record with id "; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public List getEventsOfGeoFence(int geofenceId) throws DeviceManagementDAOException { + try { + List eventList = new ArrayList<>(); + Connection conn = this.getConnection(); + String sql = "SELECT " + + "E.ID AS EVENT_ID, " + + "EVENT_SOURCE, " + + "EVENT_LOGIC, " + + "ACTIONS " + + "FROM DM_DEVICE_EVENT E, DM_GEOFENCE_EVENT_MAPPING G " + + "WHERE E.ID = G.EVENT_ID " + + "AND G.FENCE_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, geofenceId); + return getEventConfigs(stmt); + } + } catch (SQLException e) { + String msg = "Error occurred while updating Geofence record with id "; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public Set getGroupIdsOfGeoFences(List fenceIds) throws DeviceManagementDAOException { + try { + Set geoFenceGroupSet = new HashSet<>(); + if (fenceIds.isEmpty()) { + return geoFenceGroupSet; + } + Connection conn = this.getConnection(); + String sql = "SELECT " + + "FENCE_ID, " + + "M.GROUP_ID, " + + "G.GROUP_NAME " + + "FROM DM_GEOFENCE_GROUP_MAPPING M, DM_GROUP G " + + "WHERE M.GROUP_ID = G.ID " + + "AND FENCE_ID IN (%s)"; + String inClause = String.join(", ", Collections.nCopies(fenceIds.size(), "?")); + sql = String.format(sql, inClause); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + int index = 1; + for (Integer fenceId : fenceIds) { + stmt.setInt(index++, fenceId); + } + ResultSet rst = stmt.executeQuery(); + while (rst.next()) { + GeoFenceGroupMap geoFenceGroupMap = new GeoFenceGroupMap(); + geoFenceGroupMap.setFenceId(rst.getInt("FENCE_ID")); + geoFenceGroupMap.setGroupId(rst.getInt("GROUP_ID")); + geoFenceGroupMap.setGroupName(rst.getString("GROUP_NAME")); + geoFenceGroupSet.add(geoFenceGroupMap); + } + } + return geoFenceGroupSet; + } catch (SQLException e) { + String msg = "Error occurred while fetching group IDs of the fences"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + /** + * Retrieve the geofence event extracted from the DB + * @param stmt prepared statement to retrieve data from the DB + * @return Retrieved Event list from the DB + * @throws SQLException for the errors occur while accessing the DB + */ + private List getEventConfigs(PreparedStatement stmt) throws SQLException { + List eventList = new ArrayList<>(); + ResultSet resultSet = stmt.executeQuery(); + EventConfig event; + while (resultSet.next()) { + event = new EventConfig(); + event.setEventId(resultSet.getInt("EVENT_ID")); + event.setEventSource(resultSet.getString("EVENT_SOURCE")); + event.setEventLogic(resultSet.getString("EVENT_LOGIC")); + event.setActions(resultSet.getString("ACTIONS")); + eventList.add(event); + } + return eventList; + } + + @Override + public List getGeoFences(int groupId, int tenantId) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "SELECT " + + "G.ID AS FENCE_ID, " + + "FENCE_NAME, " + + "DESCRIPTION, " + + "LATITUDE," + + "LONGITUDE, " + + "RADIUS, " + + "GEO_JSON, " + + "FENCE_SHAPE " + + "FROM DM_GEOFENCE G, DM_GEOFENCE_GROUP_MAPPING M " + + "WHERE M.GROUP_ID = ? AND TENANT_ID = ? " + + "GROUP BY G.ID"; + + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, groupId); + stmt.setInt(2, tenantId); + ResultSet rst = stmt.executeQuery(); + List geofenceDataList = new ArrayList<>(); + while (rst.next()) { + GeofenceData geofenceData = new GeofenceData(); + geofenceData.setId(rst.getInt("FENCE_ID")); + geofenceData.setFenceName(rst.getString("FENCE_NAME")); + geofenceData.setDescription(rst.getString("DESCRIPTION")); + geofenceData.setLatitude(rst.getDouble("LATITUDE")); + geofenceData.setLongitude(rst.getDouble("LONGITUDE")); + geofenceData.setRadius(rst.getFloat("RADIUS")); + geofenceData.setGeoJson(rst.getString("GEO_JSON")); + geofenceData.setFenceShape(rst.getString("FENCE_SHAPE")); + geofenceDataList.add(geofenceData); + } + return geofenceDataList; + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving Geo fences of group " + groupId + + " and tenant " + tenantId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public GeofenceData getGeofence(int fenceId, boolean requireGroupData) throws DeviceManagementDAOException { + if (!requireGroupData) { + return getGeofence(fenceId); + } + + try { + Connection con = this.getConnection(); + String sql = "SELECT " + + "G.ID AS FENCE_ID, " + + "FENCE_NAME, " + + "G.DESCRIPTION, " + + "LATITUDE, " + + "LONGITUDE, " + + "RADIUS, " + + "GEO_JSON, " + + "FENCE_SHAPE, " + + "M.GROUP_ID AS GROUP_ID, " + + "GR.GROUP_NAME " + + "FROM DM_GEOFENCE G, DM_GEOFENCE_GROUP_MAPPING M, DM_GROUP GR " + + "WHERE G.ID = M.FENCE_ID " + + "AND M.GROUP_ID = GR.ID " + + "AND G.ID = ?"; + try (PreparedStatement stmt = con.prepareStatement(sql)){ + stmt.setInt(1, fenceId); + ResultSet rst = stmt.executeQuery(); + Map groupMap = new HashMap<>(); + GeofenceData geofenceData = null; + while (rst.next()) { + groupMap.put(rst.getInt("GROUP_ID"), rst.getString("GROUP_NAME")); + if (rst.isLast()) { + geofenceData = new GeofenceData(); + geofenceData.setId(rst.getInt("FENCE_ID")); + geofenceData.setFenceName(rst.getString("FENCE_NAME")); + geofenceData.setDescription(rst.getString("DESCRIPTION")); + geofenceData.setLatitude(rst.getDouble("LATITUDE")); + geofenceData.setLongitude(rst.getDouble("LONGITUDE")); + geofenceData.setRadius(rst.getFloat("RADIUS")); + geofenceData.setGeoJson(rst.getString("GEO_JSON")); + geofenceData.setFenceShape(rst.getString("FENCE_SHAPE")); + geofenceData.setGroupData(groupMap); + } + } + return geofenceData; + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving Geo fence data " + fenceId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/geofence/SQLServerGeofenceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/geofence/SQLServerGeofenceDAOImpl.java new file mode 100644 index 0000000000..7fe050a477 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/geofence/SQLServerGeofenceDAOImpl.java @@ -0,0 +1,109 @@ +/* + * 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.dao.impl.geofence; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; +import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.event.config.EventConfig; +import org.wso2.carbon.device.mgt.common.geo.service.GeofenceData; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; +import org.wso2.carbon.device.mgt.core.dao.EventManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.dao.GeofenceDAO; +import org.wso2.carbon.device.mgt.core.dao.impl.AbstractGeofenceDAOImpl; +import org.wso2.carbon.device.mgt.core.dto.event.config.GeoFenceGroupMap; + +import java.sql.*; +import java.util.Date; +import java.util.*; + +public class SQLServerGeofenceDAOImpl extends AbstractGeofenceDAOImpl { + private static final Log log = LogFactory.getLog(SQLServerGeofenceDAOImpl.class); + + @Override + public List getGeoFencesOfTenant(PaginationRequest request, int tenantId) + throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + boolean isNameProvided = false; + List geofenceData; + String sql = "SELECT " + + "ID, " + + "FENCE_NAME, " + + "DESCRIPTION, " + + "LATITUDE, " + + "LONGITUDE, " + + "RADIUS, " + + "GEO_JSON, " + + "FENCE_SHAPE, " + + "OWNER, " + + "TENANT_ID " + + "FROM DM_GEOFENCE " + + "WHERE TENANT_ID = ? "; + + if (request.getProperty(DeviceManagementConstants.GeoServices.FENCE_NAME) != null) { + sql += "AND FENCE_NAME LIKE ?"; + isNameProvided = true; + } + sql += "ORDER BY FENCE_NAME "; + sql += "OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; + int index = 1; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(index++, tenantId); + if (isNameProvided) { + stmt.setString(index++, request.getProperty(DeviceManagementConstants.GeoServices.FENCE_NAME).toString() + "%"); + } + stmt.setInt(index++, request.getStartIndex()); + stmt.setInt(index, request.getRowCount()); + try (ResultSet rst = stmt.executeQuery()) { + geofenceData = extractGeofenceData(rst); + } + } + return geofenceData; + } catch (SQLException e) { + String msg = "Error occurred while retrieving Geofence of the tenant " + tenantId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + private Connection getConnection() throws SQLException { + return EventManagementDAOFactory.getConnection(); + } + + private List extractGeofenceData(ResultSet rst) throws SQLException { + List geofenceDataList = new ArrayList<>(); + while (rst.next()) { + GeofenceData geofenceData = new GeofenceData(); + geofenceData.setId(rst.getInt("ID")); + geofenceData.setFenceName(rst.getString("FENCE_NAME")); + geofenceData.setDescription(rst.getString("DESCRIPTION")); + geofenceData.setLatitude(rst.getDouble("LATITUDE")); + geofenceData.setLongitude(rst.getDouble("LONGITUDE")); + geofenceData.setRadius(rst.getFloat("RADIUS")); + geofenceData.setGeoJson(rst.getString("GEO_JSON")); + geofenceData.setFenceShape(rst.getString("FENCE_SHAPE")); + geofenceData.setOwner(rst.getString("OWNER")); + geofenceData.setTenantId(rst.getInt("TENANT_ID")); + geofenceDataList.add(geofenceData); + } + return geofenceDataList; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java index f36def494d..0d24f1125c 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java @@ -86,11 +86,9 @@ import org.wso2.carbon.device.mgt.core.traccar.api.service.DeviceAPIClientServic import org.wso2.carbon.device.mgt.core.traccar.api.service.impl.DeviceAPIClientServiceImpl; import org.wso2.carbon.device.mgt.core.util.DeviceManagementSchemaInitializer; import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil; -import org.wso2.carbon.device.mgt.core.util.DeviceMgtTenantMgtListener; import org.wso2.carbon.email.sender.core.service.EmailSenderService; import org.wso2.carbon.ndatasource.core.DataSourceService; import org.wso2.carbon.registry.core.service.RegistryService; -import org.wso2.carbon.stratos.common.listeners.TenantMgtListener; import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.utils.Axis2ConfigurationContextObserver; import org.wso2.carbon.utils.ConfigurationContextService; @@ -271,9 +269,6 @@ public class DeviceManagementServiceComponent { componentContext.getBundleContext().registerService(PrivacyComplianceProvider.class.getName(), privacyComplianceProvider, null); - componentContext.getBundleContext() - .registerService(TenantMgtListener.class.getName(), new DeviceMgtTenantMgtListener(), null); - if (log.isDebugEnabled()) { log.debug("Device management core bundle has been successfully initialized"); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/dao/DeviceStatusPersistenceTests.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/dao/DeviceStatusPersistenceTests.java index 65c22e1161..b2a8903c7f 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/dao/DeviceStatusPersistenceTests.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/dao/DeviceStatusPersistenceTests.java @@ -39,9 +39,15 @@ import static org.wso2.carbon.device.mgt.common.EnrolmentInfo.Status.*; public class DeviceStatusPersistenceTests extends BaseDeviceManagementTest { private static final Log log = LogFactory.getLog(DeviceStatusPersistenceTests.class); - private EnrollmentDAO enrollmentDAO = DeviceManagementDAOFactory.getEnrollmentDAO(); + EnrollmentDAO enrollmentDAO; private DeviceStatusDAO deviceStatusDAO = DeviceManagementDAOFactory.getDeviceStatusDAO(); + @BeforeClass + @Override + public void init() throws Exception { + enrollmentDAO = DeviceManagementDAOFactory.getEnrollmentDAO(); + } + /** * Validate that the list of statuses received match the statuses * @param device @@ -245,10 +251,4 @@ public class DeviceStatusPersistenceTests extends BaseDeviceManagementTest { } return false; } - - @BeforeClass - @Override - public void init() throws Exception { - - } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/dao/EnrolmentPersistenceTests.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/dao/EnrolmentPersistenceTests.java index 9497324798..10bf0a1b64 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/dao/EnrolmentPersistenceTests.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/dao/EnrolmentPersistenceTests.java @@ -33,7 +33,14 @@ import java.sql.SQLException; public class EnrolmentPersistenceTests extends BaseDeviceManagementTest { private static final Log log = LogFactory.getLog(EnrolmentPersistenceTests.class); - private EnrollmentDAO enrollmentDAO = DeviceManagementDAOFactory.getEnrollmentDAO(); + EnrollmentDAO enrollmentDAO; + + @BeforeClass + @Override + public void init() throws Exception { + this.initDataSource(); + enrollmentDAO = DeviceManagementDAOFactory.getEnrollmentDAO(); + } @Test public void testAddEnrolment() { @@ -86,10 +93,4 @@ public class EnrolmentPersistenceTests extends BaseDeviceManagementTest { } return enrolmentInfo; } - - @BeforeClass - @Override - public void init() throws Exception { - this.initDataSource(); - } } diff --git a/components/tenant-mgt/io.entgra.tenant.mgt.common/pom.xml b/components/tenant-mgt/io.entgra.tenant.mgt.common/pom.xml new file mode 100644 index 0000000000..b69c2bb112 --- /dev/null +++ b/components/tenant-mgt/io.entgra.tenant.mgt.common/pom.xml @@ -0,0 +1,66 @@ + + + + + tenant-mgt + org.wso2.carbon.devicemgt + 5.0.25-SNAPSHOT + ../pom.xml + + + 4.0.0 + io.entgra.tenant.mgt.common + Entgra IoT - Tenant Manager Common + Entgra IoT - Tenant Manager Common + bundle + + + + + org.apache.felix + maven-bundle-plugin + true + + + ${project.artifactId} + ${project.artifactId} + ${carbon.device.mgt.version} + Tenant Management Common Bundle + + org.apache.commons.logging, + org.wso2.carbon.stratos.common.beans + + io.entgra.tenant.mgt.common.* + + + + + + + + + org.wso2.carbon.commons + org.wso2.carbon.tenant.common + ${carbon.commons.version} + + + + \ No newline at end of file diff --git a/components/tenant-mgt/io.entgra.tenant.mgt.common/src/main/java/io/entgra/tenant/mgt/common/exception/TenantMgtException.java b/components/tenant-mgt/io.entgra.tenant.mgt.common/src/main/java/io/entgra/tenant/mgt/common/exception/TenantMgtException.java new file mode 100644 index 0000000000..1470f07f63 --- /dev/null +++ b/components/tenant-mgt/io.entgra.tenant.mgt.common/src/main/java/io/entgra/tenant/mgt/common/exception/TenantMgtException.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) 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.tenant.mgt.common.exception; + +public class TenantMgtException extends Exception { + + private static final long serialVersionUID = 4304028531230841553L; + + public TenantMgtException(String msg, Throwable ex) { + super(msg, ex); + } + + public TenantMgtException(String msg) { + super(msg); + } +} diff --git a/components/tenant-mgt/io.entgra.tenant.mgt.common/src/main/java/io/entgra/tenant/mgt/common/spi/TenantManagerService.java b/components/tenant-mgt/io.entgra.tenant.mgt.common/src/main/java/io/entgra/tenant/mgt/common/spi/TenantManagerService.java new file mode 100644 index 0000000000..472b1b7cb1 --- /dev/null +++ b/components/tenant-mgt/io.entgra.tenant.mgt.common/src/main/java/io/entgra/tenant/mgt/common/spi/TenantManagerService.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) 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.tenant.mgt.common.spi; + +import io.entgra.tenant.mgt.common.exception.TenantMgtException; +import org.wso2.carbon.stratos.common.beans.TenantInfoBean; + +public interface TenantManagerService { + void addDefaultRoles(TenantInfoBean tenantInfoBean) throws TenantMgtException; + + void addDefaultAppCategories(TenantInfoBean tenantInfoBean) throws TenantMgtException; +} \ No newline at end of file diff --git a/components/tenant-mgt/io.entgra.tenant.mgt.core/pom.xml b/components/tenant-mgt/io.entgra.tenant.mgt.core/pom.xml new file mode 100644 index 0000000000..a91e831ed5 --- /dev/null +++ b/components/tenant-mgt/io.entgra.tenant.mgt.core/pom.xml @@ -0,0 +1,136 @@ + + + + + tenant-mgt + org.wso2.carbon.devicemgt + 5.0.25-SNAPSHOT + ../pom.xml + + + 4.0.0 + io.entgra.tenant.mgt.core + Entgra IoT - Tenant Manager Core + Entgra IoT - Tenant Manager Core + bundle + + + + + org.apache.felix + maven-scr-plugin + + + org.apache.felix + maven-bundle-plugin + true + + + ${project.artifactId} + ${project.artifactId} + ${carbon.device.mgt.version} + Tenant Management Core Bundle + io.entgra.tenant.mgt.core.internal + + org.osgi.framework.*;version="${imp.package.version.osgi.framework}", + org.osgi.service.*;version="${imp.package.version.osgi.service}", + org.apache.commons.logging, + io.entgra.application.mgt.common.*, + io.entgra.application.mgt.core.config, + org.wso2.carbon.device.mgt.core, + org.wso2.carbon.user.api, + org.wso2.carbon.registry.core.exceptions, + io.entgra.tenant.mgt.common.*, + org.wso2.carbon.stratos.common.beans, + org.wso2.carbon.stratos.common.exception, + org.wso2.carbon.stratos.common.listeners, + org.wso2.carbon.device.mgt.common.metadata.mgt, + org.wso2.carbon.device.mgt.common.exceptions, + org.wso2.carbon.device.mgt.common.permission.mgt, + org.wso2.carbon.device.mgt.common.roles.config, + org.wso2.carbon.device.mgt.core.metadata.mgt, + org.wso2.carbon.device.mgt.core.config, + org.wso2.carbon.user.core.service, + org.wso2.carbon.context + + + !io.entgra.tenant.mgt.core.internal, + io.entgra.tenant.mgt.core.* + + + + + + + + + + org.eclipse.osgi + org.eclipse.osgi + + + org.eclipse.osgi + org.eclipse.osgi.services + + + org.wso2.carbon.commons + org.wso2.carbon.tenant.common + ${carbon.commons.version} + + + org.wso2.carbon + org.wso2.carbon.registry.core + + + org.wso2.carbon + org.wso2.carbon.user.core + + + org.wso2.carbon + org.wso2.carbon.user.api + + + org.wso2.carbon.devicemgt + org.wso2.carbon.device.mgt.core + + + org.wso2.carbon.devicemgt + org.wso2.carbon.device.mgt.common + + + org.wso2.carbon.devicemgt + io.entgra.application.mgt.core + + + org.wso2.carbon.devicemgt + io.entgra.application.mgt.common + + + org.wso2.carbon.devicemgt + io.entgra.tenant.mgt.common + + + org.wso2.carbon + org.wso2.carbon.utils + + + + \ No newline at end of file diff --git a/components/tenant-mgt/io.entgra.tenant.mgt.core/src/main/java/io/entgra/tenant/mgt/core/TenantManager.java b/components/tenant-mgt/io.entgra.tenant.mgt.core/src/main/java/io/entgra/tenant/mgt/core/TenantManager.java new file mode 100644 index 0000000000..ab9b8b2290 --- /dev/null +++ b/components/tenant-mgt/io.entgra.tenant.mgt.core/src/main/java/io/entgra/tenant/mgt/core/TenantManager.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) 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.tenant.mgt.core; + +import io.entgra.tenant.mgt.common.exception.TenantMgtException; +import org.wso2.carbon.stratos.common.beans.TenantInfoBean; + +public interface TenantManager { + + /** + * Add default roles to a tenant described by the tenant info bean + * @param tenantInfoBean The info bean that provides tenant info + * @throws TenantMgtException Throws when error occurred while adding + * a role into user store or adding default white label theme to created tenant + */ + void addDefaultRoles(TenantInfoBean tenantInfoBean) throws TenantMgtException; + + /** + * Add default application categories to a tenant described by the tenant info bean + * @param tenantInfoBean The info bean that provides tenant info + * @throws TenantMgtException Throws when error occurred while adding default application categories + */ + void addDefaultAppCategories(TenantInfoBean tenantInfoBean) throws TenantMgtException; +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceMgtTenantMgtListener.java b/components/tenant-mgt/io.entgra.tenant.mgt.core/src/main/java/io/entgra/tenant/mgt/core/impl/TenantManagerImpl.java similarity index 56% rename from components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceMgtTenantMgtListener.java rename to components/tenant-mgt/io.entgra.tenant.mgt.core/src/main/java/io/entgra/tenant/mgt/core/impl/TenantManagerImpl.java index 79f58e82a1..4089b4bffa 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceMgtTenantMgtListener.java +++ b/components/tenant-mgt/io.entgra.tenant.mgt.core/src/main/java/io/entgra/tenant/mgt/core/impl/TenantManagerImpl.java @@ -1,11 +1,12 @@ -/* Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. +/* + * Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) All Rights Reserved. * - * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * 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 + * 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 @@ -14,23 +15,26 @@ * specific language governing permissions and limitations * under the License. */ - -package org.wso2.carbon.device.mgt.core.util; - +package io.entgra.tenant.mgt.core.impl; + +import io.entgra.application.mgt.common.exception.ApplicationManagementException; +import io.entgra.application.mgt.core.config.ConfigurationManager; +import io.entgra.application.mgt.common.services.ApplicationManager; +import io.entgra.tenant.mgt.core.TenantManager; +import io.entgra.tenant.mgt.common.exception.TenantMgtException; +import io.entgra.tenant.mgt.core.internal.TenantMgtDataHolder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.context.PrivilegedCarbonContext; -import org.wso2.carbon.device.mgt.common.exceptions.MetadataManagementException; -import org.wso2.carbon.device.mgt.common.permission.mgt.PermissionManagementException; -import org.wso2.carbon.device.mgt.common.roles.config.Role; 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.internal.DeviceManagementDataHolder; import org.wso2.carbon.device.mgt.core.permission.mgt.PermissionUtils; import org.wso2.carbon.registry.core.exceptions.RegistryException; import org.wso2.carbon.stratos.common.beans.TenantInfoBean; -import org.wso2.carbon.stratos.common.listeners.TenantMgtListener; import org.wso2.carbon.user.api.Permission; +import org.wso2.carbon.device.mgt.common.exceptions.MetadataManagementException; +import org.wso2.carbon.device.mgt.common.permission.mgt.PermissionManagementException; +import org.wso2.carbon.device.mgt.common.roles.config.Role; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.api.UserStoreManager; @@ -39,97 +43,72 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -public class DeviceMgtTenantMgtListener implements TenantMgtListener { - private static final Log log = LogFactory.getLog(DeviceMgtTenantMgtListener.class); - private static final int EXEC_ORDER = 10; +public class TenantManagerImpl implements TenantManager { + private static final Log log = LogFactory.getLog(TenantManagerImpl.class); private static final String PERMISSION_ACTION = "ui.execute"; @Override - public void onTenantCreate(TenantInfoBean tenantInfoBean) { + public void addDefaultRoles(TenantInfoBean tenantInfoBean) throws TenantMgtException { + initTenantFlow(tenantInfoBean); DeviceManagementConfig config = DeviceConfigurationManager.getInstance().getDeviceManagementConfig(); if (config.getDefaultRoles().isEnabled()) { Map> roleMap = getValidRoleMap(config); try { - PrivilegedCarbonContext.startTenantFlow(); - PrivilegedCarbonContext.getThreadLocalCarbonContext() - .setTenantDomain(tenantInfoBean.getTenantDomain(), true); - UserStoreManager userStoreManager = DeviceManagementDataHolder.getInstance().getRealmService() + UserStoreManager userStoreManager = TenantMgtDataHolder.getInstance().getRealmService() .getTenantUserRealm(tenantInfoBean.getTenantId()).getUserStoreManager(); roleMap.forEach((key, value) -> { try { userStoreManager.addRole(key, null, value.toArray(new Permission[0])); } catch (UserStoreException e) { - log.error("Error occurred while adding default roles into user store.", e); + log.error("Error occurred while adding default roles into user store", e); } }); } catch (UserStoreException e) { - log.error("Error occurred while getting user store manager.", e); - } finally { - PrivilegedCarbonContext.endTenantFlow(); + String msg = "Error occurred while getting user store manager"; + log.error(msg, e); + throw new TenantMgtException(msg, e); } } try { - DeviceManagementDataHolder.getInstance().getWhiteLabelManagementService(). + TenantMgtDataHolder.getInstance().getWhiteLabelManagementService(). addDefaultWhiteLabelThemeIfNotExist(tenantInfoBean.getTenantId()); } catch (MetadataManagementException e) { - log.error("Error occurred while adding default white label theme to created tenant.", e); + String msg = "Error occurred while adding default white label theme to created tenant - id "+tenantInfoBean.getTenantId(); + log.error(msg, e); + throw new TenantMgtException(msg, e); + } finally { + endTenantFlow(); } } @Override - public void onTenantUpdate(TenantInfoBean tenantInfoBean) { - // doing nothing - } - - @Override - public void onTenantDelete(int i) { - // doing nothing - } - - @Override - public void onTenantRename(int i, String s, String s1) { - // doing nothing - } - - @Override - public void onTenantInitialActivation(int i) { - // doing nothing - } - - @Override - public void onTenantActivation(int i) { - // doing nothing - } - - @Override - public void onTenantDeactivation(int i) { - // doing nothing - } - - @Override - public void onSubscriptionPlanChange(int i, String s, String s1) { - // doing nothing + public void addDefaultAppCategories(TenantInfoBean tenantInfoBean) throws TenantMgtException { + initTenantFlow(tenantInfoBean); + try { + ApplicationManager applicationManager = TenantMgtDataHolder.getInstance().getApplicationManager(); + applicationManager + .addApplicationCategories(ConfigurationManager.getInstance().getConfiguration().getAppCategories()); + } catch (ApplicationManagementException e) { + String msg = "Error occurred while getting default application categories"; + log.error(msg, e); + throw new TenantMgtException(msg, e); + } finally { + endTenantFlow(); + } } - @Override - public int getListenerOrder() { - return EXEC_ORDER; + private void initTenantFlow(TenantInfoBean tenantInfoBean) { + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext privilegedCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + privilegedCarbonContext.setTenantId(tenantInfoBean.getTenantId()); + privilegedCarbonContext.setTenantDomain(tenantInfoBean.getTenantDomain()); } - @Override - public void onPreDelete(int i) { - // doing nothing + private void endTenantFlow() { + PrivilegedCarbonContext.endTenantFlow(); } - /** - * Use the default roles defined in the cdm-config and evaluate the defined permissions. If permissions does not - * exist then exclude them and return role map which contains defined roles in the cdm-config and existing - * permission list as a roleMap - * @param config cdm-config - * @return {@link Map} key is role name and value is list of permissions which needs to be assigned to the role - * defined in the key. - */ private Map> getValidRoleMap(DeviceManagementConfig config) { Map> roleMap = new HashMap<>(); try { diff --git a/components/tenant-mgt/io.entgra.tenant.mgt.core/src/main/java/io/entgra/tenant/mgt/core/impl/TenantManagerServiceImpl.java b/components/tenant-mgt/io.entgra.tenant.mgt.core/src/main/java/io/entgra/tenant/mgt/core/impl/TenantManagerServiceImpl.java new file mode 100644 index 0000000000..e15d105fbf --- /dev/null +++ b/components/tenant-mgt/io.entgra.tenant.mgt.core/src/main/java/io/entgra/tenant/mgt/core/impl/TenantManagerServiceImpl.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) 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.tenant.mgt.core.impl; + +import io.entgra.tenant.mgt.common.spi.TenantManagerService; +import io.entgra.tenant.mgt.common.exception.TenantMgtException; +import io.entgra.tenant.mgt.core.internal.TenantMgtDataHolder; +import org.wso2.carbon.stratos.common.beans.TenantInfoBean; + +public class TenantManagerServiceImpl implements TenantManagerService { + + @Override + public void addDefaultRoles(TenantInfoBean tenantInfoBean) throws TenantMgtException { + TenantMgtDataHolder.getInstance().getTenantManager().addDefaultRoles(tenantInfoBean); + } + + @Override + public void addDefaultAppCategories(TenantInfoBean tenantInfoBean) throws TenantMgtException { + TenantMgtDataHolder.getInstance().getTenantManager().addDefaultAppCategories(tenantInfoBean); + } +} diff --git a/components/tenant-mgt/io.entgra.tenant.mgt.core/src/main/java/io/entgra/tenant/mgt/core/internal/TenantMgtDataHolder.java b/components/tenant-mgt/io.entgra.tenant.mgt.core/src/main/java/io/entgra/tenant/mgt/core/internal/TenantMgtDataHolder.java new file mode 100644 index 0000000000..d28862d410 --- /dev/null +++ b/components/tenant-mgt/io.entgra.tenant.mgt.core/src/main/java/io/entgra/tenant/mgt/core/internal/TenantMgtDataHolder.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) 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.tenant.mgt.core.internal; + +import io.entgra.application.mgt.common.services.ApplicationManager; +import io.entgra.tenant.mgt.core.TenantManager; +import org.wso2.carbon.device.mgt.common.metadata.mgt.WhiteLabelManagementService; +import org.wso2.carbon.user.core.service.RealmService; + +public class TenantMgtDataHolder { + private static final TenantMgtDataHolder instance = new TenantMgtDataHolder(); + private TenantManager tenantManager; + + private ApplicationManager applicationManager; + + private WhiteLabelManagementService whiteLabelManagementService; + + private RealmService realmService; + + public RealmService getRealmService() { + return realmService; + } + + public void setRealmService(RealmService realmService) { + this.realmService = realmService; + } + + public ApplicationManager getApplicationManager() { + return applicationManager; + } + + public void setApplicationManager(ApplicationManager applicationManager) { + this.applicationManager = applicationManager; + } + + public WhiteLabelManagementService getWhiteLabelManagementService() { + return whiteLabelManagementService; + } + + public void setWhiteLabelManagementService(WhiteLabelManagementService whiteLabelManagementService) { + this.whiteLabelManagementService = whiteLabelManagementService; + } + + public TenantManager getTenantManager() { + return tenantManager; + } + + public void setTenantManager(TenantManager tenantManager) { + this.tenantManager = tenantManager; + } + + public static TenantMgtDataHolder getInstance() { + return instance; + } +} diff --git a/components/tenant-mgt/io.entgra.tenant.mgt.core/src/main/java/io/entgra/tenant/mgt/core/internal/TenantMgtServiceComponent.java b/components/tenant-mgt/io.entgra.tenant.mgt.core/src/main/java/io/entgra/tenant/mgt/core/internal/TenantMgtServiceComponent.java new file mode 100644 index 0000000000..cab03921c0 --- /dev/null +++ b/components/tenant-mgt/io.entgra.tenant.mgt.core/src/main/java/io/entgra/tenant/mgt/core/internal/TenantMgtServiceComponent.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) 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.tenant.mgt.core.internal; + +import io.entgra.application.mgt.common.services.ApplicationManager; +import io.entgra.tenant.mgt.common.spi.TenantManagerService; +import io.entgra.tenant.mgt.core.TenantManager; +import io.entgra.tenant.mgt.core.impl.TenantManagerImpl; +import io.entgra.tenant.mgt.core.impl.TenantManagerServiceImpl; +import io.entgra.tenant.mgt.core.listener.DeviceMgtTenantListener; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.osgi.service.component.ComponentContext; +import org.wso2.carbon.device.mgt.common.metadata.mgt.WhiteLabelManagementService; +import org.wso2.carbon.device.mgt.core.metadata.mgt.WhiteLabelManagementServiceImpl; +import org.wso2.carbon.stratos.common.listeners.TenantMgtListener; +import org.wso2.carbon.user.core.service.RealmService; + +/** + * @scr.component name="org.wso2.carbon.devicemgt.tenant.manager" immediate="true" + * @scr.reference name="org.wso2.carbon.application.mgt.service" + * interface="io.entgra.application.mgt.common.services.ApplicationManager" + * cardinality="1..1" + * policy="dynamic" + * bind="setApplicationManager" + * unbind="unsetApplicationManager" + * @scr.reference name="user.realmservice.default" + * interface="org.wso2.carbon.user.core.service.RealmService" + * cardinality="1..1" + * policy="dynamic" + * bind="setRealmService" + * unbind="unsetRealmService" + */ + +@SuppressWarnings("unused") +public class TenantMgtServiceComponent { + + private static final Log log = LogFactory.getLog(TenantManagerService.class); + + @SuppressWarnings("unused") + protected void activate(ComponentContext componentContext) { + try { + TenantManagerService tenantManagerService = new TenantManagerServiceImpl(); + componentContext.getBundleContext(). + registerService(TenantManagerServiceImpl.class.getName(), tenantManagerService, null); + TenantManager tenantManager = new TenantManagerImpl(); + TenantMgtDataHolder.getInstance().setTenantManager(tenantManager); + WhiteLabelManagementService whiteLabelManagementService = new WhiteLabelManagementServiceImpl(); + componentContext.getBundleContext().registerService(WhiteLabelManagementServiceImpl.class.getName(), + whiteLabelManagementService, null); + TenantMgtDataHolder.getInstance().setWhiteLabelManagementService(whiteLabelManagementService); + DeviceMgtTenantListener deviceMgtTenantListener = new DeviceMgtTenantListener(); + if(log.isDebugEnabled()) { + log.info("Tenant management listener is registering"); + } + componentContext.getBundleContext(). + registerService(TenantMgtListener.class.getName(), deviceMgtTenantListener, null); + if(log.isDebugEnabled()) { + log.info("Tenant management service activated"); + } + } catch (Throwable t) { + String msg = "Error occurred while activating tenant management service"; + log.error(msg, t); + } + } + + @SuppressWarnings("unused") + protected void deactivate(ComponentContext componentContext) { + // nothing to do + } + + protected void setApplicationManager(ApplicationManager applicationManager) { + if(log.isDebugEnabled()) { + log.info("Application manager service is binding"); + } + TenantMgtDataHolder.getInstance().setApplicationManager(applicationManager); + } + + protected void unsetApplicationManager(ApplicationManager applicationManager) { + if(log.isDebugEnabled()) { + log.info("Application manager service is unbinding"); + } + TenantMgtDataHolder.getInstance().setApplicationManager(null); + } + + protected void setRealmService(RealmService realmService) { + if(log.isDebugEnabled()) { + log.info("Realm Service service is binding"); + } + TenantMgtDataHolder.getInstance().setRealmService(realmService); + } + + protected void unsetRealmService(RealmService realmService) { + if(log.isDebugEnabled()) { + log.info("Realm Service service is unbinding"); + } + TenantMgtDataHolder.getInstance().setRealmService(null); + } +} diff --git a/components/tenant-mgt/io.entgra.tenant.mgt.core/src/main/java/io/entgra/tenant/mgt/core/listener/DeviceMgtTenantListener.java b/components/tenant-mgt/io.entgra.tenant.mgt.core/src/main/java/io/entgra/tenant/mgt/core/listener/DeviceMgtTenantListener.java new file mode 100644 index 0000000000..a272585bf7 --- /dev/null +++ b/components/tenant-mgt/io.entgra.tenant.mgt.core/src/main/java/io/entgra/tenant/mgt/core/listener/DeviceMgtTenantListener.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2023, Entgra Pvt Ltd. (http://www.wso2.org) 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.tenant.mgt.core.listener; + +import io.entgra.tenant.mgt.core.TenantManager; +import io.entgra.tenant.mgt.common.exception.TenantMgtException; +import io.entgra.tenant.mgt.core.internal.TenantMgtDataHolder; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.stratos.common.beans.TenantInfoBean; +import org.wso2.carbon.stratos.common.exception.StratosException; +import org.wso2.carbon.stratos.common.listeners.TenantMgtListener; + +public class DeviceMgtTenantListener implements TenantMgtListener { + + private static final Log log = LogFactory.getLog(DeviceMgtTenantListener.class); + public static final int LISTENER_EXECUTION_ORDER = 10; + + @Override + public void onTenantCreate(TenantInfoBean tenantInfoBean) { + // Any work to be performed after a tenant creation + TenantManager tenantManager = TenantMgtDataHolder.getInstance().getTenantManager(); + try { + tenantManager.addDefaultRoles(tenantInfoBean); + tenantManager.addDefaultAppCategories(tenantInfoBean); + } catch (TenantMgtException e) { + String msg = "Error occurred while executing tenant creation flow"; + log.error(msg, e); + } + } + + @Override + public void onTenantUpdate(TenantInfoBean tenantInfoBean) throws StratosException { + // Any work to be performed after a tenant information update happens + } + + @Override + public void onTenantDelete(int i) { + // Any work to be performed after a tenant deletion + } + + @Override + public void onTenantRename(int i, String s, String s1) throws StratosException { + // Any work to be performed after a tenant rename happens + } + + @Override + public void onTenantInitialActivation(int i) throws StratosException { + // Any work to be performed after a tenant's initial activation happens + } + + @Override + public void onTenantActivation(int i) throws StratosException { + // Any work to be performed after a tenant activation + } + + @Override + public void onTenantDeactivation(int i) throws StratosException { + // Any work to be performed after a tenant deactivation + } + + @Override + public void onSubscriptionPlanChange(int i, String s, String s1) throws StratosException { + // Any work to be performed after subscription plan change + } + + @Override + public int getListenerOrder() { + return LISTENER_EXECUTION_ORDER; + } + + @Override + public void onPreDelete(int i) throws StratosException { + // Any work to be performed before a tenant is deleted + } +} diff --git a/components/tenant-mgt/pom.xml b/components/tenant-mgt/pom.xml new file mode 100644 index 0000000000..7d13f340c8 --- /dev/null +++ b/components/tenant-mgt/pom.xml @@ -0,0 +1,40 @@ + + + + + carbon-devicemgt + org.wso2.carbon.devicemgt + 5.0.25-SNAPSHOT + ../../pom.xml + + + 4.0.0 + tenant-mgt + pom + Entgra IoT - Tenant Management Component + Entgra IoT - Tenant Management Component + + + io.entgra.tenant.mgt.core + io.entgra.tenant.mgt.common + + + \ No newline at end of file diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql index 2d8bdd30c3..af29b96e1a 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql @@ -10,6 +10,13 @@ CREATE TABLE DM_DEVICE_TYPE ( CONSTRAINT DEVICE_TYPE_NAME UNIQUE(NAME, PROVIDER_TENANT_ID) ); +IF NOT EXISTS (SELECT * FROM SYS.INDEXES WHERE NAME = 'IDX_DEVICE_TYPE' AND OBJECT_ID = OBJECT_ID('DM_DEVICE_TYPE')) +CREATE INDEX IDX_DEVICE_TYPE ON DM_DEVICE_TYPE (NAME, PROVIDER_TENANT_ID); +IF NOT EXISTS (SELECT * FROM SYS.INDEXES WHERE NAME = 'IDX_DEVICE_NAME' AND OBJECT_ID = OBJECT_ID('DM_DEVICE_TYPE')) +CREATE INDEX IDX_DEVICE_NAME ON DM_DEVICE_TYPE (NAME); +IF NOT EXISTS (SELECT * FROM SYS.INDEXES WHERE NAME = 'IDX_DEVICE_TYPE_DEVICE_NAME' AND OBJECT_ID = OBJECT_ID('DM_DEVICE_TYPE')) +CREATE INDEX IDX_DEVICE_TYPE_DEVICE_NAME ON DM_DEVICE_TYPE (ID, NAME); + IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[DM_DEVICE_CERTIFICATE]') AND TYPE IN (N'U')) CREATE TABLE DM_DEVICE_CERTIFICATE ( ID INTEGER IDENTITY(1,1) NOT NULL, @@ -165,6 +172,13 @@ CREATE TABLE DM_ENROLMENT_OP_MAPPING ( PUSH_NOTIFICATION_STATUS VARCHAR(50) NULL, CREATED_TIMESTAMP BIGINT NOT NULL, UPDATED_TIMESTAMP BIGINT NOT NULL, + OPERATION_CODE VARCHAR(50) NOT NULL, + INITIATED_BY VARCHAR(100) NULL, + TYPE VARCHAR(20) NOT NULL, + DEVICE_ID INTEGER DEFAULT NULL, + DEVICE_TYPE VARCHAR(300) NOT NULL, + DEVICE_IDENTIFICATION VARCHAR(300) DEFAULT NULL, + TENANT_ID INTEGER DEFAULT 0, PRIMARY KEY (ID), CONSTRAINT FK_DM_DEVICE_OPERATION_MAPPING_DEVICE FOREIGN KEY (ENROLMENT_ID) REFERENCES DM_ENROLMENT (ID) ON DELETE NO ACTION ON UPDATE NO ACTION, @@ -178,6 +192,8 @@ IF NOT EXISTS (SELECT * FROM SYS.INDEXES WHERE NAME = 'IDX_EN_OP_MAPPING_EN_ID' CREATE INDEX IDX_EN_OP_MAPPING_EN_ID ON DM_ENROLMENT_OP_MAPPING(ENROLMENT_ID); IF NOT EXISTS (SELECT * FROM SYS.INDEXES WHERE NAME = 'IDX_EN_OP_MAPPING_OP_ID' AND OBJECT_ID = OBJECT_ID('DM_ENROLMENT_OP_MAPPING')) CREATE INDEX IDX_EN_OP_MAPPING_OP_ID ON DM_ENROLMENT_OP_MAPPING(OPERATION_ID); +IF NOT EXISTS (SELECT * FROM SYS.INDEXES WHERE NAME = 'IDX_EN_OP_MAPPING_EN_ID_STATUS' AND OBJECT_ID = OBJECT_ID('DM_ENROLMENT_OP_MAPPING')) +CREATE INDEX IDX_EN_OP_MAPPING_EN_ID_STATUS ON DM_ENROLMENT_OP_MAPPING(ENROLMENT_ID, STATUS); IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[DM_DEVICE_OPERATION_RESPONSE]') AND TYPE IN (N'U')) CREATE TABLE DM_DEVICE_OPERATION_RESPONSE ( diff --git a/features/tenant-mgt/io.entgra.tenant.mgt.server.feature/pom.xml b/features/tenant-mgt/io.entgra.tenant.mgt.server.feature/pom.xml new file mode 100644 index 0000000000..87e3214a43 --- /dev/null +++ b/features/tenant-mgt/io.entgra.tenant.mgt.server.feature/pom.xml @@ -0,0 +1,111 @@ + + + + + tenant-mgt-feature + org.wso2.carbon.devicemgt + 5.0.25-SNAPSHOT + ../pom.xml + + + 4.0.0 + io.entgra.tenant.mgt.server.feature + Entgra IoT - Tenant Management Server Feature + Entgra IoT - Tenant Management Server Feature + pom + + + + org.wso2.carbon.devicemgt + io.entgra.tenant.mgt.core + + + org.wso2.carbon.devicemgt + io.entgra.tenant.mgt.common + + + + + + + maven-resources-plugin + 2.6 + + + copy-resources + generate-resources + + copy-resources + + + src/main/resources + + + resources + + build.properties + p2.inf + + + + + + + + + org.wso2.maven + carbon-p2-plugin + ${carbon.p2.plugin.version} + + + p2-feature-generation + package + + p2-feature-gen + + + io.entgra.tenant.mgt.server + ../../etc/feature.properties + + + org.wso2.carbon.p2.category.type:server + + org.eclipse.equinox.p2.type.group:true + + + + + + + org.wso2.carbon.devicemgt:io.entgra.tenant.mgt.core:${carbon.device.mgt.version} + + + org.wso2.carbon.devicemgt:io.entgra.tenant.mgt.common:${carbon.device.mgt.version} + + + + + + + + + + \ No newline at end of file diff --git a/features/tenant-mgt/io.entgra.tenant.mgt.server.feature/src/main/resources/build.properties b/features/tenant-mgt/io.entgra.tenant.mgt.server.feature/src/main/resources/build.properties new file mode 100644 index 0000000000..920f577888 --- /dev/null +++ b/features/tenant-mgt/io.entgra.tenant.mgt.server.feature/src/main/resources/build.properties @@ -0,0 +1 @@ +custom=true \ No newline at end of file diff --git a/features/tenant-mgt/io.entgra.tenant.mgt.server.feature/src/main/resources/p2.inf b/features/tenant-mgt/io.entgra.tenant.mgt.server.feature/src/main/resources/p2.inf new file mode 100644 index 0000000000..7ab37b9d7d --- /dev/null +++ b/features/tenant-mgt/io.entgra.tenant.mgt.server.feature/src/main/resources/p2.inf @@ -0,0 +1 @@ +instructions.configure = \ \ No newline at end of file diff --git a/features/tenant-mgt/pom.xml b/features/tenant-mgt/pom.xml new file mode 100644 index 0000000000..44befb4240 --- /dev/null +++ b/features/tenant-mgt/pom.xml @@ -0,0 +1,36 @@ + + + + + + carbon-devicemgt + org.wso2.carbon.devicemgt + 5.0.25-SNAPSHOT + ../../pom.xml + + + 4.0.0 + tenant-mgt-feature + pom + Entgra IoT - Tenant Management Feature + + + io.entgra.tenant.mgt.server.feature + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index c0a3f9375d..b7c402aeb8 100644 --- a/pom.xml +++ b/pom.xml @@ -49,6 +49,7 @@ components/logger components/task-mgt components/subtype-mgt + components/tenant-mgt features/device-mgt features/apimgt-extensions features/application-mgt @@ -64,7 +65,7 @@ features/logger features/task-mgt features/subtype-mgt - + features/tenant-mgt @@ -372,6 +373,18 @@ + + + org.wso2.carbon.devicemgt + io.entgra.tenant.mgt.common + ${carbon.device.mgt.version} + + + org.wso2.carbon.devicemgt + io.entgra.tenant.mgt.core + ${carbon.device.mgt.version} + + org.wso2.carbon.devicemgt