diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/AuthenticationHandler.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/AuthenticationHandler.java index c9873629b7..464dfc248d 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/AuthenticationHandler.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/AuthenticationHandler.java @@ -232,4 +232,4 @@ public class AuthenticationHandler extends AbstractHandler { map.put(CONTENT_TYPE, "application/json"); return map; } -} \ No newline at end of file +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/utils/AuthConstants.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/utils/AuthConstants.java index f2a9f7a42b..d9a9ef8a7b 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/utils/AuthConstants.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/utils/AuthConstants.java @@ -24,6 +24,7 @@ public class AuthConstants { public static final String MDM_SIGNATURE = "mdm-signature"; public static final String PROXY_MUTUAL_AUTH_HEADER = "proxy-mutual-auth-header"; public static final String MUTUAL_AUTH_HEADER = "mutual-auth-header"; + public static final String ONE_TIME_TOKEN_HEADER = "one-time-token"; public static final String ENCODED_PEM = "encoded-pem"; public static final String CALLBACK_URL = ""; public static final String CLIENT_NAME = "IOT-API-MANAGER"; diff --git a/components/device-mgt/io.entgra.carbon.device.mgt.config.api/pom.xml b/components/device-mgt/io.entgra.carbon.device.mgt.config.api/pom.xml index 8ffc22a4ec..fe1ff78a87 100644 --- a/components/device-mgt/io.entgra.carbon.device.mgt.config.api/pom.xml +++ b/components/device-mgt/io.entgra.carbon.device.mgt.config.api/pom.xml @@ -273,5 +273,9 @@ + + org.wso2.carbon.multitenancy + org.wso2.carbon.tenant.mgt + diff --git a/components/device-mgt/io.entgra.carbon.device.mgt.config.api/src/main/webapp/WEB-INF/web.xml b/components/device-mgt/io.entgra.carbon.device.mgt.config.api/src/main/webapp/WEB-INF/web.xml index 6b397c9fbe..aafbcec0e0 100644 --- a/components/device-mgt/io.entgra.carbon.device.mgt.config.api/src/main/webapp/WEB-INF/web.xml +++ b/components/device-mgt/io.entgra.carbon.device.mgt.config.api/src/main/webapp/WEB-INF/web.xml @@ -124,4 +124,4 @@ /* - \ No newline at end of file + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/UserManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/UserManagementService.java index 397c35b336..5e580f6a06 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/UserManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/UserManagementService.java @@ -35,7 +35,6 @@ package org.wso2.carbon.device.mgt.jaxrs.service.api; import com.google.gson.JsonArray; -import com.google.gson.JsonObject; import io.swagger.annotations.SwaggerDefinition; import io.swagger.annotations.Info; import io.swagger.annotations.ExtensionProperty; @@ -50,6 +49,7 @@ import io.swagger.annotations.ResponseHeader; import org.apache.axis2.transport.http.HTTPConstants; import org.wso2.carbon.apimgt.annotations.api.Scopes; import org.wso2.carbon.apimgt.annotations.api.Scope; +import org.wso2.carbon.device.mgt.common.invitation.mgt.DeviceEnrollmentInvitation; import org.wso2.carbon.device.mgt.jaxrs.beans.ActivityList; import org.wso2.carbon.device.mgt.jaxrs.beans.BasicUserInfo; import org.wso2.carbon.device.mgt.jaxrs.beans.BasicUserInfoList; @@ -75,7 +75,6 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import java.util.List; @SwaggerDefinition( info = @Info( @@ -894,7 +893,8 @@ public interface UserManagementService { @ApiParam( name = "users", value = "List of users", - required = true) List usernames); + required = true) + @Valid DeviceEnrollmentInvitation deviceEnrollmentInvitation); @POST @Path("/enrollment-invite") 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 a4ca3f026d..73a07b7aad 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 @@ -1288,6 +1288,10 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { operation.setId(operationStatusBean.getOperationId()); DeviceMgtAPIUtils.getDeviceManagementService().updateOperation(device, operation); return Response.status(Response.Status.OK).entity("OperationStatus updated successfully.").build(); + } catch (BadRequestException e) { + String msg = "Error occured due to invalid request"; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); } catch (DeviceManagementException e) { String msg = "Error occurred when fetching device " + deviceIdentifier.toString(); log.error(msg, e); @@ -1296,10 +1300,6 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { String msg = "Error occurred when updating operation of device " + deviceIdentifier; log.error(msg, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); - } catch (BadRequestException e) { - String msg = "Error occured due to invalid request"; - log.error(msg, e); - return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java index 81233092f3..6f240093ec 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java @@ -45,8 +45,11 @@ import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException; import org.wso2.carbon.device.mgt.common.EnrolmentInfo; import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManagementException; +import org.wso2.carbon.device.mgt.common.exceptions.OTPManagementException; +import org.wso2.carbon.device.mgt.common.invitation.mgt.DeviceEnrollmentInvitation; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; +import org.wso2.carbon.device.mgt.common.spi.OTPManagementService; import org.wso2.carbon.device.mgt.core.DeviceManagementConstants; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.EmailMetaInfo; @@ -716,48 +719,29 @@ public class UserManagementServiceImpl implements UserManagementService { return CredentialManagementResponseBuilder.buildChangePasswordResponse(credentials); } - /** - * Method used to send an invitation email to a existing user to enroll a device. - * - * @param usernames Username list of the users to be invited - */ + @POST @Path("/send-invitation") @Produces({MediaType.APPLICATION_JSON}) - public Response inviteExistingUsersToEnrollDevice(List usernames) { + public Response inviteExistingUsersToEnrollDevice(DeviceEnrollmentInvitation deviceEnrollmentInvitation) { + if (deviceEnrollmentInvitation.getUsernames() == null || deviceEnrollmentInvitation.getUsernames().isEmpty()) { + String msg = "Error occurred while validating list of user-names. User-names cannot be empty."; + log.error(msg); + throw new BadRequestException( + new ErrorResponse.ErrorResponseBuilder().setCode(HttpStatus.SC_BAD_REQUEST).setMessage(msg) + .build()); + } if (log.isDebugEnabled()) { - log.debug("Sending enrollment invitation mail to existing user."); + log.debug("Sending device enrollment invitation mail to existing user/s."); } - DeviceManagementProviderService dms = DeviceMgtAPIUtils.getDeviceManagementService(); + OTPManagementService oms = DeviceMgtAPIUtils.getOTPManagementService(); try { - for (String username : usernames) { - String recipient = getClaimValue(username, Constants.USER_CLAIM_EMAIL_ADDRESS); - - Properties props = new Properties(); - props.setProperty("first-name", getClaimValue(username, Constants.USER_CLAIM_FIRST_NAME)); - props.setProperty("username", username); - - EmailMetaInfo metaInfo = new EmailMetaInfo(recipient, props); - dms.sendEnrolmentInvitation(DeviceManagementConstants.EmailAttributes.USER_ENROLLMENT_TEMPLATE, - metaInfo); - } - } catch (DeviceManagementException e) { - String msg = "Error occurred while inviting user to enrol their device"; - if (e.getMessage() != null && !e.getMessage().isEmpty()) { - msg = e.getMessage(); - } + oms.sendDeviceEnrollmentInvitationMail(deviceEnrollmentInvitation); + } catch (OTPManagementException e) { + String msg = "Error occurred while generating OTP and inviting user/s to enroll their device/s."; log.error(msg, e); return Response.serverError().entity( new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); - } catch (UserStoreException e) { - String msg = "Error occurred while getting claim values to invite user"; - log.error(msg, e); - return Response.serverError().entity( - new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); - } catch (ConfigurationManagementException e) { - String msg = "Error occurred while sending the email invitations. Mail server not configured."; - return Response.serverError().entity( - new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); } return Response.status(Response.Status.OK).entity("Invitation mails have been sent.").build(); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java index 31b9543d08..56f2a76e36 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java @@ -14,6 +14,23 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * 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.jaxrs.util; @@ -52,6 +69,7 @@ import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; import org.wso2.carbon.device.mgt.common.permission.mgt.PermissionManagerService; import org.wso2.carbon.device.mgt.common.report.mgt.ReportManagementService; import org.wso2.carbon.device.mgt.common.spi.DeviceTypeGeneratorService; +import org.wso2.carbon.device.mgt.common.spi.OTPManagementService; import org.wso2.carbon.device.mgt.core.app.mgt.ApplicationManagementProviderService; import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceInformationManager; import org.wso2.carbon.device.mgt.core.dto.DeviceTypeVersion; @@ -134,13 +152,14 @@ public class DeviceMgtAPIUtils { public static final String DAS_ADMIN_SERVICE_EP = "https://" + DAS_HOST_NAME + ":" + DAS_PORT + "/services/"; private static SSLContext sslContext; - private static Log log = LogFactory.getLog(DeviceMgtAPIUtils.class); + private static final Log log = LogFactory.getLog(DeviceMgtAPIUtils.class); private static KeyStore keyStore; private static KeyStore trustStore; private static char[] keyStorePassword; private static IntegrationClientService integrationClientService; private static MetadataManagementService metadataManagementService; + private static OTPManagementService otpManagementService; static { String keyStorePassword = ServerConfiguration.getInstance().getFirstProperty("Security.KeyStore.Password"); @@ -337,6 +356,25 @@ public class DeviceMgtAPIUtils { return integrationClientService; } + /** + * Initializing and accessing method for OTPManagementService. + * + * @return OTPManagementService instance + * @throws IllegalStateException if OTPManagementService cannot be initialized + */ + public static synchronized OTPManagementService getOTPManagementService() { + if (otpManagementService == null) { + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + otpManagementService = (OTPManagementService) ctx.getOSGiService(OTPManagementService.class, null); + if (otpManagementService == null) { + String msg = "OTP Management service has not initialized."; + log.error(msg); + throw new IllegalStateException(msg); + } + } + return otpManagementService; + } + public static RegistryService getRegistryService() { RegistryService registryService; PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/test/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImplTest.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/test/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImplTest.java index 13942afb25..aa2f84733f 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/test/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImplTest.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/test/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImplTest.java @@ -15,6 +15,23 @@ * specific language governing permissions and limitations * under the License. * + * + * 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.jaxrs.service.impl; @@ -34,6 +51,10 @@ import org.testng.annotations.Test; import org.wso2.carbon.context.CarbonContext; import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException; import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManagementException; +import org.wso2.carbon.device.mgt.common.exceptions.OTPManagementException; +import org.wso2.carbon.device.mgt.common.invitation.mgt.DeviceEnrollmentInvitation; +import org.wso2.carbon.device.mgt.common.spi.OTPManagementService; +import org.wso2.carbon.device.mgt.core.otp.mgt.service.OTPManagementServiceImpl; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderServiceImpl; import org.wso2.carbon.device.mgt.jaxrs.beans.BasicUserInfo; @@ -66,9 +87,11 @@ public class UserManagementServiceImplTest { private UserStoreManager userStoreManager; private UserManagementService userManagementService; private DeviceManagementProviderService deviceManagementProviderService; + private OTPManagementService otpManagementService; private static final String DEFAULT_DEVICE_USER = "Internal/devicemgt-user"; private UserRealm userRealm; private EnrollmentInvitation enrollmentInvitation; + private DeviceEnrollmentInvitation deviceEnrollmentInvitation; private List userList; private static final String TEST_USERNAME = "test"; private static final String TEST2_USERNAME = "test2"; @@ -86,6 +109,7 @@ public class UserManagementServiceImplTest { userStoreManager = Mockito.mock(UserStoreManager.class, Mockito.RETURNS_MOCKS); deviceManagementProviderService = Mockito .mock(DeviceManagementProviderServiceImpl.class, Mockito.CALLS_REAL_METHODS); + otpManagementService = Mockito.mock(OTPManagementServiceImpl.class, Mockito.CALLS_REAL_METHODS); userRealm = Mockito.mock(UserRealm.class); RealmConfiguration realmConfiguration = Mockito.mock(RealmConfiguration.class); Mockito.doReturn(null).when(realmConfiguration).getSecondaryRealmConfig(); @@ -97,6 +121,8 @@ public class UserManagementServiceImplTest { enrollmentInvitation.setRecipients(recipients); userList = new ArrayList<>(); userList.add(TEST_USERNAME); + deviceEnrollmentInvitation = new DeviceEnrollmentInvitation(); + deviceEnrollmentInvitation.setUsernames(userList); } @Test(description = "This method tests the addUser method of UserManagementService") @@ -205,13 +231,11 @@ public class UserManagementServiceImplTest { @Test(description = "This method tests the send invitation method of UserManagementService", dependsOnMethods = {"testIsUserExists"}) - public void testSendInvitation() throws ConfigurationManagementException, DeviceManagementException { - PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getUserStoreManager")) - .toReturn(this.userStoreManager); - PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService")) - .toReturn(this.deviceManagementProviderService); - Mockito.doNothing().when(deviceManagementProviderService).sendEnrolmentInvitation(Mockito.any(), Mockito.any()); - Response response = userManagementService.inviteExistingUsersToEnrollDevice(userList); + public void testSendInvitation() throws OTPManagementException { + PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getOTPManagementService")) + .toReturn(this.otpManagementService); + Mockito.doNothing().when(otpManagementService).sendDeviceEnrollmentInvitationMail(Mockito.any()); + Response response = userManagementService.inviteExistingUsersToEnrollDevice(deviceEnrollmentInvitation); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode(), "Inviting existing users to enroll device failed"); } @@ -240,7 +264,7 @@ public class UserManagementServiceImplTest { @Test(description = "This method tests the inviteToEnrollDevice method of UserManagementService", dependsOnMethods = "testGetUsers") - public void testInviteToEnrollDevice() { + public void testInviteToEnrollDevice() throws ConfigurationManagementException, DeviceManagementException { URL resourceUrl = ClassLoader.getSystemResource("testng.xml"); System.setProperty("carbon.home", resourceUrl.getPath()); PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getUserStoreManager")) @@ -248,6 +272,7 @@ public class UserManagementServiceImplTest { PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getAuthenticatedUser")).toReturn(TEST_USERNAME); PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService")) .toReturn(this.deviceManagementProviderService); + Mockito.doNothing().when(deviceManagementProviderService).sendEnrolmentInvitation(Mockito.any(), Mockito.any()); EnrollmentInvitation enrollmentInvitation = new EnrollmentInvitation(); List recipients = new ArrayList<>(); recipients.add(TEST_USERNAME); @@ -289,16 +314,22 @@ public class UserManagementServiceImplTest { @Test(description = "This method tests the behaviour of methods when there is an issue with " + "DeviceManagementProviderService", dependsOnMethods = {"testGetUserCount"}) - public void testNegativeScenarios1() throws ConfigurationManagementException, DeviceManagementException { + public void testNegativeScenarios1() + throws ConfigurationManagementException, DeviceManagementException, OTPManagementException { PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getUserStoreManager")) .toReturn(this.userStoreManager); PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService")) .toReturn(this.deviceManagementProviderService); PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getAuthenticatedUser")).toReturn(TEST_USERNAME); Mockito.reset(deviceManagementProviderService); + PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getOTPManagementService")) + .toReturn(this.otpManagementService); + Mockito.reset(otpManagementService); Mockito.doThrow(new DeviceManagementException()).when(deviceManagementProviderService) .sendEnrolmentInvitation(Mockito.any(), Mockito.any()); - Response response = userManagementService.inviteExistingUsersToEnrollDevice(userList); + Mockito.doThrow(new OTPManagementException()).when(otpManagementService) + .sendDeviceEnrollmentInvitationMail(Mockito.any()); + Response response = userManagementService.inviteExistingUsersToEnrollDevice(deviceEnrollmentInvitation); Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), "Invite existing users to enroll device succeeded under erroneous conditions"); response = userManagementService.inviteToEnrollDevice(enrollmentInvitation); @@ -346,6 +377,8 @@ public class UserManagementServiceImplTest { PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService")) .toReturn(this.deviceManagementProviderService); Mockito.reset(this.userStoreManager); + PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getOTPManagementService")) + .toReturn(this.otpManagementService); Mockito.doThrow(new UserStoreException()).when(userStoreManager) .getUserClaimValue(Mockito.any(), Mockito.any(), Mockito.any()); Mockito.doThrow(new UserStoreException()).when(userStoreManager) @@ -362,7 +395,7 @@ public class UserManagementServiceImplTest { response = userManagementService.inviteToEnrollDevice(enrollmentInvitation); Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), "Invite existing users to enroll device succeeded under erroneous conditions"); - response = userManagementService.inviteExistingUsersToEnrollDevice(userList); + response = userManagementService.inviteExistingUsersToEnrollDevice(deviceEnrollmentInvitation); Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), "Invite existing users to enroll device succeeded under erroneous conditions"); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DeviceManagementConstants.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DeviceManagementConstants.java index 20b4f5b626..492288febb 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DeviceManagementConstants.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DeviceManagementConstants.java @@ -125,4 +125,14 @@ public final class DeviceManagementConstants { public static final String DEFAULT_HTTP_PROTOCOL = "https"; public static final String DAS_URL = DEFAULT_HTTP_PROTOCOL + "://" + DAS_HOST_NAME + ":" + DAS_PORT; } + + public static final class OTPProperties { + private OTPProperties() { throw new AssertionError(); } + + public static final String FIRST_NAME = "first-name"; + public static final String LAST_NAME = "last-name"; + public static final String TENANT_ADMIN_USERNAME = "tenant-admin-username"; + public static final String TENANT_ADMIN_PASSWORD = "tenant-admin-password"; + } + } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/BadRequestException.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/BadRequestException.java index b7d99da0e0..ed681b8140 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/BadRequestException.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/BadRequestException.java @@ -19,7 +19,7 @@ package org.wso2.carbon.device.mgt.common.exceptions; -public class BadRequestException extends Exception { +public class BadRequestException extends DeviceManagementException { private static final long serialVersionUID = 2304023531260840549L; public BadRequestException() { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/DBConnectionException.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/DBConnectionException.java new file mode 100644 index 0000000000..a47449c060 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/DBConnectionException.java @@ -0,0 +1,33 @@ +/* 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.common.exceptions; + +/** + * Exception thrown due to Database Connection issues. + */ +public class DBConnectionException extends Exception { + + private static final long serialVersionUID = -6779125067467878014L; + + public DBConnectionException(String message, Throwable cause) { + super(message, cause); + } + + public DBConnectionException(String msg) { + super(msg); + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/OTPManagementException.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/OTPManagementException.java new file mode 100644 index 0000000000..3dd3bee07f --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/OTPManagementException.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * you may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.wso2.carbon.device.mgt.common.exceptions; + +public class OTPManagementException extends Exception { + + private static final long serialVersionUID = 397485329551276175L; + + public OTPManagementException(String msg, Exception nestedEx) { + super(msg, nestedEx); + } + + public OTPManagementException(String message, Throwable cause) { + super(message, cause); + } + + public OTPManagementException(String msg) { + super(msg); + } + + public OTPManagementException() { + super(); + } + + public OTPManagementException(Throwable cause) { + super(cause); + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/UnAuthorizedException.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/UnAuthorizedException.java new file mode 100644 index 0000000000..6c3d5c6346 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/UnAuthorizedException.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2020, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved. + * + * Entgra (pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.wso2.carbon.device.mgt.common.exceptions; + +public class UnAuthorizedException extends DeviceManagementException { + private static final long serialVersionUID = 2304023531260840549L; + + public UnAuthorizedException() { + super(); + } + + public UnAuthorizedException(String msg) { + super(msg); + } + + public UnAuthorizedException(Throwable cause) { + super(cause); + } + + public UnAuthorizedException(String msg, Exception nestedEx) { + super(msg, nestedEx); + } + + public UnAuthorizedException(String message, Throwable cause) { + super(message, cause); + } +} + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/general/OneTimeTokenDetails.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/general/OneTimeTokenDetails.java new file mode 100644 index 0000000000..f204a1f390 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/general/OneTimeTokenDetails.java @@ -0,0 +1,96 @@ +/* + * 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.common.general; + +import java.util.Map; + +public class OneTimeTokenDetails extends TenantDetail { + + String password; + String token; + long createdDate; + long updatedDate; + boolean isExpired; + String metaInfo; + Map replaceValue; + String emailType; + + public long getCreatedDate() { + return createdDate; + } + + public void setCreatedDate(long createdDate) { + this.createdDate = createdDate; + } + + public long getUpdatedDate() { + return updatedDate; + } + + public void setUpdatedDate(long updatedDate) { + this.updatedDate = updatedDate; + } + + public boolean isExpired() { + return isExpired; + } + + public void setExpired(boolean expired) { + isExpired = expired; + } + + public String getMetaInfo() { + return metaInfo; + } + + public void setMetaInfo(String metaInfo) { + this.metaInfo = metaInfo; + } + + public Map getReplaceValue() { + return replaceValue; + } + + public void setReplaceValue(Map replaceValue) { + this.replaceValue = replaceValue; + } + + public String getEmailType() { + return emailType; + } + + public void setEmailType(String emailType) { + this.emailType = emailType; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/invitation/mgt/DeviceEnrollmentInvitation.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/invitation/mgt/DeviceEnrollmentInvitation.java new file mode 100644 index 0000000000..0bdb03e921 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/invitation/mgt/DeviceEnrollmentInvitation.java @@ -0,0 +1,59 @@ +/* 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.common.invitation.mgt; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.io.Serializable; +import java.util.List; + +@ApiModel( + value = "DeviceEnrollmentInvitation", + description = "Holds data to send device enrollment invitation to list of existing users.") +public class DeviceEnrollmentInvitation implements Serializable { + + private static final long serialVersionUID = 6933837278652532052L; + + @ApiModelProperty( + name = "usernames", + value = "List of usernames of users.", + required = true) + private List usernames; + + @ApiModelProperty( + name = "deviceEnrollmentTypes", + value = "List of enrollment types against device types.") + private List deviceEnrollmentTypes; + + public List getUsernames() { + return usernames; + } + + public void setUsernames(List usernames) { + this.usernames = usernames; + } + + public List getDeviceEnrollmentTypes() { + return deviceEnrollmentTypes; + } + + public void setDeviceEnrollmentTypes( + List deviceEnrollmentTypes) { + this.deviceEnrollmentTypes = deviceEnrollmentTypes; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/invitation/mgt/DeviceEnrollmentInvitationDetails.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/invitation/mgt/DeviceEnrollmentInvitationDetails.java new file mode 100644 index 0000000000..3882d47293 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/invitation/mgt/DeviceEnrollmentInvitationDetails.java @@ -0,0 +1,25 @@ +package org.wso2.carbon.device.mgt.common.invitation.mgt; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; +import java.util.List; + +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "DeviceEnrollmentInvitationDetails", propOrder = { + "enrollmentDetails" +}) +public class DeviceEnrollmentInvitationDetails { + + @XmlElement(name = "EnrollmentDetails") + private List enrollmentDetails; + + public List getEnrollmentDetails() { + return enrollmentDetails; + } + + public void setEnrollmentDetails(List enrollmentDetails) { + this.enrollmentDetails = enrollmentDetails; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/invitation/mgt/DeviceEnrollmentType.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/invitation/mgt/DeviceEnrollmentType.java new file mode 100644 index 0000000000..0124fde36d --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/invitation/mgt/DeviceEnrollmentType.java @@ -0,0 +1,59 @@ +/* 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.common.invitation.mgt; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.io.Serializable; +import java.util.List; + +@ApiModel( + value = "DeviceEnrollmentType", + description = "Holds data of enrollment types against device types.") +public class DeviceEnrollmentType implements Serializable { + + private static final long serialVersionUID = 6563596191450032613L; + + @ApiModelProperty( + name = "deviceType", + value = "Device type (i.e: android, ios, windows)", + required = true) + private String deviceType; + + @ApiModelProperty( + name = "enrollmentType", + value = "Enrollment type (i.e: BYOD, COPE, COSU)", + required = true) + private List enrollmentType; + + public String getDeviceType() { + return deviceType; + } + + public void setDeviceType(String deviceType) { + this.deviceType = deviceType; + } + + public List getEnrollmentType() { + return enrollmentType; + } + + public void setEnrollmentType(List enrollmentType) { + this.enrollmentType = enrollmentType; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/invitation/mgt/EnrollmentDetails.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/invitation/mgt/EnrollmentDetails.java new file mode 100644 index 0000000000..905022440b --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/invitation/mgt/EnrollmentDetails.java @@ -0,0 +1,36 @@ +package org.wso2.carbon.device.mgt.common.invitation.mgt; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "EnrollmentDetails", propOrder = { + "enrollmentType", + "enrollmentSteps" +}) +public class EnrollmentDetails { + + @XmlElement(name = "EnrollmentType") + private String enrollmentType; + + @XmlElement(name = "EnrollmentSteps") + private String enrollmentSteps; + + public String getEnrollmentType() { + return enrollmentType; + } + + public void setEnrollmentType(String enrollmentType) { + this.enrollmentType = enrollmentType; + } + + public String getEnrollmentSteps() { + return enrollmentSteps; + } + + public void setEnrollmentSteps(String enrollmentSteps) { + this.enrollmentSteps = enrollmentSteps; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/otp/mgt/OTPEmailTypes.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/otp/mgt/OTPEmailTypes.java new file mode 100644 index 0000000000..72bbea982e --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/otp/mgt/OTPEmailTypes.java @@ -0,0 +1,22 @@ +/* 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.common.otp.mgt; + +public enum OTPEmailTypes { + USER_VERIFY, DEVICE_ENROLLMENT +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/otp/mgt/dto/OneTimePinDTO.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/otp/mgt/dto/OneTimePinDTO.java new file mode 100644 index 0000000000..11923947c1 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/otp/mgt/dto/OneTimePinDTO.java @@ -0,0 +1,113 @@ +/* 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.common.otp.mgt.dto; + +import java.sql.Timestamp; + +public class OneTimePinDTO { + + int id; + String otpToken; + int tenantId; + String username; + String email; + String emailType; + String metaInfo; + Timestamp createdAt; + int expiryTime; + boolean isExpired; + + public int getTenantId() { + return tenantId; + } + + public void setTenantId(int tenantId) { + this.tenantId = tenantId; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getOtpToken() { + return otpToken; + } + + public void setOtpToken(String otpToken) { + this.otpToken = otpToken; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getEmailType() { + return emailType; + } + + public void setEmailType(String emailType) { + this.emailType = emailType; + } + + public String getMetaInfo() { return metaInfo; } + + public void setMetaInfo(String metaInfo) { + this.metaInfo = metaInfo; + } + + public Timestamp getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Timestamp createdAt) { + this.createdAt = createdAt; + } + + public int getExpiryTime() { + return expiryTime; + } + + public void setExpiryTime(int expiryTime) { + this.expiryTime = expiryTime; + } + + public boolean isExpired() { + return isExpired; + } + + public void setExpired(boolean expired) { + isExpired = expired; + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/otp/mgt/wrapper/OTPWrapper.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/otp/mgt/wrapper/OTPWrapper.java new file mode 100644 index 0000000000..319da774d1 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/otp/mgt/wrapper/OTPWrapper.java @@ -0,0 +1,53 @@ +/* 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.common.otp.mgt.wrapper; + +import org.wso2.carbon.device.mgt.common.metadata.mgt.Metadata; + +import java.util.List; + +public class OTPWrapper { + + private String email; + private String emailType; + private String username; + private List properties; + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getEmailType() { + return emailType; + } + + public void setEmailType(String emailType) { + this.emailType = emailType; + } + + public String getUsername() { return username; } + + public void setUsername(String username) { this.username = username; } + + public List getProperties() { return properties; } + + public void setProperties(List properties) { this.properties = properties; } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/spi/DeviceManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/spi/DeviceManagementService.java index 25303cf966..e6f33f85de 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/spi/DeviceManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/spi/DeviceManagementService.java @@ -38,6 +38,7 @@ import org.wso2.carbon.device.mgt.common.*; import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManager; import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException; import org.wso2.carbon.device.mgt.common.general.GeneralConfig; +import org.wso2.carbon.device.mgt.common.invitation.mgt.DeviceEnrollmentInvitationDetails; import org.wso2.carbon.device.mgt.common.policy.mgt.PolicyMonitoringManager; import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationSubscriber; import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationConfig; @@ -77,4 +78,6 @@ public interface DeviceManagementService { DeviceTypePlatformDetails getDeviceTypePlatformDetails(); + DeviceEnrollmentInvitationDetails getDeviceEnrollmentInvitationDetails(); + } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/spi/OTPManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/spi/OTPManagementService.java new file mode 100644 index 0000000000..f63a95ca32 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/spi/OTPManagementService.java @@ -0,0 +1,65 @@ +/* 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.common.spi; + +import org.wso2.carbon.device.mgt.common.exceptions.BadRequestException; +import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException; +import org.wso2.carbon.device.mgt.common.exceptions.OTPManagementException; +import org.wso2.carbon.device.mgt.common.invitation.mgt.DeviceEnrollmentInvitation; +import org.wso2.carbon.device.mgt.common.otp.mgt.dto.OneTimePinDTO; +import org.wso2.carbon.device.mgt.common.otp.mgt.wrapper.OTPWrapper; + +import java.util.Map; + +public interface OTPManagementService { + + /** + * Create OTP token and store tenant details in the DB + * @param otpWrapper OTP Mail Wrapper object which contains tenant details of registering user + * @throws OTPManagementException if error occurs while creating OTP token and storing tenant details. + * @throws BadRequestException if found and incompatible payload to create OTP token. + */ + void sendUserVerifyingMail(OTPWrapper otpWrapper) throws OTPManagementException, DeviceManagementException; + + /** + * Check the validity of the OTP + * @param oneTimeToken OTP + * @return The OTP data + * @throws OTPManagementException if error occurred whle verifying validity of the OPT + * @throws BadRequestException if found an null value for OTP + */ + OneTimePinDTO isValidOTP(String oneTimeToken) throws OTPManagementException, BadRequestException; + + /** + * Invalidate the OTP and send welcome mail + * @param oneTimeToken OTP + * @param email email address + * @param properties email properties to add to email body + * @throws OTPManagementException if error occurred while invalidate the OTP or send welcome email + */ + void completeSelfRegistration(String oneTimeToken, String email, Map properties) + throws OTPManagementException; + + /** + * Create OTP token and send device enrollment invitation + * @param deviceEnrollmentInvitation object which contains device enrollment invitation related details + * @throws OTPManagementException if error occurred while creating OTP token &/ sending mail + */ + void sendDeviceEnrollmentInvitationMail(DeviceEnrollmentInvitation deviceEnrollmentInvitation) + throws OTPManagementException; +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/pom.xml b/components/device-mgt/org.wso2.carbon.device.mgt.core/pom.xml index 4d1c23ba6c..347c710be6 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/pom.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/pom.xml @@ -360,6 +360,10 @@ org.wso2.carbon.multitenancy org.wso2.carbon.tenant.mgt + + commons-validator + commons-validator + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/DeviceManagementConstants.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/DeviceManagementConstants.java index 1b402560b7..b09d6fad9d 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/DeviceManagementConstants.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/DeviceManagementConstants.java @@ -116,6 +116,8 @@ public final class DeviceManagementConstants { public static final String USER_REGISTRATION_TEMPLATE = "user-registration"; public static final String USER_ENROLLMENT_TEMPLATE = "user-enrollment"; + public static final String USER_VERIFY_TEMPLATE = "user-verify"; + public static final String USER_WELCOME_TEMPLATE = "user-welcome"; public static final String DEFAULT_ENROLLMENT_TEMPLATE = "default-enrollment-invitation"; } @@ -142,6 +144,9 @@ public final class DeviceManagementConstants { public static final String DEFAULT_DEVICE_USER = "Internal/devicemgt-user"; public static final String DEFAULT_DEVICE_ADMIN = "Internal/devicemgt-admin"; + public static final String CLAIM_EMAIL_ADDRESS = "http://wso2.org/claims/emailaddress"; + public static final String CLAIM_FIRST_NAME = "http://wso2.org/claims/givenname"; + // Permissions that are given for a normal device user. public static final Permission[] PERMISSIONS_FOR_DEVICE_USER = { new Permission("/permission/admin/Login", "ui.execute"), 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 daf740fa60..60b309ad76 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 @@ -35,6 +35,7 @@ import org.wso2.carbon.device.mgt.common.permission.mgt.PermissionManagerService import org.wso2.carbon.device.mgt.common.report.mgt.ReportManagementService; import org.wso2.carbon.device.mgt.common.spi.DeviceManagementService; import org.wso2.carbon.device.mgt.common.spi.DeviceTypeGeneratorService; +import org.wso2.carbon.device.mgt.common.spi.OTPManagementService; import org.wso2.carbon.device.mgt.core.DeviceManagementConstants; import org.wso2.carbon.device.mgt.core.app.mgt.ApplicationManagementProviderService; import org.wso2.carbon.device.mgt.core.app.mgt.ApplicationManagerProviderServiceImpl; @@ -56,6 +57,8 @@ import org.wso2.carbon.device.mgt.core.notification.mgt.NotificationManagementSe import org.wso2.carbon.device.mgt.core.notification.mgt.dao.NotificationManagementDAOFactory; import org.wso2.carbon.device.mgt.core.operation.mgt.OperationManagerImpl; import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.otp.mgt.dao.OTPManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.otp.mgt.service.OTPManagementServiceImpl; import org.wso2.carbon.device.mgt.core.permission.mgt.PermissionManagerServiceImpl; import org.wso2.carbon.device.mgt.core.privacy.PrivacyComplianceProvider; import org.wso2.carbon.device.mgt.core.privacy.impl.PrivacyComplianceProviderImpl; @@ -178,6 +181,7 @@ public class DeviceManagementServiceComponent { NotificationManagementDAOFactory.init(dsConfig); OperationManagementDAOFactory.init(dsConfig); MetadataManagementDAOFactory.init(dsConfig); + OTPManagementDAOFactory.init(dsConfig.getJndiLookupDefinition().getJndiName()); /*Initialize the device cache*/ DeviceManagerUtil.initializeDeviceCache(); @@ -330,7 +334,10 @@ public class DeviceManagementServiceComponent { MetadataManagementService metadataManagementService = new MetadataManagementServiceImpl(); bundleContext.registerService(MetadataManagementService.class.getName(), metadataManagementService, null); - /* Registering App Management service */ + OTPManagementService otpManagementService = new OTPManagementServiceImpl(); + bundleContext.registerService(OTPManagementService.class.getName(), otpManagementService, null); + + /* Registering App Management service */ try { AppManagementConfigurationManager.getInstance().initConfig(); AppManagementConfig appConfig = diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/AbstractDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/AbstractDAOImpl.java new file mode 100644 index 0000000000..ea9faf7ee0 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/AbstractDAOImpl.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2019, Entgra (pvt) Ltd. (http://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.otp.mgt.dao; + +import org.wso2.carbon.device.mgt.common.exceptions.DBConnectionException; +import org.wso2.carbon.device.mgt.core.otp.mgt.util.ConnectionManagerUtil; + +import java.sql.Connection; + +/** + * This class deals with getting the DB connection. + */ +public abstract class AbstractDAOImpl { + + protected Connection getDBConnection() throws DBConnectionException { + return ConnectionManagerUtil.getDBConnection(); + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/OTPManagementDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/OTPManagementDAO.java new file mode 100644 index 0000000000..4c3690f5d0 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/OTPManagementDAO.java @@ -0,0 +1,64 @@ +/* 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.otp.mgt.dao; + +import org.wso2.carbon.device.mgt.common.otp.mgt.dto.OneTimePinDTO; +import org.wso2.carbon.device.mgt.core.otp.mgt.exception.OTPManagementDAOException; + +public interface OTPManagementDAO { + + /** + * Save OTP token data and tenant details of registering user + * @param oneTimePinDTO OTPMailDTO + * @return Primary key of the newly adding data raw + * @throws OTPManagementDAOException if error occurred whule storing data + */ + int addOTPData(OneTimePinDTO oneTimePinDTO) throws OTPManagementDAOException; + + /** + * Get OTP data for requesting One Time Token + * @param oneTimeToken One Time Token + * @return {@link OneTimePinDTO} + * @throws OTPManagementDAOException if error ocured while getting OTP data for requesting one time token + */ + OneTimePinDTO getOTPDataByToken (String oneTimeToken) throws OTPManagementDAOException; + + /** + * Expire the OTP + * @param oneTimeToken OTP + * @throws OTPManagementDAOException if error occurred while updating the OTP validity. + */ + boolean expireOneTimeToken(String oneTimeToken) throws OTPManagementDAOException; + + /** + * Update OTP with renewed OTP + * @param id ID + * @param oneTimeToken One Time Token + * @throws OTPManagementDAOException if error occured while updating OTP + */ + void renewOneTimeToken(int id, String oneTimeToken) throws OTPManagementDAOException; + + /** + * To veify whether email and email type exists or not + * @param email email + * @param emailType email type + * @return true if email and email type exists otherwise returns false + * @throws OTPManagementDAOException if error occurred while verify existance of the email and email type + */ + boolean isEmailExist (String email, String emailType) throws OTPManagementDAOException; +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/OTPManagementDAOFactory.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/OTPManagementDAOFactory.java new file mode 100644 index 0000000000..5d7ca6c585 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/OTPManagementDAOFactory.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2020, Entgra (pvt) Ltd. (http://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.otp.mgt.dao; + +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.exceptions.UnsupportedDatabaseEngineException; +import org.wso2.carbon.device.mgt.core.otp.mgt.dao.impl.GenericOTPManagementDAOImpl; +import org.wso2.carbon.device.mgt.core.otp.mgt.dao.impl.OracleOTPManagementDAOImpl; +import org.wso2.carbon.device.mgt.core.otp.mgt.dao.impl.PostgreSQLOTPManagementDAOImpl; +import org.wso2.carbon.device.mgt.core.otp.mgt.dao.impl.SQLServerOTPManagementDAOImpl; +import org.wso2.carbon.device.mgt.core.otp.mgt.util.ConnectionManagerUtil; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; + +/** + * This class intends to act as the primary entity that hides all DAO instantiation related complexities and logic so + * that the business objection handling layer doesn't need to be aware of the same providing seamless plug-ability of + * different data sources, connection acquisition mechanisms as well as different forms of DAO implementations to the + * high-level implementations that require Application management related metadata persistence. + */ +public class OTPManagementDAOFactory { + + private static String databaseEngine; + private static final Log log = LogFactory.getLog(OTPManagementDAOFactory.class); + + public static void init(String datasourceName) { + ConnectionManagerUtil.resolveDataSource(datasourceName); + databaseEngine = ConnectionManagerUtil.getDatabaseType(); + } + + public static void init(DataSource dtSource) { + try (Connection connection = dtSource.getConnection()) { + databaseEngine = connection.getMetaData().getDatabaseProductName(); + } catch (SQLException e) { + log.error("Error occurred while retrieving config.datasource connection", e); + } + } + + public static OTPManagementDAO getOTPManagementDAO() { + if (databaseEngine != null) { + switch (databaseEngine) { + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_H2: + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_MYSQL: + return new GenericOTPManagementDAOImpl(); + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_POSTGRESQL: + return new PostgreSQLOTPManagementDAOImpl(); + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_MSSQL: + return new SQLServerOTPManagementDAOImpl(); + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_ORACLE: + return new OracleOTPManagementDAOImpl(); + default: + throw new UnsupportedDatabaseEngineException("Unsupported database engine : " + databaseEngine); + } + } + throw new IllegalStateException("Database engine has not initialized properly."); + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/impl/GenericOTPManagementDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/impl/GenericOTPManagementDAOImpl.java new file mode 100644 index 0000000000..273cf6c1a5 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/impl/GenericOTPManagementDAOImpl.java @@ -0,0 +1,243 @@ +/* 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.otp.mgt.dao.impl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.exceptions.DBConnectionException; +import org.wso2.carbon.device.mgt.common.otp.mgt.dto.OneTimePinDTO; +import org.wso2.carbon.device.mgt.core.otp.mgt.dao.AbstractDAOImpl; +import org.wso2.carbon.device.mgt.core.otp.mgt.dao.OTPManagementDAO; +import org.wso2.carbon.device.mgt.core.otp.mgt.exception.OTPManagementDAOException; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Timestamp; +import java.util.Calendar; + +public class GenericOTPManagementDAOImpl extends AbstractDAOImpl implements OTPManagementDAO { + + private static final Log log = LogFactory.getLog(GenericOTPManagementDAOImpl.class); + + @Override + public int addOTPData(OneTimePinDTO oneTimePinDTO) throws OTPManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to create an OTP data entry"); + log.debug("OTP Details : "); + log.debug("OTP key : " + oneTimePinDTO.getOtpToken() + " Email : " + oneTimePinDTO.getEmail()); + } + + String sql = "INSERT INTO DM_OTP_DATA " + + "(OTP_TOKEN, " + + "EMAIL, " + + "EMAIL_TYPE, " + + "META_INFO, " + + "CREATED_AT," + + "TENANT_ID," + + "USERNAME) VALUES (?, ?, ?, ?, ?, ?, ?)"; + try { + Connection conn = this.getDBConnection(); + Calendar calendar = Calendar.getInstance(); + Timestamp timestamp = new Timestamp(calendar.getTime().getTime()); + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setString(1, oneTimePinDTO.getOtpToken()); + stmt.setString(2, oneTimePinDTO.getEmail()); + stmt.setString(3, oneTimePinDTO.getEmailType()); + stmt.setString(4, oneTimePinDTO.getMetaInfo()); + stmt.setTimestamp(5, timestamp); + stmt.setInt(6, oneTimePinDTO.getTenantId()); + stmt.setString(7, oneTimePinDTO.getUsername()); + stmt.executeUpdate(); + try (ResultSet rs = stmt.getGeneratedKeys()) { + if (rs.next()) { + return rs.getInt(1); + } + return -1; + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to create an opt entry for email " + + oneTimePinDTO.getEmail(); + log.error(msg, e); + throw new OTPManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to create an otp entry for email " + oneTimePinDTO.getEmail(); + log.error(msg, e); + throw new OTPManagementDAOException(msg, e); + } + } + + @Override + public OneTimePinDTO getOTPDataByToken (String oneTimeToken) throws OTPManagementDAOException { + + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to get an OTP data entry for OTP"); + log.debug("OTP Details : OTP key : " + oneTimeToken ); + } + + String sql = "SELECT " + + "ID, " + + "OTP_TOKEN, " + + "EMAIL, " + + "EMAIL_TYPE, " + + "META_INFO, " + + "CREATED_AT, " + + "EXPIRY_TIME, " + + "IS_EXPIRED, " + + "TENANT_ID, " + + "USERNAME FROM DM_OTP_DATA " + + "WHERE OTP_TOKEN = ?"; + + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setString(1, oneTimeToken); + + try (ResultSet rs = stmt.executeQuery()) { + if (rs.next()) { + OneTimePinDTO oneTimePinDTO = new OneTimePinDTO(); + oneTimePinDTO.setId(rs.getInt("ID")); + oneTimePinDTO.setOtpToken(rs.getString("OTP_TOKEN")); + oneTimePinDTO.setEmail(rs.getString("EMAIL")); + oneTimePinDTO.setEmailType(rs.getString("EMAIL_TYPE")); + oneTimePinDTO.setMetaInfo(rs.getString("META_INFO")); + oneTimePinDTO.setCreatedAt(rs.getTimestamp("CREATED_AT")); + oneTimePinDTO.setExpiryTime(rs.getInt("EXPIRY_TIME")); + oneTimePinDTO.setExpired(rs.getBoolean("IS_EXPIRED")); + oneTimePinDTO.setTenantId(rs.getInt("TENANT_ID")); + oneTimePinDTO.setUsername(rs.getString("USERNAME")); + return oneTimePinDTO; + } + return null; + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to get OPT data for given OTP. OTP: " + + oneTimeToken; + log.error(msg, e); + throw new OTPManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to get OTP data for OTP. One time token: " + oneTimeToken; + log.error(msg, e); + throw new OTPManagementDAOException(msg, e); + } + } + + @Override + public boolean expireOneTimeToken(String oneTimeToken) throws OTPManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to update an OTP data entry for OTP"); + log.debug("OTP Details : OTP key : " + oneTimeToken ); + } + + String sql = "UPDATE DM_OTP_DATA " + + "SET " + + "IS_EXPIRED = ? " + + "WHERE OTP_TOKEN = ?"; + + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setBoolean(1, true); + stmt.setString(2, oneTimeToken); + return stmt.executeUpdate() == 1; + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to update the OTP token validity."; + log.error(msg, e); + throw new OTPManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred when obtaining database connection for updating the OTP token validity."; + log.error(msg, e); + throw new OTPManagementDAOException(msg, e); + } + } + + @Override + public void renewOneTimeToken(int id, String oneTimeToken) throws OTPManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to update an OTP data entry for OTP"); + log.debug("OTP Details : OTP key : " + oneTimeToken ); + } + + String sql = "UPDATE DM_OTP_DATA " + + "SET " + + "OTP_TOKEN = ?, " + + "CREATED_AT = ? " + + "WHERE ID = ?"; + + try { + Connection conn = this.getDBConnection(); + Calendar calendar = Calendar.getInstance(); + Timestamp timestamp = new Timestamp(calendar.getTime().getTime()); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setString(1, oneTimeToken); + stmt.setTimestamp(2, timestamp); + stmt.setInt(3, id); + stmt.executeUpdate(); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to update the OTP token."; + log.error(msg, e); + throw new OTPManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred when executing sql query to update the OTP token."; + log.error(msg, e); + throw new OTPManagementDAOException(msg, e); + } + } + + @Override + public boolean isEmailExist (String email, String emailType) throws OTPManagementDAOException { + + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to verify whether email was registed with emai type in OTP"); + log.debug("OTP Details : email : " + email + " email type: " + emailType ); + } + + String sql = "SELECT " + + "ID " + + "FROM DM_OTP_DATA " + + "WHERE EMAIL = ? AND " + + "EMAIL_TYPE = ?"; + + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setString(1, email); + stmt.setString(2, emailType); + try (ResultSet rs = stmt.executeQuery()) { + return rs.next(); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to verify email and email type exist in OTP." + + " Email: " + email + "Email Type: " + emailType; + log.error(msg, e); + throw new OTPManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to verify email and email type exist in OTP. Email: " + + email + "Email Type: " + emailType; + log.error(msg, e); + throw new OTPManagementDAOException(msg, e); + } + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/impl/OracleOTPManagementDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/impl/OracleOTPManagementDAOImpl.java new file mode 100644 index 0000000000..c3feb1262d --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/impl/OracleOTPManagementDAOImpl.java @@ -0,0 +1,24 @@ +/* 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.otp.mgt.dao.impl; + +/** + * This handles OTP managing DAO methods which are specific to Oracle. + */ +public class OracleOTPManagementDAOImpl extends GenericOTPManagementDAOImpl{ +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/impl/PostgreSQLOTPManagementDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/impl/PostgreSQLOTPManagementDAOImpl.java new file mode 100644 index 0000000000..52d705736b --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/impl/PostgreSQLOTPManagementDAOImpl.java @@ -0,0 +1,25 @@ +/* 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.otp.mgt.dao.impl; + +/** + * This handles OTP managing DAO methods which are specific to PostgreSQL. + */ +public class PostgreSQLOTPManagementDAOImpl extends GenericOTPManagementDAOImpl{ + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/impl/SQLServerOTPManagementDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/impl/SQLServerOTPManagementDAOImpl.java new file mode 100644 index 0000000000..222fc9fd7c --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/dao/impl/SQLServerOTPManagementDAOImpl.java @@ -0,0 +1,24 @@ +/* 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.otp.mgt.dao.impl; + +/** + * This handles OTP managing DAO methods which are specific to MSSQL. + */ +public class SQLServerOTPManagementDAOImpl extends GenericOTPManagementDAOImpl{ +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/exception/OTPManagementDAOException.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/exception/OTPManagementDAOException.java new file mode 100644 index 0000000000..6815823bab --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/exception/OTPManagementDAOException.java @@ -0,0 +1,31 @@ +/* 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.otp.mgt.exception; + +/** + * Exception thrown during the ApplicationDTO Management DAO operations. + */ +public class OTPManagementDAOException extends Exception { + + public OTPManagementDAOException(String message, Throwable throwable) { + super(message, throwable); + } + + public OTPManagementDAOException(String message) { + super(message, new Exception()); + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/service/OTPManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/service/OTPManagementServiceImpl.java new file mode 100644 index 0000000000..9b25987e84 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/service/OTPManagementServiceImpl.java @@ -0,0 +1,461 @@ +/* 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.otp.mgt.service; + +import com.google.gson.Gson; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.base.MultitenantConstants; +import org.wso2.carbon.context.CarbonContext; +import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManagementException; +import org.wso2.carbon.device.mgt.common.exceptions.BadRequestException; +import org.wso2.carbon.device.mgt.common.exceptions.DBConnectionException; +import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException; +import org.wso2.carbon.device.mgt.common.exceptions.OTPManagementException; +import org.wso2.carbon.device.mgt.common.exceptions.TransactionManagementException; +import org.wso2.carbon.device.mgt.common.exceptions.UnAuthorizedException; +import org.wso2.carbon.device.mgt.common.invitation.mgt.DeviceEnrollmentInvitation; +import org.wso2.carbon.device.mgt.common.invitation.mgt.DeviceEnrollmentInvitationDetails; +import org.wso2.carbon.device.mgt.common.invitation.mgt.DeviceEnrollmentType; +import org.wso2.carbon.device.mgt.common.metadata.mgt.Metadata; +import org.wso2.carbon.device.mgt.common.otp.mgt.OTPEmailTypes; +import org.wso2.carbon.device.mgt.common.otp.mgt.dto.OneTimePinDTO; +import org.wso2.carbon.device.mgt.common.spi.OTPManagementService; +import org.wso2.carbon.device.mgt.core.DeviceManagementConstants; +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.config.keymanager.KeyManagerConfigurations; +import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; +import org.wso2.carbon.device.mgt.core.otp.mgt.dao.OTPManagementDAO; +import org.wso2.carbon.device.mgt.common.otp.mgt.wrapper.OTPWrapper; +import org.wso2.carbon.device.mgt.core.otp.mgt.dao.OTPManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.otp.mgt.exception.OTPManagementDAOException; +import org.wso2.carbon.device.mgt.core.otp.mgt.util.ConnectionManagerUtil; +import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; +import org.wso2.carbon.device.mgt.core.service.EmailMetaInfo; +import org.apache.commons.validator.routines.EmailValidator; +import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil; +import org.wso2.carbon.user.api.Tenant; +import org.wso2.carbon.user.api.UserStoreException; + +import static org.wso2.carbon.device.mgt.common.DeviceManagementConstants.OTPProperties; + +import java.sql.Timestamp; +import java.util.Calendar; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.UUID; + +public class OTPManagementServiceImpl implements OTPManagementService { + + private static final Log log = LogFactory.getLog(OTPManagementServiceImpl.class); + private OTPManagementDAO otpManagementDAO; + + public OTPManagementServiceImpl() { + initDataAccessObjects(); + } + + private void initDataAccessObjects() { + otpManagementDAO = OTPManagementDAOFactory.getOTPManagementDAO(); + } + + @Override + public void sendUserVerifyingMail(OTPWrapper otpWrapper) throws OTPManagementException, DeviceManagementException { + Tenant tenant = validateTenantCreatingDetails(otpWrapper); + OneTimePinDTO oneTimePinDTO = createOneTimePin(otpWrapper.getEmail(), otpWrapper.getEmailType(), + otpWrapper.getUsername(), tenant, -1234); + try { + ConnectionManagerUtil.beginDBTransaction(); + if (this.otpManagementDAO.addOTPData(oneTimePinDTO) == -1) { + ConnectionManagerUtil.rollbackDBTransaction(); + String msg = "OTP data saving failed. Please, contact Administrator"; + log.error(msg); + throw new OTPManagementException(msg); + } + Properties props = new Properties(); + props.setProperty("first-name", tenant.getAdminFirstName()); + props.setProperty("otp-token", oneTimePinDTO.getOtpToken()); + sendMail(props, tenant.getEmail(), DeviceManagementConstants.EmailAttributes.USER_VERIFY_TEMPLATE); + ConnectionManagerUtil.commitDBTransaction(); + } catch (TransactionManagementException e) { + String msg = "Error occurred while disabling AutoCommit."; + log.error(msg, e); + throw new OTPManagementException(msg, e); + } catch (DBConnectionException e) { + String msg = "Error occurred while getting database connection."; + log.error(msg, e); + throw new OTPManagementException(msg, e); + } catch (OTPManagementDAOException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + String msg = "Error occurred while saving the OTP data. Email address: " + oneTimePinDTO.getEmail(); + log.error(msg, e); + throw new OTPManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + @Override + public OneTimePinDTO isValidOTP(String oneTimeToken) throws OTPManagementException, BadRequestException { + if (StringUtils.isBlank(oneTimeToken)){ + String msg = "Received blank OTP to verify. OTP: " + oneTimeToken; + log.error(msg); + throw new BadRequestException(msg); + } + + OneTimePinDTO oneTimePinDTO = getOTPDataByToken(oneTimeToken); + if (oneTimePinDTO == null) { + String msg = "Couldn't found OTP data for the requesting OTP " + oneTimeToken + " In the system."; + log.error(msg); + throw new BadRequestException(msg); + } + if (oneTimePinDTO.isExpired()) { + log.warn("Token is expired. OTP: " + oneTimeToken); + return null; + } + + Calendar calendar = Calendar.getInstance(); + Timestamp currentTimestamp = new Timestamp(calendar.getTime().getTime()); + Timestamp expiredTimestamp = new Timestamp( + oneTimePinDTO.getCreatedAt().getTime() + oneTimePinDTO.getExpiryTime() * 1000); + + if (currentTimestamp.after(expiredTimestamp)) { + String renewedOTP = UUID.randomUUID().toString(); + renewOTP(oneTimePinDTO, renewedOTP); + Gson gson = new Gson(); + Tenant tenant = gson.fromJson(oneTimePinDTO.getMetaInfo(), Tenant.class); + + Properties props = new Properties(); + props.setProperty("first-name", tenant.getAdminFirstName()); + props.setProperty("otp-token", renewedOTP); + sendMail(props, oneTimePinDTO.getEmail(), DeviceManagementConstants.EmailAttributes.USER_VERIFY_TEMPLATE); + return null; + } + return oneTimePinDTO; + } + + @Override + public void completeSelfRegistration(String oneTimeToken, String email, Map properties) + throws OTPManagementException { + try { + invalidateOTP(oneTimeToken); + Properties props = new Properties(); + properties.forEach(props::setProperty); + sendMail(props, email, DeviceManagementConstants.EmailAttributes.USER_WELCOME_TEMPLATE); + } catch (OTPManagementException e) { + String msg = "Error occurred while completing the self registration via OTP"; + log.error(msg, e); + throw new OTPManagementException(msg, e); + } + } + + /** + * Invalidate the OTP + * @param oneTimeToken OTP + * @throws OTPManagementException If error occurred while invalidating the OTP + */ + private void invalidateOTP(String oneTimeToken) throws OTPManagementException { + try { + ConnectionManagerUtil.beginDBTransaction(); + if (!otpManagementDAO.expireOneTimeToken(oneTimeToken)) { + ConnectionManagerUtil.rollbackDBTransaction(); + String msg = "Couldn't find OTP entry for OTP: " + oneTimeToken; + log.error(msg); + throw new OTPManagementException(msg); + } + ConnectionManagerUtil.commitDBTransaction(); + } catch (OTPManagementDAOException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + String msg = "Error occurred while invalidate the OTP: " + oneTimeToken; + log.error(msg); + throw new OTPManagementException(msg); + } catch (TransactionManagementException e) { + String msg = "Error occurred while disabling AutoCommit to invalidate OTP."; + log.error(msg, e); + throw new OTPManagementException(msg, e); + } catch (DBConnectionException e) { + String msg = "Error occurred while getting database connection to invalidate OPT."; + log.error(msg, e); + throw new OTPManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + + @Override + public void sendDeviceEnrollmentInvitationMail(DeviceEnrollmentInvitation deviceEnrollmentInvitation) + throws OTPManagementException { + DeviceManagementProviderService dms = DeviceManagementDataHolder.getInstance().getDeviceManagementProvider(); + StringBuilder enrollmentSteps = new StringBuilder(); + DeviceEnrollmentInvitationDetails deviceEnrollmentInvitationDetails; + for (DeviceEnrollmentType deviceEnrollmentType : deviceEnrollmentInvitation.getDeviceEnrollmentTypes()) { + deviceEnrollmentInvitationDetails = dms.getDeviceEnrollmentInvitationDetails( + deviceEnrollmentType.getDeviceType()); + if (deviceEnrollmentInvitationDetails != null && + deviceEnrollmentInvitationDetails.getEnrollmentDetails() != null) { + for (String enrollmentType : deviceEnrollmentType.getEnrollmentType()) { + deviceEnrollmentInvitationDetails.getEnrollmentDetails().stream() + .filter(details -> enrollmentType.equals(details.getEnrollmentType())).findFirst() + .ifPresent(details -> enrollmentSteps.append(details.getEnrollmentSteps())); + } + } + } + int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); + OneTimePinDTO oneTimePinDTO; + Properties props = new Properties(); + props.setProperty("enrollment-steps", enrollmentSteps.toString()); + try { + for (String username : deviceEnrollmentInvitation.getUsernames()) { + String emailAddress = DeviceManagerUtil.getUserClaimValue( + username, DeviceManagementConstants.User.CLAIM_EMAIL_ADDRESS); + oneTimePinDTO = createOneTimePin(emailAddress, OTPEmailTypes.DEVICE_ENROLLMENT.toString(), username, + null, tenantId); + props.setProperty("first-name", DeviceManagerUtil. + getUserClaimValue(username, DeviceManagementConstants.User.CLAIM_FIRST_NAME)); + props.setProperty("username", username); + props.setProperty("otp-token", oneTimePinDTO.getOtpToken()); + sendMail(props, emailAddress, DeviceManagementConstants.EmailAttributes.USER_ENROLLMENT_TEMPLATE); + } + } catch (UserStoreException e) { + String msg = "Error occurred while getting claim values to invite user"; + log.error(msg, e); + throw new OTPManagementException(msg, e); + } + } + + + /** + * Create One Time Token + * @param email email + * @param emailType email type + * @param userName username + * @param metaDataObj meta data object + * @param tenantId tenant Id + * @return {@link OneTimePinDTO} + */ + private OneTimePinDTO createOneTimePin(String email, String emailType, String userName, Object metaDataObj, + int tenantId) { + + String otpValue = UUID.randomUUID().toString(); + + Gson gson = new Gson(); + String metaInfo = gson.toJson(metaDataObj); + + OneTimePinDTO oneTimePinDTO = new OneTimePinDTO(); + oneTimePinDTO.setEmail(email); + oneTimePinDTO.setTenantId(tenantId); + oneTimePinDTO.setUsername(userName); + oneTimePinDTO.setEmailType(emailType); + oneTimePinDTO.setMetaInfo(metaInfo); + oneTimePinDTO.setOtpToken(otpValue); + + return oneTimePinDTO; + } + + /** + * Get OTPData from DB + * @param oneTimeToken One Time Token + * @return {@link OneTimePinDTO} + * @throws OTPManagementException if error occurred while getting OTP data for given OTP in DB + */ + private OneTimePinDTO getOTPDataByToken ( String oneTimeToken) throws OTPManagementException { + try { + ConnectionManagerUtil.openDBConnection(); + return otpManagementDAO.getOTPDataByToken(oneTimeToken); + } catch (DBConnectionException e) { + String msg = "Error occurred while getting database connection to validate the given OTP."; + log.error(msg, e); + throw new OTPManagementException(msg, e); + } catch (OTPManagementDAOException e) { + String msg = "Error occurred while getting OTP data from DB. OTP: " + oneTimeToken; + log.error(msg, e); + throw new OTPManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + /** + * Validate Tenant details + * @param otpWrapper OTP-Wrapper + * @return {@link Tenant} if its valid payload otherwise throws {@link DeviceManagementException} + * @throws DeviceManagementException if invalid payload or unauthorized request received + */ + private Tenant validateTenantCreatingDetails(OTPWrapper otpWrapper) throws DeviceManagementException { + + DeviceManagementConfig deviceManagementConfig = DeviceConfigurationManager.getInstance() + .getDeviceManagementConfig(); + KeyManagerConfigurations kmConfig = deviceManagementConfig.getKeyManagerConfigurations(); + + if (StringUtils.isBlank(otpWrapper.getUsername())) { + String msg = "Received Blank username to create OTP. Username: " + otpWrapper.getUsername(); + log.error(msg); + throw new BadRequestException(msg); + } + + String[] superTenantDetails = otpWrapper.getUsername().split("@"); + if (!MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(superTenantDetails[superTenantDetails.length - 1]) + || !superTenantDetails[0].equals(kmConfig.getAdminUsername())) { + String msg = "You don't have required permission to create OTP"; + log.error(msg); + throw new UnAuthorizedException(msg); + } + + Tenant tenant = new Tenant(); + List properties = otpWrapper.getProperties(); + for (Metadata property : properties) { + if (property == null) { + String msg = "Received invalid property to create OTP."; + log.error(msg); + throw new BadRequestException(msg); + } + switch (property.getMetaKey()) { + case OTPProperties.FIRST_NAME: + String firstName = property.getMetaValue(); + if (StringUtils.isBlank(firstName)) { + String msg = "Received empty or blank first name field with OTP creating payload."; + log.error(msg); + throw new BadRequestException(msg); + } + tenant.setAdminFirstName(firstName); + break; + case OTPProperties.LAST_NAME: + String lastName = property.getMetaValue(); + if (StringUtils.isBlank(lastName)) { + String msg = "Received empty or blank last name field with OTP creating payload."; + log.error(msg); + throw new BadRequestException(msg); + } + tenant.setAdminLastName(lastName); + break; + case OTPProperties.TENANT_ADMIN_PASSWORD: + String pwd = property.getMetaValue(); + if (StringUtils.isBlank(pwd)) { + String msg = "Received empty or blank admin password field with OTP creating payload."; + log.error(msg); + throw new BadRequestException(msg); + } + tenant.setAdminPassword(pwd); + break; + default: + String msg = "Received invalid key with OTP properties for creating OTP."; + log.error(msg); + throw new BadRequestException(msg); + } + } + + if (StringUtils.isBlank(otpWrapper.getEmail())) { + String msg = "Received empty or blank email field with OTP creating payload."; + log.error(msg); + throw new BadRequestException(msg); + } + + EmailValidator validator = EmailValidator.getInstance(); + if (!validator.isValid(otpWrapper.getEmail())) { + String msg = "Found invalid email. Hence please verify the email address and re-try. Email: " + otpWrapper + .getEmail(); + log.error(msg); + throw new BadRequestException(msg); + } + + if (StringUtils.isBlank(otpWrapper.getEmailType())) { + String msg = "Received empty or blank email type field with OTP creating payload."; + log.error(msg); + throw new BadRequestException(msg); + } + + try { + ConnectionManagerUtil.openDBConnection(); + if (otpManagementDAO.isEmailExist(otpWrapper.getEmail(), otpWrapper.getEmailType())) { + String msg = "Email is registered to execute the same action. Hence can't proceed."; + log.error(msg); + throw new BadRequestException(msg); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while getting database connection to validate the given email and email type."; + log.error(msg); + throw new DeviceManagementException(msg); + } catch (OTPManagementDAOException e) { + String msg = "Error occurred while executing SQL query to validate the given email and email type."; + log.error(msg); + throw new DeviceManagementException(msg); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + + String[] tenantUsernameDetails = otpWrapper.getEmail().split("@"); + tenant.setAdminName(tenantUsernameDetails[0]); + tenant.setDomain(tenantUsernameDetails[tenantUsernameDetails.length - 1]); + tenant.setEmail(otpWrapper.getEmail()); + return tenant; + } + + /** + * If OTP expired, resend the user verifying mail with renewed OTP + * @param props Mail body properties + * @param mailAddress Mail Address of the User + * @param template Mail template to be used + * @throws OTPManagementException if error occurred while resend the user verifying mail + */ + private void sendMail(Properties props, String mailAddress, String template) throws OTPManagementException { + try { + EmailMetaInfo metaInfo = new EmailMetaInfo(mailAddress, props); + DeviceManagementDataHolder.getInstance().getDeviceManagementProvider() + .sendEnrolmentInvitation(template, metaInfo); + } catch (DeviceManagementException e) { + String msg = "Error occurred while sending email using email template '" + template + "'."; + log.error(msg, e); + throw new OTPManagementException(msg, e); + } catch (ConfigurationManagementException e) { + String msg = "Configuration error occurred. Hence mail sending failed."; + log.error(msg, e); + throw new OTPManagementException(msg, e); + } + } + + /** + * Renew the OTP + * @param oneTimePinDTO {@link OneTimePinDTO} + * @param renewedOTP Renewed OTP + * @throws OTPManagementException if error occurred while renew the OTP + */ + private void renewOTP(OneTimePinDTO oneTimePinDTO, String renewedOTP) throws OTPManagementException { + try { + ConnectionManagerUtil.beginDBTransaction(); + this.otpManagementDAO.renewOneTimeToken(oneTimePinDTO.getId(), renewedOTP); + ConnectionManagerUtil.commitDBTransaction(); + } catch (TransactionManagementException e) { + String msg = "Error occurred while disabling AutoCommit to renew the OTP."; + log.error(msg, e); + throw new OTPManagementException(msg, e); + } catch (DBConnectionException e) { + String msg = "Error occurred while getting database connection to renew the OTP."; + log.error(msg, e); + throw new OTPManagementException(msg, e); + } catch (OTPManagementDAOException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + String msg = "Error occurred while renew the OTP. OTP: " + renewedOTP; + log.error(msg, e); + throw new OTPManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/util/ConnectionManagerUtil.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/util/ConnectionManagerUtil.java new file mode 100644 index 0000000000..9db3784dd5 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/otp/mgt/util/ConnectionManagerUtil.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2020, Entgra (pvt) Ltd. (http://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.otp.mgt.util; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.exceptions.DBConnectionException; +import org.wso2.carbon.device.mgt.common.exceptions.TransactionManagementException; +import org.wso2.carbon.device.mgt.common.exceptions.IllegalTransactionStateException; + +import javax.naming.InitialContext; +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; + +/** + * ConnectionManagerUtil is responsible for handling all the datasource connections utilities. + */ +public class ConnectionManagerUtil { + + private static final Log log = LogFactory.getLog(ConnectionManagerUtil.class); + private static final ThreadLocal currentConnection = new ThreadLocal<>(); + private static DataSource dataSource; + + public static void openDBConnection() throws DBConnectionException { + Connection conn = currentConnection.get(); + if (conn != null) { + String msg = "Database connection has already been obtained."; + log.error(msg); + throw new IllegalTransactionStateException(msg); + } + try { + conn = dataSource.getConnection(); + } catch (SQLException e) { + String msg = "Failed to get a database connection."; + log.error(msg, e); + throw new DBConnectionException(msg, e); + } + currentConnection.set(conn); + } + + public static Connection getDBConnection() throws DBConnectionException { + Connection conn = currentConnection.get(); + if (conn == null) { + try { + conn = dataSource.getConnection(); + currentConnection.set(conn); + } catch (SQLException e) { + throw new DBConnectionException("Failed to get database connection.", e); + } + } + return conn; + } + + public static void beginDBTransaction() throws TransactionManagementException, DBConnectionException { + Connection conn = currentConnection.get(); + if (conn == null) { + conn = getDBConnection(); + } else if (inTransaction(conn)) { + String msg = "Transaction has already been started."; + log.error(msg); + throw new IllegalTransactionStateException(msg); + } + + try { + conn.setAutoCommit(false); + } catch (SQLException e) { + String msg = "Error occurred while starting a database transaction."; + log.error(msg, e); + throw new TransactionManagementException(msg, e); + } + } + + public static void endDBTransaction() throws TransactionManagementException { + Connection conn = currentConnection.get(); + if (conn == null) { + throw new IllegalTransactionStateException("Database connection is not active."); + } + + if (!inTransaction(conn)) { + throw new IllegalTransactionStateException("Transaction has not been started."); + } + + try { + conn.setAutoCommit(true); + } catch (SQLException e) { + throw new TransactionManagementException("Error occurred while ending database transaction.", e); + } + } + + public static void commitDBTransaction() { + Connection conn = currentConnection.get(); + if (conn == null) { + throw new IllegalTransactionStateException("Database connection is not active."); + } + + if (!inTransaction(conn)) { + throw new IllegalTransactionStateException("Transaction has not been started."); + } + + try { + conn.commit(); + } catch (SQLException e) { + log.error("Error occurred while committing the transaction", e); + } + } + + public static void rollbackDBTransaction() { + Connection conn = currentConnection.get(); + if (conn == null) { + throw new IllegalTransactionStateException("Database connection is not active."); + } + + if (!inTransaction(conn)) { + throw new IllegalTransactionStateException("Transaction has not been started."); + } + + try { + conn.rollback(); + } catch (SQLException e) { + log.warn("Error occurred while roll-backing the transaction", e); + } + } + + public static void closeDBConnection() { + Connection conn = currentConnection.get(); + if (conn == null) { + throw new IllegalTransactionStateException("Database connection is not active."); + } + try { + conn.close(); + } catch (SQLException e) { + log.error("Error occurred while closing the connection", e); + } + currentConnection.remove(); + } + + private static boolean inTransaction(Connection conn) { + boolean inTransaction = true; + try { + if (conn.getAutoCommit()) { + inTransaction = false; + } + } catch (SQLException e) { + throw new IllegalTransactionStateException("Failed to get transaction state."); + } + return inTransaction; + } + + public static boolean isTransactionStarted() throws DBConnectionException { + Connection connection = getDBConnection(); + return inTransaction(connection); + } + + /** + * Resolve the datasource from the datasource definition. + * + * @param dataSourceName Name of the datasource + * @return DataSource resolved by the datasource name + */ + public static DataSource resolveDataSource(String dataSourceName) { + try { + dataSource = InitialContext.doLookup(dataSourceName); + } catch (Exception e) { + throw new RuntimeException("Error in looking up data source: " + e.getMessage(), e); + } + return dataSource; + } + + public static String getDatabaseType() { + try (Connection connection = dataSource.getConnection()) { + return connection.getMetaData().getDatabaseProductName(); + } catch (SQLException e) { + log.error("Error occurred while retrieving config.datasource connection", e); + } + return null; + } + + /** + * To check whether particular database that is used for application management supports batch query execution. + * + * @return true if batch query is supported, otherwise false. + */ + public static boolean isBatchQuerySupported() { + try (Connection connection = dataSource.getConnection()) { + return connection.getMetaData().supportsBatchUpdates(); + } catch (SQLException e) { + log.error("Error occurred while checking whether database supports batch updates", e); + } + return false; + } + + public static void init(DataSource dtSource) { + dataSource = dtSource; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java index 54c7c04805..3a79a9cd42 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java @@ -14,8 +14,8 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. - */ -/* + * + * * Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved. * * Entgra (pvt) Ltd. licenses this file to you under the Apache License, @@ -32,23 +32,6 @@ * specific language governing permissions and limitations * under the License. */ -/* - * Copyright (c) 2020, Entgra (pvt) Ltd. (http://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.service; @@ -76,6 +59,7 @@ import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManageme import org.wso2.carbon.device.mgt.common.configuration.mgt.DeviceConfiguration; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; import org.wso2.carbon.device.mgt.common.device.details.DeviceData; +import org.wso2.carbon.device.mgt.common.invitation.mgt.DeviceEnrollmentInvitationDetails; import org.wso2.carbon.device.mgt.common.license.mgt.License; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; @@ -89,7 +73,6 @@ import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.core.dto.DeviceTypeVersion; import org.wso2.carbon.device.mgt.core.geo.GeoCluster; import org.wso2.carbon.device.mgt.core.geo.geoHash.GeoCoordinate; -import org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation; import java.sql.SQLException; import java.util.Date; @@ -927,4 +910,12 @@ public interface DeviceManagementProviderService { */ List getDeviceByIdList(List deviceIdentifiers) throws DeviceManagementException; + + /** + * Retrieve device enrollment details to be sent device enrollment invitation. + * This has the relevant enrollment steps of each enrollment types. + * @param deviceType Device type of the required device enrollment details + * @return enrollment steps of each enrollment types which are provided in the device type xml file + */ + DeviceEnrollmentInvitationDetails getDeviceEnrollmentInvitationDetails(String deviceType); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java index 55787e37fc..5e28129390 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java @@ -14,6 +14,23 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * 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.service; @@ -74,6 +91,7 @@ import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroupConstants; import org.wso2.carbon.device.mgt.common.group.mgt.GroupAlreadyExistException; import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException; +import org.wso2.carbon.device.mgt.common.invitation.mgt.DeviceEnrollmentInvitationDetails; import org.wso2.carbon.device.mgt.common.license.mgt.License; import org.wso2.carbon.device.mgt.common.license.mgt.LicenseManagementException; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; @@ -4187,4 +4205,11 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv DeviceManagementDAOFactory.closeConnection(); } } + + @Override + public DeviceEnrollmentInvitationDetails getDeviceEnrollmentInvitationDetails(String deviceType) { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + DeviceManagementService dms = pluginRepository.getDeviceManagementService(deviceType, tenantId); + return dms.getDeviceEnrollmentInvitationDetails(); + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java index cb5d305aef..9404e5de86 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java @@ -14,6 +14,23 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * 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.util; @@ -79,6 +96,7 @@ import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerSer import org.wso2.carbon.user.api.TenantManager; 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.utils.CarbonUtils; import org.wso2.carbon.utils.ConfigurationContextService; import org.wso2.carbon.utils.NetworkUtils; @@ -1047,4 +1065,17 @@ public final class DeviceManagerUtil { } return roleList; } + + /** + * Retrieve the value of the user property from the user profile + * @param username of the user + * @param claimUri name of the claim + * @return value for the claim uri of user + * @throws UserStoreException when there is error in retrieving the user store manager + */ + public static String getUserClaimValue(String username, String claimUri) throws UserStoreException { + UserStoreManager userStoreManager = CarbonContext.getThreadLocalCarbonContext().getUserRealm() + .getUserStoreManager(); + return userStoreManager.getUserClaimValue(username, claimUri, null); + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/TestDeviceManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/TestDeviceManagementService.java index 580ed77161..c3789d47fa 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/TestDeviceManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/TestDeviceManagementService.java @@ -37,6 +37,7 @@ import org.wso2.carbon.device.mgt.common.*; import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManager; import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException; import org.wso2.carbon.device.mgt.common.general.GeneralConfig; +import org.wso2.carbon.device.mgt.common.invitation.mgt.DeviceEnrollmentInvitationDetails; import org.wso2.carbon.device.mgt.common.policy.mgt.PolicyMonitoringManager; import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationSubscriber; import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationConfig; @@ -142,4 +143,9 @@ public class TestDeviceManagementService implements DeviceManagementService { public DeviceTypePlatformDetails getDeviceTypePlatformDetails() { return null; } + + @Override + public DeviceEnrollmentInvitationDetails getDeviceEnrollmentInvitationDetails() { + return null; + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/template/DeviceTypeManagerService.java b/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/template/DeviceTypeManagerService.java index 67b79bfeb4..5896039d99 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/template/DeviceTypeManagerService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/template/DeviceTypeManagerService.java @@ -48,6 +48,7 @@ import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManager; import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; import org.wso2.carbon.device.mgt.common.general.GeneralConfig; +import org.wso2.carbon.device.mgt.common.invitation.mgt.DeviceEnrollmentInvitationDetails; import org.wso2.carbon.device.mgt.common.policy.mgt.PolicyMonitoringManager; import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationSubscriber; import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationConfig; @@ -92,6 +93,7 @@ public class DeviceTypeManagerService implements DeviceManagementService { private PullNotificationSubscriber pullNotificationSubscriber; private final DeviceStatusTaskPluginConfig deviceStatusTaskPluginConfig; private DeviceTypePlatformDetails deviceTypePlatformDetails; + private DeviceEnrollmentInvitationDetails deviceEnrollmentInvitationDetails; private GeneralConfig generalConfig; private boolean isRegistryBasedConfigs = false; private boolean isScheduled = false; @@ -116,6 +118,8 @@ public class DeviceTypeManagerService implements DeviceManagementService { this.setPolicyMonitoringManager(deviceTypeConfiguration.getPolicyMonitoring()); this.setPullNotificationSubscriber(deviceTypeConfiguration.getPullNotificationSubscriberConfig()); this.setGeneralConfig(deviceTypeConfiguration); + this.deviceEnrollmentInvitationDetails = new DeviceEnrollmentInvitationDetails(); + this.setDeviceEnrollmentInvitationDetails(deviceTypeConfiguration); } @Override @@ -259,6 +263,11 @@ public class DeviceTypeManagerService implements DeviceManagementService { return generalConfig; } + @Override + public DeviceEnrollmentInvitationDetails getDeviceEnrollmentInvitationDetails() { + return deviceEnrollmentInvitationDetails; + } + private void setProvisioningConfig(String tenantDomain, DeviceTypeConfiguration deviceTypeConfiguration) { if (deviceTypeConfiguration.getProvisioningConfig() != null) { boolean sharedWithAllTenants = deviceTypeConfiguration.getProvisioningConfig().isSharedWithAllTenants(); @@ -354,4 +363,13 @@ public class DeviceTypeManagerService implements DeviceManagementService { deviceTypePlatformDetails.setDeviceTypePlatformVersion(deviceTypeVersions.getDeviceTypePlatformVersion()); } } + + public void setDeviceEnrollmentInvitationDetails(DeviceTypeConfiguration deviceTypeConfiguration) { + DeviceEnrollmentInvitationDetails deviceEnrollmentInvitationDetailsFromConfig = deviceTypeConfiguration + .getDeviceEnrollmentInvitationDetails(); + if (deviceEnrollmentInvitationDetailsFromConfig != null) { + deviceEnrollmentInvitationDetails.setEnrollmentDetails( + deviceEnrollmentInvitationDetailsFromConfig.getEnrollmentDetails()); + } + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/template/config/DeviceTypeConfiguration.java b/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/template/config/DeviceTypeConfiguration.java index f1c470829e..098baec3e3 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/template/config/DeviceTypeConfiguration.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/template/config/DeviceTypeConfiguration.java @@ -34,6 +34,7 @@ */ package org.wso2.carbon.device.mgt.extensions.device.type.template.config; +import org.wso2.carbon.device.mgt.common.invitation.mgt.DeviceEnrollmentInvitationDetails; import org.wso2.carbon.device.mgt.common.type.mgt.DeviceTypePlatformDetails; import javax.xml.bind.annotation.XmlElement; @@ -107,6 +108,8 @@ public class DeviceTypeConfiguration { protected List operations; @XmlElement(name = "DeviceTypePlatformDetails", required = true) protected DeviceTypePlatformDetails deviceTypePlatformDetails; + @XmlElement(name = "DeviceEnrollmentInvitationDetails", required = true) + protected DeviceEnrollmentInvitationDetails deviceEnrollmentInvitationDetails; public DeviceTypePlatformDetails getDeviceTypePlatformDetails() { return deviceTypePlatformDetails; @@ -414,4 +417,21 @@ public class DeviceTypeConfiguration { public void setStartupOperations(List startupOperations) { this.startupOperations = startupOperations; } + + /** + * Gets the value of device enrollment invitation details which has enrollment steps of enrollment types + * @return device enrollment invitation details + */ + public DeviceEnrollmentInvitationDetails getDeviceEnrollmentInvitationDetails() { + return deviceEnrollmentInvitationDetails; + } + + /** + * Sets the value of device enrollment invitation details from the relevant device type xml file + * @param deviceEnrollmentInvitationDetails {@link DeviceEnrollmentInvitationDetails} object + */ + public void setDeviceEnrollmentInvitationDetails( + DeviceEnrollmentInvitationDetails deviceEnrollmentInvitationDetails) { + this.deviceEnrollmentInvitationDetails = deviceEnrollmentInvitationDetails; + } } diff --git a/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/test/java/org/wso2/carbon/policy/mgt/core/mock/TypeXDeviceManagementService.java b/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/test/java/org/wso2/carbon/policy/mgt/core/mock/TypeXDeviceManagementService.java index 9bcd089eb0..de7a16c0b1 100644 --- a/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/test/java/org/wso2/carbon/policy/mgt/core/mock/TypeXDeviceManagementService.java +++ b/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/test/java/org/wso2/carbon/policy/mgt/core/mock/TypeXDeviceManagementService.java @@ -44,6 +44,7 @@ import org.wso2.carbon.device.mgt.common.ProvisioningConfig; import org.wso2.carbon.device.mgt.common.StartupOperationConfig; import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManager; import org.wso2.carbon.device.mgt.common.general.GeneralConfig; +import org.wso2.carbon.device.mgt.common.invitation.mgt.DeviceEnrollmentInvitationDetails; import org.wso2.carbon.device.mgt.common.policy.mgt.PolicyMonitoringManager; import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationSubscriber; import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationConfig; @@ -131,4 +132,9 @@ public class TypeXDeviceManagementService implements DeviceManagementService { public DeviceTypePlatformDetails getDeviceTypePlatformDetails() { return null; } + + @Override + public DeviceEnrollmentInvitationDetails getDeviceEnrollmentInvitationDetails() { + return null; + } } diff --git a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/OTPInvokerHandler.java b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/OTPInvokerHandler.java new file mode 100644 index 0000000000..624814f327 --- /dev/null +++ b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/OTPInvokerHandler.java @@ -0,0 +1,270 @@ +/* + * 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 io.entgra.ui.request.interceptor; + +import io.entgra.ui.request.interceptor.util.HandlerConstants; +import io.entgra.ui.request.interceptor.util.HandlerUtil; +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.FileUploadException; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.http.HttpHeaders; +import org.apache.http.HttpStatus; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpHead; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.cookie.SM; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.InputStreamEntity; +import org.apache.http.entity.mime.HttpMultipartMode; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.entity.mime.content.InputStreamBody; +import org.wso2.carbon.device.application.mgt.common.ProxyResponse; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Enumeration; +import java.util.List; + +@WebServlet( + name = "OTPRequestHandlerServlet", + description = "This servlet intercepts the otp-api requests initiated from the user interface and validate " + + "before forwarding to the backend", + urlPatterns = { + "/otp-invoke/*" + } +) +public class OTPInvokerHandler extends HttpServlet { + private static final Log log = LogFactory.getLog(OTPInvokerHandler.class); + private static final long serialVersionUID = 3109569827313066220L; + private static String apiEndpoint; + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) { + try { + if (validateRequest(req, resp)) { + HttpPost postRequest = new HttpPost(HandlerUtil.generateBackendRequestURL(req, apiEndpoint)); + generateRequestEntity(req, postRequest); + ProxyResponse proxyResponse = HandlerUtil.execute(postRequest); + + if (proxyResponse.getExecutorResponse().contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) { + log.error("Error occurred while invoking the POST API endpoint."); + HandlerUtil.handleError(resp, proxyResponse); + return; + } + HandlerUtil.handleSuccess(resp, proxyResponse); + } + } catch (FileUploadException e) { + log.error("Error occurred when processing Multipart POST request.", e); + } catch (IOException e) { + log.error("Error occurred when processing POST request.", e); + } + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) { + try { + if (validateRequest(req, resp)) { + HttpGet getRequest = new HttpGet(HandlerUtil.generateBackendRequestURL(req, apiEndpoint)); + copyRequestHeaders(req, getRequest, false); + ProxyResponse proxyResponse = HandlerUtil.execute(getRequest); + + if (proxyResponse.getExecutorResponse().contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) { + log.error("Error occurred while invoking the GET API endpoint."); + HandlerUtil.handleError(resp, proxyResponse); + return; + } + HandlerUtil.handleSuccess(resp, proxyResponse); + } + } catch (IOException e) { + log.error("Error occurred when processing GET request.", e); + } + } + + @Override + protected void doHead(HttpServletRequest req, HttpServletResponse resp) { + try { + if (validateRequest(req, resp)) { + HttpHead headRequest = new HttpHead(HandlerUtil.generateBackendRequestURL(req, apiEndpoint)); + copyRequestHeaders(req, headRequest, false); + ProxyResponse proxyResponse = HandlerUtil.execute(headRequest); + + if (proxyResponse.getExecutorResponse().contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) { + log.error("Error occurred while invoking the HEAD API endpoint."); + HandlerUtil.handleError(resp, proxyResponse); + return; + } + HandlerUtil.handleSuccess(resp, proxyResponse); + } + } catch (IOException e) { + log.error("Error occurred when processing HEAD request.", e); + } + } + + @Override + protected void doPut(HttpServletRequest req, HttpServletResponse resp) { + try { + if (validateRequest(req, resp)) { + HttpPut putRequest = new HttpPut(HandlerUtil.generateBackendRequestURL(req, apiEndpoint)); + generateRequestEntity(req, putRequest); + ProxyResponse proxyResponse = HandlerUtil.execute(putRequest); + + if (proxyResponse.getExecutorResponse().contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) { + log.error("Error occurred while invoking the PUT API endpoint."); + HandlerUtil.handleError(resp, proxyResponse); + return; + } + HandlerUtil.handleSuccess(resp, proxyResponse); + } + } catch (FileUploadException e) { + log.error("Error occurred when processing Multipart PUT request.", e); + } catch (IOException e) { + log.error("Error occurred when processing PUT request.", e); + } + } + + @Override + protected void doDelete(HttpServletRequest req, HttpServletResponse resp) { + try { + if (validateRequest(req, resp)) { + HttpDelete deleteRequest = new HttpDelete(HandlerUtil.generateBackendRequestURL(req, apiEndpoint)); + copyRequestHeaders(req, deleteRequest, false); + ProxyResponse proxyResponse = HandlerUtil.execute(deleteRequest); + + if (proxyResponse.getExecutorResponse().contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) { + log.error("Error occurred while invoking the DELETE API endpoint."); + HandlerUtil.handleError(resp, proxyResponse); + return; + } + HandlerUtil.handleSuccess(resp, proxyResponse); + } + } catch (IOException e) { + log.error("Error occurred when processing DELETE request.", e); + } + } + + /** + * Generate te request entity for POST and PUT requests from the incoming request. + * + * @param req incoming {@link HttpServletRequest}. + * @param proxyRequest proxy request instance. + * @throws FileUploadException If unable to parse the incoming request for multipart content extraction. + * @throws IOException If error occurred while generating the request body. + */ + private void generateRequestEntity(HttpServletRequest req, HttpEntityEnclosingRequestBase proxyRequest) + throws FileUploadException, IOException { + if (ServletFileUpload.isMultipartContent(req)) { + ServletFileUpload servletFileUpload = new ServletFileUpload(new DiskFileItemFactory()); + List fileItemList = servletFileUpload.parseRequest(req); + MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create(); + entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); + for (FileItem item: fileItemList) { + if (!item.isFormField()) { + entityBuilder.addPart(item.getFieldName(), new InputStreamBody(item.getInputStream(), + ContentType.create(item.getContentType()), item.getName())); + } else { + entityBuilder.addTextBody(item.getFieldName(), item.getString()); + } + } + proxyRequest.setEntity(entityBuilder.build()); + copyRequestHeaders(req, proxyRequest, false); + } else { + if (StringUtils.isNotEmpty(req.getHeader(HttpHeaders.CONTENT_LENGTH)) || + StringUtils.isNotEmpty(req.getHeader(HttpHeaders.TRANSFER_ENCODING))) { + InputStreamEntity entity = new InputStreamEntity(req.getInputStream(), + Long.parseLong(req.getHeader(HttpHeaders.CONTENT_LENGTH))); + proxyRequest.setEntity(entity); + } + copyRequestHeaders(req, proxyRequest, true); + } + } + + /** + * Copy incoming request headers to the proxy request. + * + * @param req incoming {@link HttpServletRequest} + * @param httpRequest proxy request instance. + * @param preserveContentType true if content type header needs to be preserved. + * This should be set to false when handling multipart requests as Http + * client will generate the Content-Type header automatically. + */ + private void copyRequestHeaders(HttpServletRequest req, HttpRequestBase httpRequest, boolean preserveContentType) { + Enumeration headerNames = req.getHeaderNames(); + while (headerNames.hasMoreElements()) { + String headerName = headerNames.nextElement(); + if (headerName.equalsIgnoreCase(HttpHeaders.CONTENT_LENGTH) || + headerName.equalsIgnoreCase(SM.COOKIE) || + (!preserveContentType && headerName.equalsIgnoreCase(HttpHeaders.CONTENT_TYPE))) { + continue; + } + Enumeration headerValues = req.getHeaders(headerName); + while (headerValues.hasMoreElements()) { + httpRequest.setHeader(headerName, headerValues.nextElement()); + } + } + } + + /*** + * Validates the incoming request. + * + * @param req {@link HttpServletRequest} + * @param resp {@link HttpServletResponse} + * @return If request is a valid one, returns TRUE, otherwise return FALSE + * @throws IOException If and error occurs while witting error response to client side + */ + private static boolean validateRequest(HttpServletRequest req, HttpServletResponse resp) + throws IOException { + String schema = req.getScheme(); + apiEndpoint = schema + HandlerConstants.SCHEME_SEPARATOR + System.getProperty("iot.core.host") + + HandlerConstants.COLON + HandlerUtil.getCorePort(schema); + + if (StringUtils.isBlank(req.getHeader(HandlerConstants.OTP_HEADER))) { + log.error("Unauthorized, Please provide OTP token."); + handleError(resp, HttpStatus.SC_UNAUTHORIZED); + return false; + } + return true; + } + + /** + * Handle error requests + * + * @param resp {@link HttpServletResponse} + * @param errorCode HTTP error status code + * @throws IOException If error occurred when trying to send the error response. + */ + private static void handleError(HttpServletResponse resp, int errorCode) + throws IOException { + ProxyResponse proxyResponse = new ProxyResponse(); + proxyResponse.setCode(errorCode); + proxyResponse.setExecutorResponse( + HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(errorCode)); + HandlerUtil.handleError(resp, proxyResponse); + } +} diff --git a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/util/HandlerConstants.java b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/util/HandlerConstants.java index a335f224c7..b691eaa315 100644 --- a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/util/HandlerConstants.java +++ b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/util/HandlerConstants.java @@ -47,4 +47,6 @@ public class HandlerConstants { public static final int INTERNAL_ERROR_CODE = 500; public static final long TIMEOUT = 1200; + + public static final String OTP_HEADER = "one-time-token"; } diff --git a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/util/HandlerUtil.java b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/util/HandlerUtil.java index 82685daa43..592806f338 100644 --- a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/util/HandlerUtil.java +++ b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/util/HandlerUtil.java @@ -34,6 +34,7 @@ import org.json.JSONException; import org.json.JSONObject; import org.wso2.carbon.device.application.mgt.common.ProxyResponse; +import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.BufferedReader; import java.io.IOException; @@ -203,7 +204,7 @@ public class HandlerUtil { } /** - * Get gatway port according to request recieved scheme + * Get gateway port according to request received scheme * @param scheme https or https * @return {@link String} gateway port */ @@ -215,6 +216,19 @@ public class HandlerUtil { return gatewayPort; } + /** + * Get core port according to request received scheme + * @param scheme https or https + * @return {@link String} gateway port + */ + public static String getCorePort(String scheme) { + String productCorePort = System.getProperty("iot.core.https.port"); + if (HandlerConstants.HTTP_PROTOCOL.equals(scheme)) { + productCorePort = System.getProperty("iot.core.https.por"); + } + return productCorePort; + } + /** * Retrieve Http client based on hostname verification. * @return {@link CloseableHttpClient} http client @@ -242,4 +256,21 @@ public class HandlerUtil { HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(HttpStatus.SC_UNAUTHORIZED)); handleError(resp, proxyResponse); } + + /** + * Generates the target URL for the proxy request. + * + * @param req incoming {@link HttpServletRequest} + * @param apiEndpoint API Endpoint URL + * @return Target URL + */ + public static String generateBackendRequestURL(HttpServletRequest req, String apiEndpoint) { + StringBuilder urlBuilder = new StringBuilder(); + urlBuilder.append(apiEndpoint).append(HandlerConstants.API_COMMON_CONTEXT) + .append(req.getPathInfo().replace(" ", "%20")); + if (StringUtils.isNotEmpty(req.getQueryString())) { + urlBuilder.append("?").append(req.getQueryString()); + } + return urlBuilder.toString(); + } } diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml index d2c8bb4dec..24cbfecefb 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml @@ -93,7 +93,7 @@ org.apache.axis2.transport.http, org.wso2.carbon.certificate.mgt.core.*, org.wso2.carbon.device.mgt.core.permission.mgt, - org.wso2.carbon.device.mgt.common, + org.wso2.carbon.device.mgt.common.*, org.wso2.carbon.device.mgt.common.permission.mgt, org.apache.axis2, org.apache.axis2.client, diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/Constants.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/Constants.java index 2694ea069a..6426c53f47 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/Constants.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/Constants.java @@ -31,6 +31,7 @@ public final class Constants { public static final String HEADER_HTTP_ACCEPT = "Accept"; public static final String HEADER_HTTP_AUTHORIZATION = "Authorization"; + public static final String ONE_TIME_TOKEN_HEADER = "one-time-token"; } public static final class ContentTypes { diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/OneTimeTokenAuthenticator.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/OneTimeTokenAuthenticator.java new file mode 100644 index 0000000000..9d290c51da --- /dev/null +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/OneTimeTokenAuthenticator.java @@ -0,0 +1,91 @@ +/* + * 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.webapp.authenticator.framework.authenticator; + +import org.apache.catalina.connector.Response; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.otp.mgt.dto.OneTimePinDTO; +import org.wso2.carbon.device.mgt.common.spi.OTPManagementService; +import org.wso2.carbon.webapp.authenticator.framework.AuthenticationInfo; +import org.wso2.carbon.webapp.authenticator.framework.Constants; +import org.wso2.carbon.webapp.authenticator.framework.Utils.Utils; +import org.wso2.carbon.webapp.authenticator.framework.internal.AuthenticatorFrameworkDataHolder; + +import java.util.Properties; + +public class OneTimeTokenAuthenticator implements WebappAuthenticator { + private static final Log log = LogFactory.getLog(OneTimeTokenAuthenticator.class); + + + @Override + public void init() { + + } + + public boolean canHandle(org.apache.catalina.connector.Request request) { + return request.getHeader(Constants.HTTPHeaders.ONE_TIME_TOKEN_HEADER) != null; + } + + public AuthenticationInfo authenticate(org.apache.catalina.connector.Request request, Response response) { + + AuthenticationInfo authenticationInfo = new AuthenticationInfo(); + + try { + OTPManagementService otpManagementService = AuthenticatorFrameworkDataHolder.getInstance() + .getOtpManagementService(); + OneTimePinDTO validOTP = otpManagementService.isValidOTP(request.getHeader(Constants.HTTPHeaders + .ONE_TIME_TOKEN_HEADER)); + if (validOTP != null) { + authenticationInfo.setStatus(Status.CONTINUE); + authenticationInfo.setTenantId(validOTP.getTenantId()); + authenticationInfo.setTenantDomain(Utils.getTenantDomain(validOTP.getTenantId())); + authenticationInfo.setUsername(validOTP.getUsername()); + } else { + authenticationInfo.setStatus(Status.FAILURE); + authenticationInfo.setMessage("Invalid OTP token."); + } + } catch (Exception e) { + String msg = "OTP Token Validation Failed."; + log.error(msg, e); + authenticationInfo.setStatus(Status.FAILURE); + authenticationInfo.setMessage(msg); + } + return authenticationInfo; + } + + public String getName() { + return "One-Time-Token"; + } + + @Override + public void setProperties(Properties properties) { + + } + + @Override + public Properties getProperties() { + return null; + } + + @Override + public String getProperty(String name) { + return null; + } + +} diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/AuthenticatorFrameworkDataHolder.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/AuthenticatorFrameworkDataHolder.java index 8607d02239..a95b4fadb6 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/AuthenticatorFrameworkDataHolder.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/AuthenticatorFrameworkDataHolder.java @@ -20,6 +20,7 @@ package org.wso2.carbon.webapp.authenticator.framework.internal; import org.wso2.carbon.certificate.mgt.core.scep.SCEPManager; import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService; +import org.wso2.carbon.device.mgt.common.spi.OTPManagementService; import org.wso2.carbon.identity.oauth2.OAuth2TokenValidationService; import org.wso2.carbon.registry.core.service.TenantRegistryLoader; import org.wso2.carbon.registry.indexing.service.TenantIndexingLoader; @@ -35,6 +36,7 @@ public class AuthenticatorFrameworkDataHolder { private OAuth2TokenValidationService oAuth2TokenValidationService; private TenantIndexingLoader tenantIndexingLoader; private TenantRegistryLoader tenantRegistryLoader; + private OTPManagementService otpManagementService; private static AuthenticatorFrameworkDataHolder thisInstance = new AuthenticatorFrameworkDataHolder(); @@ -114,4 +116,10 @@ public class AuthenticatorFrameworkDataHolder { public TenantRegistryLoader getTenantRegistryLoader() { return tenantRegistryLoader; } + + public OTPManagementService getOtpManagementService() { return otpManagementService; } + + public void setOtpManagementService(OTPManagementService otpManagementService) { + this.otpManagementService = otpManagementService; + } } diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkServiceComponent.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkServiceComponent.java index 36dd1c09c6..49eff0503b 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkServiceComponent.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkServiceComponent.java @@ -25,6 +25,7 @@ import org.osgi.framework.BundleContext; import org.osgi.service.component.ComponentContext; import org.wso2.carbon.certificate.mgt.core.scep.SCEPManager; import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService; +import org.wso2.carbon.device.mgt.common.spi.OTPManagementService; import org.wso2.carbon.identity.oauth2.OAuth2TokenValidationService; import org.wso2.carbon.registry.core.service.TenantRegistryLoader; import org.wso2.carbon.registry.indexing.service.TenantIndexingLoader; @@ -80,7 +81,14 @@ import java.util.Properties; * cardinality="1..1" policy="dynamic" * bind="setTenantRegistryLoader" * unbind="unsetTenantRegistryLoader" + * @scr.reference name="org.wso2.carbon.device.manager" + * interface="org.wso2.carbon.device.mgt.common.spi.OTPManagementService" + * cardinality="1..1" + * policy="dynamic" + * bind="setOTPManagementService" + * unbind="unsetOTPManagementService" */ + public class WebappAuthenticatorFrameworkServiceComponent { private static final Log log = LogFactory.getLog(WebappAuthenticatorFrameworkServiceComponent.class); @@ -211,4 +219,18 @@ public class WebappAuthenticatorFrameworkServiceComponent { protected void unsetTenantRegistryLoader(TenantRegistryLoader tenantRegistryLoader) { AuthenticatorFrameworkDataHolder.getInstance().setTenantRegistryLoader(null); } + + protected void setOTPManagementService(OTPManagementService otpManagementService) { + if (log.isDebugEnabled()) { + log.debug("Setting OTP Management OSGI Service"); + } + AuthenticatorFrameworkDataHolder.getInstance().setOtpManagementService(otpManagementService); + } + + protected void unsetOTPManagementService(OTPManagementService otpManagementService) { + if (log.isDebugEnabled()) { + log.debug("Removing OTP Management OSGI Service"); + } + AuthenticatorFrameworkDataHolder.getInstance().setOtpManagementService(null); + } } diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/config/etc/webapp-authenticator-config.xml b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/config/etc/webapp-authenticator-config.xml index 5099328df7..93830ca169 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/config/etc/webapp-authenticator-config.xml +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/config/etc/webapp-authenticator-config.xml @@ -24,5 +24,9 @@ CertificateAuth org.wso2.carbon.webapp.authenticator.framework.authenticator.CertificateAuthenticator + + OTPAuth + org.wso2.carbon.webapp.authenticator.framework.authenticator.OneTimeTokenAuthenticator + diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql index 4d16db5abe..623bd6b374 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql @@ -572,6 +572,23 @@ CREATE TABLE IF NOT EXISTS DM_METADATA ( ); -- END OF METADATA TABLE -- +-- DM_OTP_DATA TABLE -- +CREATE TABLE IF NOT EXISTS DM_OTP_DATA ( + ID INT AUTO_INCREMENT NOT NULL, + OTP_TOKEN VARCHAR(100) NOT NULL, + TENANT_ID INT NOT NULL, + USERNAME VARCHAR(500) DEFAULT NOT NULL, + EMAIL VARCHAR(100) NOT NULL, + EMAIL_TYPE VARCHAR(20) NOT NULL, + META_INFO VARCHAR(20000) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + EXPIRY_TIME INT NOT NULL DEFAULT 3600, + IS_EXPIRED BOOLEAN DEFAULT false, + PRIMARY KEY (ID), + CONSTRAINT email_type_uk UNIQUE (EMAIL, EMAIL_TYPE) +); +-- END OF DM_OTP_DATA TABLE -- + -- DASHBOARD RELATED VIEWS -- CREATE VIEW POLICY_COMPLIANCE_INFO AS SELECT 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 8739701915..058bceb53b 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 @@ -614,6 +614,23 @@ CREATE TABLE DM_METADATA ( ); -- END OF METADATA TABLE -- +-- DM_OTP_DATA TABLE -- +CREATE TABLE DM_OTP_DATA ( + ID INT IDENTITY NOT NULL, + OTP_TOKEN VARCHAR(100) NOT NULL, + TENANT_ID INTEGER NOT NULL, + USERNAME VARCHAR(500) NOT NULL, + EMAIL VARCHAR(100) NOT NULL, + EMAIL_TYPE VARCHAR(20) NOT NULL, + META_INFO VARCHAR(20000) NOT NULL, + CREATED_AT DATETIME2(0) NOT NULL, + EXPIRY_TIME INT NOT NULL DEFAULT 3600, + IS_EXPIRED BIT DEFAULT false, + PRIMARY KEY (ID), + CONSTRAINT email_type_uk UNIQUE (EMAIL, EMAIL_TYPE) +); +-- END OF DM_OTP_DATA TABLE -- + -- DASHBOARD RELATED VIEWS -- IF NOT EXISTS (SELECT * FROM SYS.VIEWS WHERE NAME = 'POLICY_COMPLIANCE_INFO') diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql index ba57c26757..f1244dd87e 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql @@ -630,6 +630,23 @@ CREATE TABLE IF NOT EXISTS DM_METADATA ( ) ENGINE=InnoDB; -- END OF METADATA TABLE -- +-- DM_OTP_DATA TABLE -- +CREATE TABLE IF NOT EXISTS DM_OTP_DATA ( + ID INT AUTO_INCREMENT NOT NULL, + OTP_TOKEN VARCHAR(100) NOT NULL, + TENANT_ID INT NOT NULL, + USERNAME VARCHAR(500) NOT NULL, + EMAIL VARCHAR(100) NOT NULL, + EMAIL_TYPE VARCHAR(20) NOT NULL, + META_INFO VARCHAR(20000) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + EXPIRY_TIME INT NOT NULL DEFAULT 3600, + IS_EXPIRED BOOLEAN DEFAULT false, + PRIMARY KEY (ID), + CONSTRAINT email_type_uk UNIQUE (EMAIL, EMAIL_TYPE) +); +-- END OF DM_OTP_DATA TABLE -- + -- DASHBOARD RELATED VIEWS -- CREATE VIEW DEVICE_INFO_VIEW AS diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql index 3ca15d3f38..325bb770b3 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql @@ -978,6 +978,34 @@ END; / -- END OF METADATA TABLE -- +-- OPT-DATA TABLE -- +CREATE TABLE DM_OTP_DATA ( + ID NUMBER(10) NOT NULL, + OTP_TOKEN VARCHAR2(100) NOT NULL, + TENANT_ID INTEGER NOT NULL, + USERNAME VARCHAR(500) NOT NULL, + EMAIL VARCHAR2(100) NOT NULL, + EMAIL_TYPE VARCHAR2(20) NOT NULL, + META_INFO VARCHAR2(20000) NOT NULL, + CREATED_AT TIMESTAMP(0) NOT NULL, + EXPIRY_TIME NUMBER(10) DEFAULT 3600 NOT NULL, + IS_EXPIRED CHAR(1) DEFAULT false, + PRIMARY KEY (ID), + CONSTRAINT email_type_uk UNIQUE (EMAIL, EMAIL_TYPE) +); + +-- Generate ID using sequence and trigger +CREATE SEQUENCE DM_OTP_DATA_seq START WITH 1 INCREMENT BY 1; + +CREATE OR REPLACE TRIGGER DM_OTP_DATA_seq_tr + BEFORE INSERT ON DM_OTP_DATA FOR EACH ROW + WHEN (NEW.ID IS NULL) +BEGIN +SELECT DM_OTP_DATA_seq.NEXTVAL INTO :NEW.ID FROM DUAL; +END; +/ +-- END OF OTP-DATA TABLE -- + -- DASHBOARD RELATED VIEWS -- CREATE VIEW POLICY_COMPLIANCE_INFO AS diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql index dc3d264cfd..d695625575 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql @@ -617,6 +617,26 @@ CREATE TABLE IF NOT EXISTS DM_METADATA ( ); -- END OF METADATA TABLE -- +-- OPT-DATA TABLE -- +CREATE SEQUENCE DM_OTP_DATA_seq; + +CREATE TABLE IF NOT EXISTS DM_OTP_DATA ( + ID INT DEFAULT NEXTVAL ('DM_OTP_DATA_seq') NOT NULL, + OTP_TOKEN VARCHAR(100) NOT NULL, + TENANT_ID INTEGER NOT NULL, + USERNAME VARCHAR(500) NOT NULL, + EMAIL VARCHAR(100) NOT NULL, + EMAIL_TYPE VARCHAR(20) NOT NULL, + META_INFO VARCHAR(20000) NOT NULL, + CREATED_AT TIMESTAMP(0) NOT NULL, + EXPIRY_TIME INT NOT NULL DEFAULT 3600, + IS_EXPIRED BOOLEAN DEFAULT false, + PRIMARY KEY (ID), + CONSTRAINT email_type_uk UNIQUE (EMAIL, EMAIL_TYPE) +); + +-- END OF OPT-DATA TABLE -- + -- DASHBOARD RELATED VIEWS -- CREATE VIEW DEVICE_INFO_VIEW AS diff --git a/features/email-sender/org.wso2.carbon.email.sender.feature/src/main/resources/email/templates/user-enrollment.vm b/features/email-sender/org.wso2.carbon.email.sender.feature/src/main/resources/email/templates/user-enrollment.vm index 20bcf6e768..9573061735 100644 --- a/features/email-sender/org.wso2.carbon.email.sender.feature/src/main/resources/email/templates/user-enrollment.vm +++ b/features/email-sender/org.wso2.carbon.email.sender.feature/src/main/resources/email/templates/user-enrollment.vm @@ -14,6 +14,22 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + + Copyright (c) 2019, 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. *# You have been invited to enroll your device in Entgra IoT @@ -37,7 +53,13 @@

You have been invited to enrol your device in Entgra IoT Server. - Click here to begin device enrolment.

+ Click here to begin device enrolment.

+ +

+ Enrollment Steps are as below, +

+ + $enrollment-steps

Should you need assistance, please contact your administrator. diff --git a/features/email-sender/org.wso2.carbon.email.sender.feature/src/main/resources/email/templates/user-verify.vm b/features/email-sender/org.wso2.carbon.email.sender.feature/src/main/resources/email/templates/user-verify.vm new file mode 100644 index 0000000000..858503fd8a --- /dev/null +++ b/features/email-sender/org.wso2.carbon.email.sender.feature/src/main/resources/email/templates/user-verify.vm @@ -0,0 +1,61 @@ +#* + 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. +*# + + Verify email to register with Entgra IoTS + + + + Entgra IoT Server + + +

+
+
+
+ entgra +
+
+
+

+ Hi $first-name, +

+

+ Congratulations!!! Thank you for registering with Entgra cloud. Please click and log in to the + following link to complete your registration with us. Click here. +

+ +

+ If you need further assistance, please contact your administrator. +

+ +

+ Regards, +

+ +

+ Entgra IoT Administrator +

+
+
+
+ + + ]]> + +
diff --git a/features/email-sender/org.wso2.carbon.email.sender.feature/src/main/resources/email/templates/user-welcome.vm b/features/email-sender/org.wso2.carbon.email.sender.feature/src/main/resources/email/templates/user-welcome.vm new file mode 100644 index 0000000000..5ce4611964 --- /dev/null +++ b/features/email-sender/org.wso2.carbon.email.sender.feature/src/main/resources/email/templates/user-welcome.vm @@ -0,0 +1,98 @@ +#* + 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. +*# + + Welcome to Entgra Evaluation Cloud + + + + Entgra IoT Server + + +
+
+
+
+ entgra +
+
+
+

+ Hi $first-name, +

+
+

+ Welcome to Entgra Evaluation Cloud!! Entgra server support offers managing Android, iOS and Windows + devices along with a wide range of features that support cooperate (COPE) or personal device (BYOD) + enrollments. +

+
+
+

Access different portals

+

Your log-in credentials to any of our portals(endpoint-mgt, store, publisher) are,

+

Username: $portal-username

+

Password: password provided at registration for an evaluation account.

+

Endpoint management portal URL: $base-url-https/endpoint-mgt/

+

+ This is the portal used to send operations and policies to devices and overall management of + the server. +

+

Application store portal URL: $base-url-https/store

+

+ This is an in-house corporate app store where you can host all your corporate applications. + Users may browse apps and install them to their devices if the administrator has made the apps + publicly visible to users. Administrator can install, uninstall and update apps in the user + device or device groups. +

+

Application publishing portal URL: $base-url-https/publisher

+

+ The portal for publishing new applications for internal use. This is the developer view of the + enterprise application store that comes with the product. +

+
+
+

Enroll a device

+

+ Please find here a set of videos on how to enroll and onboard devices to our Cloud platform. + [Cloud Enrollment Guide] + When enrolling a device, Make sure to use the following log-in format: +

+

Organisation: $tenant-domain

+

Username: $agent-username

+

Password: password provided at registration.

+
+
+

+ If you have any further questions, please reach out to us using your registered mail to + bizdev-group@entgra.io. Looking forward to working with you. +

+

+ Best Regards, +

+

+ Entgra Cloud Team +

+
+
+
+
+ + + ]]> + +
diff --git a/features/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework.server.feature/src/main/resources/conf/webapp-authenticator-config.xml b/features/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework.server.feature/src/main/resources/conf/webapp-authenticator-config.xml index 4b727a28c2..dfea5c07ac 100644 --- a/features/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework.server.feature/src/main/resources/conf/webapp-authenticator-config.xml +++ b/features/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework.server.feature/src/main/resources/conf/webapp-authenticator-config.xml @@ -31,6 +31,10 @@ CertificateAuth org.wso2.carbon.webapp.authenticator.framework.authenticator.CertificateAuthenticator + + OTPAuth + org.wso2.carbon.webapp.authenticator.framework.authenticator.OneTimeTokenAuthenticator + BST org.wso2.carbon.webapp.authenticator.framework.authenticator.BSTAuthenticator diff --git a/pom.xml b/pom.xml index d522b61dab..d12b76d9f4 100644 --- a/pom.xml +++ b/pom.xml @@ -1772,6 +1772,11 @@ maven-checkstyle-plugin ${maven.checkstyle.vesion} + + commons-validator + commons-validator + ${apache.validator.version} + @@ -2219,6 +2224,9 @@ 2.3.2 + + 1.7 + 2.1.7-wso2v7 1.5.11.wso2v15 @@ -2252,7 +2260,7 @@ v12.18.1 3.1.0 - + 7.0.85 1.0