Compare commits

Invalid templates have been ignored

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

..

3 Commits

Author SHA1 Message Date
Ruwin Dissanayake 7c40390ee0 Resolved comments
1 week ago
Ruwin Dissanayake a149f64d13 Fix to display statistics in webapps
3 weeks ago
Ruwin Dissanayake e547199706 Fix for incorrect statistics issue in User and Role
3 weeks ago

@ -122,10 +122,7 @@ public class FileDownloaderServiceProvider {
}
FileMetaEntry fileMetaEntry = new FileMetaEntry();
String contentLength = response.header("Content-Length");
if (contentLength != null) {
fileMetaEntry.setSize(Long.parseLong(contentLength));
}
fileMetaEntry.setSize(Long.parseLong(Objects.requireNonNull(response.header("Content-Length"))));
fileMetaEntry.setFileName(fileNameSegments[0]);
fileMetaEntry.setExtension(fileNameSegments[1]);
return fileMetaEntry;
@ -135,21 +132,9 @@ public class FileDownloaderServiceProvider {
}
/**
* Extracts file name segments (name and extension) by parsing the given URL.
* This method handles two types of URL formats:
* - If the URL includes a query parameter in the format `?fileName=`, the file name
* is extracted from this query parameter (ex: when referencing an existing
* screenshot or icon from the main release)
* - If the URL does not have the `fileName` query parameter, the method attempts to
* extract the file name from the URL path. (ex: this applies to cases where new files are
* uploaded, and only a path-based URL is provided)
* After locating the file name (from either the query parameter or path), the method
* splits the name into segments based on the last dot (`.`), returning the base name and
* extension as a two-element array. If file name cannot be extracted, `null` is returned.
*
* @param url Remote URL to extract file name segments from, which may contain a file name
* as either a query parameter (`fileName=...`) or in the path.
* @return An array containing the file name and extension segments, or null if extraction fails.
* Extracting file name segments by parsing the URL
* @param url Remote URL to extract file name segments
* @return Array containing file name segments or null when failed to extract
*/
public static String[] extractFileNameSegmentsFromUrl(URL url) {
if (url == null) {
@ -158,36 +143,25 @@ public class FileDownloaderServiceProvider {
}
return null;
}
String fullQualifiedName = null;
String query = url.getQuery();
if (query != null && query.startsWith("fileName=")) {
String[] queryParts = query.split("=", 2);
if (queryParts.length > 1 && !queryParts[1].isEmpty()) {
fullQualifiedName = queryParts[1];
}
}
if (fullQualifiedName == null) {
String[] urlSegments = url.getPath().split("/");
if (urlSegments.length > 0) {
fullQualifiedName = urlSegments[urlSegments.length - 1];
}
}
if (fullQualifiedName != null) {
String[] fileNameSegments = fullQualifiedName.split("\\.(?=[^.]+$)");
if (fileNameSegments.length == 2) {
return fileNameSegments;
} else {
String []urlSegments = url.toString().split("/");
if (urlSegments.length < 1) {
if (log.isDebugEnabled()) {
log.debug("Error encountered when constructing file name");
log.debug("Cannot determine the file name for the remote file");
}
return null;
}
} else {
String fullQualifiedName = urlSegments[urlSegments.length - 1];
String []fileNameSegments = fullQualifiedName.split("\\.(?=[^.]+$)");
if (fileNameSegments.length != 2) {
if (log.isDebugEnabled()) {
log.debug("Error encountered when constructing file name");
}
}
return null;
}
return fileNameSegments;
}
/**
* Extract file name segments(filename & extensions) from content disposition header and content type header

@ -183,15 +183,6 @@ public class FileTransferServiceHelperUtil {
return fileDescriptorResolvedFromRelease;
}
String file = urlPathSegments[urlPathSegments.length - 1];
String query = downloadUrl.getQuery();
if (query != null && query.startsWith("fileName=")) {
String[] queryParts = query.split("=", 2);
if (queryParts.length > 1 && !queryParts[1].isEmpty()) {
file = queryParts[1];
}
}
if (urlPathSegments.length < 2) {
if (log.isDebugEnabled()) {
log.debug("URL patch segments contain less than 2 segments");
@ -199,6 +190,7 @@ public class FileTransferServiceHelperUtil {
return null;
}
String file = urlPathSegments[urlPathSegments.length - 1];
String artifactHolder = urlPathSegments[urlPathSegments.length - 2];
try {
FileDescriptor fileDescriptor = new FileDescriptor();

@ -44,6 +44,8 @@ import io.entgra.device.mgt.core.device.mgt.common.EnrolmentInfo;
import io.entgra.device.mgt.core.device.mgt.common.PaginationRequest;
import io.entgra.device.mgt.core.device.mgt.common.PaginationResult;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceManagementException;
import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceManagementDAOException;
import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceDetailsDTO;
import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@ -190,7 +192,7 @@ public class RoleBasedSubscriptionManagementHelperServiceImpl implements Subscri
List<Integer> deviceIdsOwnByRole = getDeviceIdsOwnByRole(subscriptionInfo.getIdentifier(), tenantId);
SubscriptionStatisticDTO subscriptionStatisticDTO = subscriptionDAO.
getSubscriptionStatistic(deviceIdsOwnByRole, isUnsubscribe, tenantId, applicationReleaseDTO.getId());
int allDeviceCount = deviceIdsOwnByRole.size();
int allDeviceCount = getDeviceIdsOwnByRoleWithType(subscriptionInfo.getIdentifier(), tenantId, applicationReleaseDTO);
return SubscriptionManagementHelperUtil.getSubscriptionStatistics(subscriptionStatisticDTO, allDeviceCount);
} catch (DeviceManagementException | ApplicationManagementDAOException | UserStoreException e) {
String msg = "Error encountered while getting subscription statistics for role: " + subscriptionInfo.getIdentifier();
@ -212,7 +214,7 @@ public class RoleBasedSubscriptionManagementHelperServiceImpl implements Subscri
PaginationRequest paginationRequest = new PaginationRequest(-1, -1);
paginationRequest.setOwner(user);
paginationRequest.setStatusList(Arrays.asList(EnrolmentInfo.Status.ACTIVE.name(),
EnrolmentInfo.Status.INACTIVE.name(),EnrolmentInfo.Status.UNREACHABLE.name()));
EnrolmentInfo.Status.INACTIVE.name(), EnrolmentInfo.Status.UNREACHABLE.name()));
PaginationResult ownDeviceIds = HelperUtil.getDeviceManagementProviderService().
getAllDevicesIdList(paginationRequest);
if (ownDeviceIds.getData() != null) {
@ -222,6 +224,35 @@ public class RoleBasedSubscriptionManagementHelperServiceImpl implements Subscri
return deviceListOwnByRole.stream().map(Device::getId).collect(Collectors.toList());
}
private int getDeviceIdsOwnByRoleWithType(String roleName, int tenantId, ApplicationReleaseDTO applicationReleaseDTO)
throws UserStoreException, DeviceManagementException, ApplicationManagementException {
UserStoreManager userStoreManager = DataHolder.getInstance().getRealmService()
.getTenantUserRealm(tenantId).getUserStoreManager();
String[] usersWithRole = userStoreManager.getUserListOfRole(roleName);
int idCountOwnByRole = 0;
int deviceTypeId;
try {
deviceTypeId = applicationDAO.getApplication(applicationReleaseDTO.getUuid(), tenantId).getDeviceTypeId();
} catch (ApplicationManagementDAOException e) {
String msg = "Error encountered while accessing application management data.";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
}
for (String user : usersWithRole) {
try {
List<DeviceDetailsDTO> idsOwnByRole = HelperUtil.getDeviceManagementProviderService()
.getDevicesByTenantId(tenantId, deviceTypeId, user, null);
if (idsOwnByRole != null) {
idCountOwnByRole += idsOwnByRole.size();
}
} catch (DeviceManagementDAOException e) {
String msg = String.format("Error encountered while accessing device management data for user: %s", user);
log.error(msg, e);
}
}
return idCountOwnByRole;
}
private static class RoleBasedSubscriptionManagementHelperServiceImplHolder {
private static final RoleBasedSubscriptionManagementHelperServiceImpl INSTANCE
= new RoleBasedSubscriptionManagementHelperServiceImpl();

@ -43,6 +43,8 @@ import io.entgra.device.mgt.core.device.mgt.common.EnrolmentInfo;
import io.entgra.device.mgt.core.device.mgt.common.PaginationRequest;
import io.entgra.device.mgt.core.device.mgt.common.PaginationResult;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceManagementException;
import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceManagementDAOException;
import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceDetailsDTO;
import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@ -181,9 +183,11 @@ public class UserBasedSubscriptionManagementHelperServiceImpl implements Subscri
List<Integer> deviceIdsOwnByUser = getDeviceIdsOwnByUser(subscriptionInfo.getIdentifier());
SubscriptionStatisticDTO subscriptionStatisticDTO = subscriptionDAO.
getSubscriptionStatistic(deviceIdsOwnByUser, isUnsubscribe, tenantId, applicationReleaseDTO.getId());
int allDeviceCount = deviceIdsOwnByUser.size();
List <DeviceDetailsDTO> devices = HelperUtil.getDeviceManagementProviderService().getDevicesByTenantId(tenantId,
applicationDAO.getApplication(applicationReleaseDTO.getUuid(), tenantId).getDeviceTypeId(), subscriptionInfo.getIdentifier(), null);
int allDeviceCount = devices.size();
return SubscriptionManagementHelperUtil.getSubscriptionStatistics(subscriptionStatisticDTO, allDeviceCount);
} catch (DeviceManagementException | ApplicationManagementDAOException e) {
} catch (DeviceManagementException | ApplicationManagementDAOException | DeviceManagementDAOException e) {
String msg = "Error encountered while getting subscription statistics for user: " + subscriptionInfo.getIdentifier();
log.error(msg, e);
throw new ApplicationManagementException(msg, e);

@ -29,6 +29,7 @@ import io.entgra.device.mgt.core.certificate.mgt.core.util.CertificateManagement
import io.entgra.device.mgt.core.certificate.mgt.core.util.CommonUtil;
import io.entgra.device.mgt.core.certificate.mgt.core.util.Serializer;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bouncycastle.asn1.ASN1Encodable;
@ -435,7 +436,7 @@ public class CertificateGenerator {
String orgUnit = CommonUtil.getSubjectDnAttribute(reqCert,
CertificateManagementConstants.ORG_UNIT_ATTRIBUTE);
CertificateResponse lookUpCertificate;
if (CommonUtil.isScepOrgUnit(orgUnit)) {
if (StringUtils.isNotEmpty(orgUnit)) {
int tenantId = Integer.parseInt(orgUnit.split(("_"))[1]);
lookUpCertificate = keyStoreReader.getCertificateBySerial(reqCert.getSerialNumber().toString(),
tenantId);

@ -36,7 +36,6 @@ public final class CertificateManagementConstants {
public static final String CONF_LOCATION = "conf.location";
public static final String DEFAULT_PRINCIPAL = "O=WSO2, OU=Mobile, C=LK";
public static final String ORG_UNIT_ATTRIBUTE = "OU=";
public static final String ORG_UNIT_TENANT_PREFIX = "tenant_";
public static final String RSA_PRIVATE_KEY_BEGIN_TEXT = "-----BEGIN RSA PRIVATE KEY-----\n";
public static final String RSA_PRIVATE_KEY_END_TEXT = "-----END RSA PRIVATE KEY-----";
public static final String EMPTY_TEXT = "";

@ -18,7 +18,6 @@
package io.entgra.device.mgt.core.certificate.mgt.core.util;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import java.math.BigInteger;
import java.security.cert.X509Certificate;
@ -69,24 +68,4 @@ public class CommonUtil {
}
return null;
}
/**
* Checks if the organizational unit (OU) attribute has a valid tenant id in order to verify that it is
* a SCEP certificate. eg: OU=tenant_1
* <br/><br/>
* Refer to engineering mail SCEP implementation for Android
* @param orgUnit organizational unit (OU) of the certificate
* @return true if it is a valid SCEP org unit else false
*/
public static boolean isScepOrgUnit(String orgUnit) {
if (StringUtils.isNotEmpty(orgUnit)) {
if (orgUnit.contains(CertificateManagementConstants.ORG_UNIT_TENANT_PREFIX)) {
String[] orgUnitArray = orgUnit.split(("_"));
if (orgUnitArray.length > 1) {
return NumberUtils.isNumber(orgUnitArray[1]);
}
}
}
return false;
}
}

