diff --git a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/pom.xml b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/pom.xml
new file mode 100644
index 0000000000..40ac6610bd
--- /dev/null
+++ b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/pom.xml
@@ -0,0 +1,230 @@
+
+
+
+
+
+
+ device-mgt-extensions
+ io.entgra.device.mgt.core
+ 5.0.31-SNAPSHOT
+ ../pom.xml
+
+
+ 4.0.0
+ io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper
+ bundle
+ Entgra IoT - User store role mapping Module
+ Entgra IoT - User store role mapping Module
+ http://entgra.io
+
+
+
+
+ org.apache.felix
+ maven-scr-plugin
+
+
+ maven-compiler-plugin
+
+
+ 1.8
+
+ 2.3.2
+
+
+ org.apache.felix
+ maven-bundle-plugin
+ 1.4.0
+ true
+
+
+ ${project.artifactId}
+ ${project.artifactId}
+ ${io.entgra.device.mgt.core.version}
+ IOT - User store role mapping Module
+ io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper.internal
+
+ org.osgi.framework.*;version="${imp.package.version.osgi.framework}",
+ org.osgi.service.*;version="${imp.package.version.osgi.service}",
+ org.apache.commons.logging,
+ org.apache.axis2.*;version="${axis2.osgi.version.range}",
+ org.wso2.carbon.core,
+ org.wso2.carbon.utils.*,
+ javax.xml.bind;resolution:=optional,
+ javax.xml.bind.annotation,
+ javax.xml.parsers,
+ org.w3c.dom,
+ org.wso2.carbon,
+ org.wso2.carbon.context,
+ org.wso2.carbon.user.api,
+ org.wso2.carbon.user.core.common,
+ org.wso2.carbon.user.core.service,
+ org.wso2.carbon.user.mgt.common,
+ io.entgra.device.mgt.core.server.bootup.heartbeat.beacon.service,
+ io.entgra.device.mgt.core.server.bootup.heartbeat.beacon.exception
+
+
+ !io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper.internal,
+ io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper.*;version="${project.version}"
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+
+ ${basedir}/target/coverage-reports/jacoco-unit.exec
+
+
+
+ jacoco-initialize
+
+ prepare-agent
+
+
+
+ jacoco-site
+ test
+
+ report
+
+
+ ${basedir}/target/coverage-reports/jacoco-unit.exec
+ ${basedir}/target/coverage-reports/site
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.eclipse.osgi
+ org.eclipse.osgi
+
+
+ org.eclipse.osgi
+ org.eclipse.osgi.services
+
+
+ org.wso2.carbon
+ org.wso2.carbon.core
+
+
+ org.wso2.carbon
+ org.wso2.carbon.logging
+
+
+ org.wso2.carbon
+ org.wso2.carbon.utils
+ provided
+
+
+ org.wso2.carbon
+ org.wso2.carbon.user.api
+ provided
+
+
+ org.wso2.carbon
+ org.wso2.carbon.user.core
+ provided
+
+
+ org.wso2.carbon.identity.framework
+ org.wso2.carbon.user.mgt
+ provided
+
+
+ org.mockito
+ mockito-inline
+ test
+
+
+ org.testng
+ testng
+ test
+
+
+ org.wso2.orbit.com.h2database
+ h2
+ test
+
+
+ org.apache.httpcomponents.wso2
+ httpcore
+ test
+
+
+ org.wso2.apache.httpcomponents
+ httpclient
+ test
+
+
+ org.wso2.carbon
+ org.wso2.carbon.securevault
+
+ test
+
+
+ org.wso2.securevault
+ org.wso2.securevault
+ test
+
+
+ xerces.wso2
+ xercesImpl
+ test
+
+
+ org.apache.axis2.wso2
+ axis2
+ test
+
+
+ org.wso2.carbon
+ org.wso2.carbon.queuing
+ test
+
+
+ javax.xml.bind
+ jaxb-api
+ test
+
+
+ io.entgra.device.mgt.core
+ io.entgra.device.mgt.core.server.bootup.heartbeat.beacon
+ provided
+
+
+
diff --git a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/userstore/role/mapper/UserStoreRoleMapper.java b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/userstore/role/mapper/UserStoreRoleMapper.java
new file mode 100644
index 0000000000..59e3d352c7
--- /dev/null
+++ b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/userstore/role/mapper/UserStoreRoleMapper.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
+ *
+ * Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper;
+
+import io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper.bean.RoleMapping;
+import io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper.bean.UserStoreRoleMappingConfig;
+import io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper.internal.UserStoreRoleMappingDataHolder;
+import io.entgra.device.mgt.core.server.bootup.heartbeat.beacon.exception.HeartBeatManagementException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+import org.wso2.carbon.core.ServerStartupObserver;
+import org.wso2.carbon.user.api.UserStoreException;
+import org.wso2.carbon.user.api.UserStoreManager;
+import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+public class UserStoreRoleMapper implements ServerStartupObserver {
+ private static final Log log = LogFactory.getLog(UserStoreRoleMapper.class);
+
+ private UserStoreRoleMappingConfig config = null;
+ @Override
+ public void completingServerStartup() {
+
+ }
+
+ @Override
+ public void completedServerStartup() {
+
+ config = UserStoreRoleMappingDataHolder.getInstance()
+ .getUserStoreRoleMappingConfigManager().getUserStoreRoleMappingConfig();
+
+ try {
+ if ((config.isEnabled() &&
+ UserStoreRoleMappingDataHolder.getInstance().getHeartBeatService().isTaskPartitioningEnabled() &&
+ UserStoreRoleMappingDataHolder.getInstance().getHeartBeatService().isQualifiedToExecuteTask())
+ || (config.isEnabled() &&
+ !UserStoreRoleMappingDataHolder.getInstance().getHeartBeatService().isTaskPartitioningEnabled())) {
+ Runnable periodicTask = new Runnable() {
+ public void run() {
+ updateRoleMapping();
+ log.info("UserStoreRoleMapper executed....");
+ }
+ };
+
+ ScheduledExecutorService executor =
+ Executors.newSingleThreadScheduledExecutor();
+
+ executor.scheduleAtFixedRate(periodicTask, config.getInitialDelayInSeconds(), config.getPeriodInSeconds(), TimeUnit.SECONDS);
+ }
+ } catch (HeartBeatManagementException e) {
+ log.error("Error while accessing heart beat service " + e.getMessage());
+ }
+ }
+
+ private void updateRoleMapping() {
+ try {
+ PrivilegedCarbonContext.startTenantFlow();
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(
+ MultitenantConstants.SUPER_TENANT_ID);
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
+ MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);
+
+ List roleMappings = config.getMappings();
+
+ if (!roleMappings.isEmpty()) {
+ UserStoreManager userStoreManager =
+ UserStoreRoleMappingDataHolder.getInstance().getRealmService()
+ .getTenantUserRealm(MultitenantConstants.SUPER_TENANT_ID).getUserStoreManager();
+
+ for (RoleMapping mapping : roleMappings) {
+ if (userStoreManager.isExistingRole(mapping.getSecondaryRole())) {
+ String[] users = userStoreManager.getUserListOfRole(mapping.getSecondaryRole());
+ if (users != null && users.length > 0) {
+ List primaryRoles = mapping.getInternalRoles();
+ for (String role : primaryRoles) {
+ if (userStoreManager.isExistingRole(role)) {
+ String[] existingUsers = userStoreManager.getUserListOfRole(role);
+ List existingUserList = new ArrayList<>(Arrays.asList(existingUsers));
+ List newUserList = new ArrayList<>();
+ for (String user : users) {
+ if (existingUserList.contains(user)) {
+ // if contains, remove from existing list
+ existingUserList.remove(user);
+ } else {
+ // new user
+ newUserList.add(user);
+ }
+ }
+
+ List deleteUserList = new ArrayList<>();
+ if (!existingUserList.isEmpty()) {
+ String domain = mapping.getSecondaryRole().substring(0, mapping.getSecondaryRole().indexOf("/"));
+ for (String user : existingUserList) {
+ if (user.startsWith(domain.toUpperCase())) {
+ deleteUserList.add(user);
+ }
+ }
+ }
+
+ // update user list of given role
+ if (!newUserList.isEmpty() || !deleteUserList.isEmpty()) {
+ userStoreManager.updateUserListOfRole(role, deleteUserList.toArray(new String[0]), newUserList.toArray(new String[0]));
+ log.info("update user role mapping executed.....");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } catch (UserStoreException e) {
+ log.error("Error while getting user store..." + e.getMessage());
+ } finally {
+ PrivilegedCarbonContext.endTenantFlow();
+ }
+ }
+}
diff --git a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/userstore/role/mapper/UserStoreRoleMappingConfigManager.java b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/userstore/role/mapper/UserStoreRoleMappingConfigManager.java
new file mode 100644
index 0000000000..1c4b5eac16
--- /dev/null
+++ b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/userstore/role/mapper/UserStoreRoleMappingConfigManager.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
+ *
+ * Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper;
+
+import io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper.bean.UserStoreRoleMappingConfig;
+import io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper.exception.UserStoreRoleMapperException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.w3c.dom.Document;
+import org.wso2.carbon.utils.CarbonUtils;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import java.io.File;
+
+public class UserStoreRoleMappingConfigManager {
+
+ private static final Log log = LogFactory.getLog(UserStoreRoleMappingConfigManager.class);
+ private static final String USERSTORE_ROLE_MAPPING_CONFIG_PATH = CarbonUtils.getCarbonConfigDirPath() +
+ File.separator + "user-store-role-mapping-config.xml";
+
+ private final UserStoreRoleMappingConfig userStoreRoleMappingConfig;
+
+ public UserStoreRoleMappingConfigManager() throws UserStoreRoleMapperException {
+ try {
+ File UserStoreRoleMappingConfig = new File(USERSTORE_ROLE_MAPPING_CONFIG_PATH);
+ Document doc = convertToDocument(UserStoreRoleMappingConfig);
+ JAXBContext smsContext = JAXBContext.newInstance(UserStoreRoleMappingConfig.class);
+ Unmarshaller unmarshaller = smsContext.createUnmarshaller();
+ this.userStoreRoleMappingConfig = (UserStoreRoleMappingConfig) unmarshaller.unmarshal(doc);
+ } catch (JAXBException e) {
+ String msg = "Error occurred while initializing config '" + USERSTORE_ROLE_MAPPING_CONFIG_PATH + "'";
+ log.error(msg, e);
+ throw new UserStoreRoleMapperException(msg, e);
+ }
+ }
+
+ private static Document convertToDocument(File file) throws UserStoreRoleMapperException {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+
+ try {
+ factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+ factory.setFeature("http://javax.xml.XMLConstants/feature/secure-processing", true);
+ DocumentBuilder docBuilder = factory.newDocumentBuilder();
+ return docBuilder.parse(file);
+ } catch (Exception e) {
+ throw new UserStoreRoleMapperException("Error occurred while parsing " + USERSTORE_ROLE_MAPPING_CONFIG_PATH +
+ " file, while converting to a org.w3c.dom.Document", e);
+ }
+ }
+
+ public UserStoreRoleMappingConfig getUserStoreRoleMappingConfig() {
+ return this.userStoreRoleMappingConfig;
+ }
+
+}
diff --git a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/userstore/role/mapper/bean/RoleMapping.java b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/userstore/role/mapper/bean/RoleMapping.java
new file mode 100644
index 0000000000..604c58b4a2
--- /dev/null
+++ b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/userstore/role/mapper/bean/RoleMapping.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
+ *
+ * Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper.bean;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.util.List;
+
+@XmlRootElement(
+ name = "mapping"
+)
+public class RoleMapping {
+ private String secondaryRole;
+
+ private List internalRoles;
+
+ @XmlAttribute(
+ name = "secondaryRole"
+ )
+ public String getSecondaryRole() {
+ return secondaryRole;
+ }
+
+ public void setSecondaryRole(String secondaryRole) {
+ this.secondaryRole = secondaryRole;
+ }
+
+ @XmlElementWrapper(
+ name = "internalRoles"
+ )
+ @XmlElement(
+ name = "role"
+ )
+ public List getInternalRoles() {
+ return internalRoles;
+ }
+
+ public void setInternalRoles(List internalRoles) {
+ this.internalRoles = internalRoles;
+ }
+}
diff --git a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/userstore/role/mapper/bean/UserStoreRoleMappingConfig.java b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/userstore/role/mapper/bean/UserStoreRoleMappingConfig.java
new file mode 100644
index 0000000000..58e287a9ee
--- /dev/null
+++ b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/userstore/role/mapper/bean/UserStoreRoleMappingConfig.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
+ *
+ * Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper.bean;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.util.List;
+
+@XmlRootElement(
+ name = "UserStoreRoleMappingConfig"
+)
+public class UserStoreRoleMappingConfig {
+
+ private boolean enabled;
+ private List mappings;
+
+ private long initialDelayInSeconds;
+
+ private long periodInSeconds;
+
+ @XmlElement(
+ name = "enabled"
+ )
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ @XmlElementWrapper(
+ name = "mappings"
+ )
+ @XmlElement(
+ name = "mapping"
+ )
+ public List getMappings() {
+ return mappings;
+ }
+
+ public void setMappings(List mappings) {
+ this.mappings = mappings;
+ }
+
+ @XmlElement(
+ name = "initialDelayInSeconds"
+ )
+ public long getInitialDelayInSeconds() {
+ return initialDelayInSeconds;
+ }
+
+ public void setInitialDelayInSeconds(long initialDelayInSeconds) {
+ this.initialDelayInSeconds = initialDelayInSeconds;
+ }
+
+ @XmlElement(
+ name = "periodInSeconds"
+ )
+ public long getPeriodInSeconds() {
+ return periodInSeconds;
+ }
+
+ public void setPeriodInSeconds(long periodInSeconds) {
+ this.periodInSeconds = periodInSeconds;
+ }
+}
diff --git a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/userstore/role/mapper/exception/UserStoreRoleMapperException.java b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/userstore/role/mapper/exception/UserStoreRoleMapperException.java
new file mode 100644
index 0000000000..72d56d202a
--- /dev/null
+++ b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/userstore/role/mapper/exception/UserStoreRoleMapperException.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
+ *
+ * Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper.exception;
+
+public class UserStoreRoleMapperException extends Exception {
+
+ public UserStoreRoleMapperException(String msg, Exception e) {
+ super(msg, e);
+ }
+}
diff --git a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/userstore/role/mapper/internal/UserStoreRoleMappingDataHolder.java b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/userstore/role/mapper/internal/UserStoreRoleMappingDataHolder.java
new file mode 100644
index 0000000000..71d3c32edd
--- /dev/null
+++ b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/userstore/role/mapper/internal/UserStoreRoleMappingDataHolder.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
+ *
+ * Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper.internal;
+
+import io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper.UserStoreRoleMappingConfigManager;
+import io.entgra.device.mgt.core.server.bootup.heartbeat.beacon.service.HeartBeatManagementService;
+import org.wso2.carbon.context.CarbonContext;
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+import org.wso2.carbon.user.api.UserRealm;
+import org.wso2.carbon.user.api.UserStoreException;
+import org.wso2.carbon.user.api.UserStoreManager;
+import org.wso2.carbon.user.core.service.RealmService;
+import org.wso2.carbon.utils.ConfigurationContextService;
+
+public class UserStoreRoleMappingDataHolder {
+
+ private ConfigurationContextService configurationContextService;
+ private RealmService realmService;
+ private UserStoreRoleMappingConfigManager userStoreRoleMappingConfigManager;
+ private HeartBeatManagementService heartBeatService;
+ private static final UserStoreRoleMappingDataHolder thisInstance = new UserStoreRoleMappingDataHolder();
+
+ private UserStoreRoleMappingDataHolder() {}
+
+ public static UserStoreRoleMappingDataHolder getInstance() {
+ return thisInstance;
+ }
+
+ public ConfigurationContextService getConfigurationContextService() {
+ return configurationContextService;
+ }
+
+ public void setConfigurationContextService(ConfigurationContextService configurationContextService) {
+ this.configurationContextService = configurationContextService;
+ }
+
+ public UserStoreManager getUserStoreManager() throws UserStoreException {
+ if (realmService == null) {
+ String msg = "Realm service has not initialized.";
+ throw new IllegalStateException(msg);
+ }
+ int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
+ return realmService.getTenantUserRealm(tenantId).getUserStoreManager();
+ }
+
+ public UserRealm getUserRealm() throws UserStoreException {
+ UserRealm realm;
+ if (realmService == null) {
+ throw new IllegalStateException("Realm service not initialized");
+ }
+ int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
+ realm = realmService.getTenantUserRealm(tenantId);
+ return realm;
+ }
+
+ public RealmService getRealmService() {
+ return realmService;
+ }
+
+ public void setRealmService(RealmService realmService) {
+ this.realmService = realmService;
+ }
+
+ public UserStoreRoleMappingConfigManager getUserStoreRoleMappingConfigManager() {
+ return userStoreRoleMappingConfigManager;
+ }
+
+ public void setUserStoreRoleMappingConfigManager(UserStoreRoleMappingConfigManager userStoreRoleMappingConfigManager) {
+ this.userStoreRoleMappingConfigManager = userStoreRoleMappingConfigManager;
+ }
+
+ public HeartBeatManagementService getHeartBeatService() {
+ return heartBeatService;
+ }
+
+ public void setHeartBeatService(HeartBeatManagementService heartBeatService) {
+ this.heartBeatService = heartBeatService;
+ }
+}
diff --git a/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/userstore/role/mapper/internal/UserStoreRoleMappingServiceComponent.java b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/userstore/role/mapper/internal/UserStoreRoleMappingServiceComponent.java
new file mode 100644
index 0000000000..2471c18403
--- /dev/null
+++ b/components/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/java/io/entgra/device/mgt/core/device/mgt/extensions/userstore/role/mapper/internal/UserStoreRoleMappingServiceComponent.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
+ *
+ * Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper.internal;
+
+import io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper.UserStoreRoleMapper;
+import io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper.UserStoreRoleMappingConfigManager;
+import io.entgra.device.mgt.core.server.bootup.heartbeat.beacon.service.HeartBeatManagementService;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.ComponentContext;
+import org.wso2.carbon.core.ServerStartupObserver;
+import org.wso2.carbon.user.core.service.RealmService;
+import org.wso2.carbon.utils.ConfigurationContextService;
+
+/**
+ * @scr.component name="io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper.internal.UserStoreRoleMappingServiceComponent"
+ * immediate="true"
+ * @scr.reference name="user.realmservice.default"
+ * interface="org.wso2.carbon.user.core.service.RealmService"
+ * cardinality="1..1"
+ * policy="dynamic"
+ * bind="setRealmService"
+ * unbind="unsetRealmService"
+ * @scr.reference name="config.context.service"
+ * interface="org.wso2.carbon.utils.ConfigurationContextService"
+ * cardinality="0..1"
+ * policy="dynamic"
+ * bind="setConfigurationContextService"
+ * unbind="unsetConfigurationContextService"
+ * @scr.reference name="entgra.heart.beat.service"
+ * interface="io.entgra.device.mgt.core.server.bootup.heartbeat.beacon.service.HeartBeatManagementService"
+ * cardinality="0..1"
+ * policy="dynamic"
+ * bind="setHeartBeatService"
+ * unbind="unsetHeartBeatService"
+ */
+public class UserStoreRoleMappingServiceComponent {
+
+ private static final Log log = LogFactory.getLog(UserStoreRoleMappingServiceComponent.class);
+
+ protected void activate(ComponentContext ctx) {
+ if (log.isDebugEnabled()) {
+ log.debug("Activating Role Management Service Component");
+ }
+ try {
+ BundleContext bundleContext = ctx.getBundleContext();
+ UserStoreRoleMapper mapper = new UserStoreRoleMapper();
+ bundleContext.registerService(ServerStartupObserver.class.getName(), mapper, null);
+ UserStoreRoleMappingDataHolder.getInstance().setUserStoreRoleMappingConfigManager(new UserStoreRoleMappingConfigManager());
+ if (log.isDebugEnabled()) {
+ log.debug("Role Management Service Component has been successfully activated");
+ }
+ } catch (Throwable e) {
+ log.error("Error occurred while activating Role Management Service Component", e);
+ }
+ }
+
+ protected void deactivate(ComponentContext ctx) {
+ if (log.isDebugEnabled()) {
+ log.debug("De-activating Role Manager Service Component");
+ }
+ }
+
+ protected void setConfigurationContextService(ConfigurationContextService configurationContextService) {
+ if (log.isDebugEnabled()) {
+ log.debug("Setting ConfigurationContextService");
+ }
+
+ UserStoreRoleMappingDataHolder.getInstance().setConfigurationContextService(configurationContextService);
+ }
+
+ protected void unsetConfigurationContextService(ConfigurationContextService configurationContextService) {
+ if (log.isDebugEnabled()) {
+ log.debug("Un-setting ConfigurationContextService");
+ }
+ UserStoreRoleMappingDataHolder.getInstance().setConfigurationContextService(null);
+ }
+
+ /**
+ * Sets Realm Service.
+ *
+ * @param realmService An instance of RealmService
+ */
+ protected void setRealmService(RealmService realmService) {
+ if (log.isDebugEnabled()) {
+ log.debug("Setting Realm Service");
+ }
+ UserStoreRoleMappingDataHolder.getInstance().setRealmService(realmService);
+ }
+
+ /**
+ * Unsets Realm Service.
+ *
+ * @param realmService An instance of RealmService
+ */
+ protected void unsetRealmService(RealmService realmService) {
+ if (log.isDebugEnabled()) {
+ log.debug("Unsetting Realm Service");
+ }
+ UserStoreRoleMappingDataHolder.getInstance().setRealmService(null);
+ }
+
+ @SuppressWarnings("unused")
+ protected void setHeartBeatService(HeartBeatManagementService heartBeatService) {
+ if (log.isDebugEnabled()) {
+ log.debug("Setting heart beat service");
+ }
+ UserStoreRoleMappingDataHolder.getInstance().setHeartBeatService(heartBeatService);
+ }
+
+ @SuppressWarnings("unused")
+ protected void unsetHeartBeatService(HeartBeatManagementService heartBeatManagementService) {
+ if (log.isDebugEnabled()) {
+ log.debug("Removing heart beat service");
+ }
+ UserStoreRoleMappingDataHolder.getInstance().setHeartBeatService(null);
+ }
+}
diff --git a/components/device-mgt-extensions/pom.xml b/components/device-mgt-extensions/pom.xml
index 5dbed0b826..814cfe0181 100644
--- a/components/device-mgt-extensions/pom.xml
+++ b/components/device-mgt-extensions/pom.xml
@@ -43,6 +43,7 @@
io.entgra.device.mgt.core.device.mgt.extensions.logger
io.entgra.device.mgt.core.device.mgt.extensions.defaultrole.manager
io.entgra.device.mgt.core.device.mgt.extensions.stateengine
+ io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper
diff --git a/features/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/pom.xml b/features/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/pom.xml
new file mode 100644
index 0000000000..d06c47c7a8
--- /dev/null
+++ b/features/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/pom.xml
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+ io.entgra.device.mgt.core
+ device-mgt-extensions-feature
+ 5.0.31-SNAPSHOT
+ ../pom.xml
+
+
+ 4.0.0
+ io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper.feature
+ pom
+ Entgra IoT - User store role mapper feature
+ http://entgra.io
+
+ This feature contains the core bundles required for user store role mapping functionality
+
+
+
+
+ io.entgra.device.mgt.core
+ io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper
+
+
+
+
+
+
+ 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.device.mgt.core.device.mgt.extensions.userstore.role.mapper
+ ../../etc/feature.properties
+
+
+ org.wso2.carbon.p2.category.type:server
+
+ org.eclipse.equinox.p2.type.group:true
+
+
+
+
+
+ io.entgra.device.mgt.core:io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper:${io.entgra.device.mgt.core.version}
+
+
+
+
+
+
+
+
+
diff --git a/features/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/resources/build.properties b/features/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/resources/build.properties
new file mode 100644
index 0000000000..89aee3ff76
--- /dev/null
+++ b/features/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/resources/build.properties
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2018 - 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.
+#
+
+custom = true
diff --git a/features/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/resources/conf/user-store-role-mapping-config.xml b/features/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/resources/conf/user-store-role-mapping-config.xml
new file mode 100644
index 0000000000..16316f47ad
--- /dev/null
+++ b/features/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/resources/conf/user-store-role-mapping-config.xml
@@ -0,0 +1,35 @@
+
+
+
+ false
+ 30
+ 3600
+
+
+
+ Internal/branch_css
+
+
+
+
+ Internal/branch_css
+
+
+
+
\ No newline at end of file
diff --git a/features/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/resources/p2.inf b/features/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/resources/p2.inf
new file mode 100644
index 0000000000..31d07a5e20
--- /dev/null
+++ b/features/device-mgt-extensions/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper/src/main/resources/p2.inf
@@ -0,0 +1,2 @@
+instructions.configure = \
+org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper_${feature.version}/conf/user-store-role-mapping-config.xml,target:${installFolder}/../../../repository/conf/user-store-role-mapping-config.xml,overwrite:true);\
diff --git a/features/device-mgt-extensions/pom.xml b/features/device-mgt-extensions/pom.xml
index 36516f0fe8..e941289b7d 100644
--- a/features/device-mgt-extensions/pom.xml
+++ b/features/device-mgt-extensions/pom.xml
@@ -41,6 +41,7 @@
io.entgra.device.mgt.core.device.mgt.extensions.defaultrole.manager.feature
io.entgra.device.mgt.core.device.mgt.extensions.logger.feature
io.entgra.device.mgt.core.device.mgt.extensions.stateengine.feature
+ io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper
diff --git a/pom.xml b/pom.xml
index eeee195f4a..627b0479fe 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1631,6 +1631,11 @@
io.entgra.device.mgt.core.device.mgt.extensions.defaultrole.manager
${io.entgra.device.mgt.core.version}
+
+ io.entgra.device.mgt.core
+ io.entgra.device.mgt.core.device.mgt.extensions.userstore.role.mapper
+ ${io.entgra.device.mgt.core.version}
+
io.entgra.device.mgt.core
io.entgra.device.mgt.core.device.mgt.extensions.logger