@ -1590,20 +1590,23 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO {
int deviceCount = 0;
try {
Connection connection = GroupManagementDAOFactory.getConnection();
String sql = "SELECT COUNT(e.ID) AS COUNT " +
StringBuilder sql = new StringBuilder("SELECT COUNT(e.ID) AS COUNT " +
"FROM DM_GROUP d " +
"INNER JOIN DM_DEVICE_GROUP_MAP m ON d.ID = m.GROUP_ID " +
"INNER JOIN DM_ENROLMENT e ON m.DEVICE_ID = e.DEVICE_ID " +
"INNER JOIN DM_DEVICE r ON e.DEVICE_ID = r.ID " +
"WHERE d.TENANT_ID = ? " +
"AND d.GROUP_NAME = ? " +
"AND r.DEVICE_TYPE_ID = ? " +
"AND e.STATUS NOT IN ('REMOVED', 'DELETED')";
try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
"AND e.STATUS NOT IN ('REMOVED', 'DELETED')");
if (deviceTypeId != 0) {
sql.append(" AND r.DEVICE_TYPE_ID = ?");
}
try (PreparedStatement preparedStatement = connection.prepareStatement(sql.toString())) {
preparedStatement.setInt(1, tenantId);
preparedStatement.setString(2, groupName);
if (deviceTypeId != 0) {
preparedStatement.setInt(3, deviceTypeId);
}
try (ResultSet resultSet = preparedStatement.executeQuery()) {
if (resultSet.next()) {
deviceCount = resultSet.getInt("COUNT");

@ -1,55 +0,0 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.ui.request.interceptor.beans;
public class ErrorResponse {
private int code;
private String data;
private int status;
public ErrorResponse(int code, String data, int status) {
this.code = code;
this.data = data;
this.status = status;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
}

@ -20,16 +20,17 @@ package io.entgra.device.mgt.core.ui.request.interceptor.util;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.TextNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import io.entgra.device.mgt.core.ui.request.interceptor.beans.AuthData;
import io.entgra.device.mgt.core.ui.request.interceptor.beans.ErrorResponse;
import io.entgra.device.mgt.core.ui.request.interceptor.cache.LoginCache;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
@ -226,37 +227,16 @@ public class HandlerUtil {
proxyResponse.setExecutorResponse(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil
.getStatusKey(HandlerConstants.INTERNAL_ERROR_CODE));
}
JsonNode dataNode = proxyResponse.getData();
String responseData = extractDataAsString(dataNode);
resp.setStatus(proxyResponse.getCode());
resp.setContentType(ContentType.APPLICATION_JSON.getMimeType());
resp.setCharacterEncoding(Consts.UTF_8.name());
proxyResponse.setExecutorResponse(null);
proxyResponse.setData(null);
ErrorResponse errorResponse = new ErrorResponse(
proxyResponse.getCode(),
responseData,
proxyResponse.getStatus()
);
try (PrintWriter writer = resp.getWriter()) {
writer.write(gson.toJson(errorResponse));
writer.write(gson.toJson(proxyResponse));
}
}
/**
* Extracts a string representation from the given JsonNode.
*
* @param dataNode the JsonNode from which to extract the string representation (can be null).
* @return the string representation of the JsonNode, or null if the dataNode is null.
*/
private static String extractDataAsString(JsonNode dataNode) {
if (dataNode == null) {
return null;
}
return dataNode.isTextual() ? dataNode.asText() : dataNode.toString();
}
/**
* Handle error requests with custom error codes.
*
@ -792,7 +772,9 @@ public class HandlerUtil {
try {
finalNode = objectMapper.readTree(content);
} catch (JsonProcessingException e) {
finalNode = new TextNode(content);
ObjectNode objectNode = objectMapper.createObjectNode();
objectNode.put("message", content);
finalNode = objectMapper.valueToTree(objectNode);
}
}
return finalNode;

@ -427,12 +427,6 @@
<Scope>dm:admin:cea:sync</Scope>
<Scope>am:pub:app:upload</Scope>
<Scope>dm:devices:ops:status:update</Scope>
<Scope>tm:tags:view</Scope>
<Scope>tm:tags:create</Scope>
<Scope>tm:tags:update</Scope>
<Scope>tm:tags:delete</Scope>
<Scope>tm:tags:mapping:create</Scope>
<Scope>tm:tags:mapping:delete</Scope>
</Scopes>
<SSOConfiguration>
<Issuer>device-mgt</Issuer>

Loading…
Cancel
Save