diff --git a/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.api.user.push.common/pom.xml b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.api.user.push.common/pom.xml
new file mode 100644
index 00000000..11597cd6
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.api.user.push.common/pom.xml
@@ -0,0 +1,46 @@
+
+
+ 4.0.0
+
+ org.wso2.carbon.identity.user.api
+ org.wso2.carbon.identity.api.user.push
+ 1.3.39
+
+
+ org.wso2.carbon.identity.api.user.push.common
+ jar
+
+
+
+ org.wso2.carbon.identity.notification.push
+ org.wso2.carbon.identity.notification.push.device.handler
+
+
+ org.springframework
+ spring-web
+ provided
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 1.8
+
+
+
+
+
+
+ 17
+ 17
+ UTF-8
+
+
+
\ No newline at end of file
diff --git a/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.api.user.push.common/src/main/java/org/wso2/carbon/identity/api/user/push/common/PushDeviceManagerServiceDataHolder.java b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.api.user.push.common/src/main/java/org/wso2/carbon/identity/api/user/push/common/PushDeviceManagerServiceDataHolder.java
new file mode 100644
index 00000000..1c0c1a9f
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.api.user.push.common/src/main/java/org/wso2/carbon/identity/api/user/push/common/PushDeviceManagerServiceDataHolder.java
@@ -0,0 +1,31 @@
+package org.wso2.carbon.identity.api.user.push.common;
+
+import org.wso2.carbon.identity.notification.push.device.handler.DeviceHandlerService;
+
+/**
+ * Data holder for Push Device Manager Service.
+ */
+public class PushDeviceManagerServiceDataHolder {
+
+ private static DeviceHandlerService deviceHandlerService;
+
+ /**
+ * Get Device Handler Service.
+ *
+ * @return DeviceHandlerService
+ */
+ public static DeviceHandlerService getDeviceHandlerService() {
+
+ return PushDeviceManagerServiceDataHolder.deviceHandlerService;
+ }
+
+ /**
+ * Set Device Handler Service.
+ *
+ * @param deviceHandlerService DeviceHandlerService
+ */
+ public static void setDeviceHandlerService(DeviceHandlerService deviceHandlerService) {
+
+ PushDeviceManagerServiceDataHolder.deviceHandlerService = deviceHandlerService;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.api.user.push.common/src/main/java/org/wso2/carbon/identity/api/user/push/common/factory/PushDeviceManagerOSGIServiceFactory.java b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.api.user.push.common/src/main/java/org/wso2/carbon/identity/api/user/push/common/factory/PushDeviceManagerOSGIServiceFactory.java
new file mode 100644
index 00000000..87585566
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.api.user.push.common/src/main/java/org/wso2/carbon/identity/api/user/push/common/factory/PushDeviceManagerOSGIServiceFactory.java
@@ -0,0 +1,34 @@
+package org.wso2.carbon.identity.api.user.push.common.factory;
+
+import org.springframework.beans.factory.config.AbstractFactoryBean;
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+import org.wso2.carbon.identity.notification.push.device.handler.DeviceHandlerService;
+
+/**
+ * Push device manager OSGI service factory.
+ */
+public class PushDeviceManagerOSGIServiceFactory extends AbstractFactoryBean {
+
+ private DeviceHandlerService deviceHandlerService;
+
+ @Override
+ public Class> getObjectType() {
+
+ return Object.class;
+ }
+
+ @Override
+ protected DeviceHandlerService createInstance() throws Exception {
+
+ if (this.deviceHandlerService == null) {
+ DeviceHandlerService deviceHandlerService = (DeviceHandlerService) PrivilegedCarbonContext
+ .getThreadLocalCarbonContext().getOSGiService(DeviceHandlerService.class, null);
+ if (deviceHandlerService != null) {
+ this.deviceHandlerService = deviceHandlerService;
+ } else {
+ throw new Exception("Unable to retrieve DeviceHandlerService.");
+ }
+ }
+ return this.deviceHandlerService;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/pom.xml b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/pom.xml
new file mode 100644
index 00000000..46eb4b6f
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/pom.xml
@@ -0,0 +1,162 @@
+
+
+ 4.0.0
+
+ org.wso2.carbon.identity.user.api
+ org.wso2.carbon.identity.api.user.push
+ 1.3.39
+
+
+ org.wso2.carbon.identity.rest.api.user.push.v1
+ WSO2 Identity Server - Push Notification Device Management REST API
+ WSO2 Identity Server - Push Notification Device Management REST API
+ jar
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 1.8
+
+
+
+
+ org.openapitools
+ openapi-generator-maven-plugin
+ 4.1.2
+
+
+
+ generate
+
+
+ ${project.basedir}/src/main/resources/push.yaml
+ org.wso2.carbon.codegen.CxfWso2Generator
+
+ src/gen/java
+ org.wso2.carbon.identity.rest.api.user.push.v1
+ org.wso2.carbon.identity.rest.api.user.push.v1.model
+ org.wso2.carbon.identity.rest.api.user.push.v1
+ java8
+ true
+
+
+ true
+
+
+
+
+
+ org.openapitools
+ cxf-wso2-openapi-generator
+ 1.0.0
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ 1.8
+
+
+ add-source
+ generate-sources
+
+ add-source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.apache.cxf
+ cxf-rt-frontend-jaxrs
+ provided
+
+
+ org.apache.cxf
+ cxf-rt-rs-service-description
+ provided
+
+
+ org.springframework
+ spring-web
+ provided
+
+
+ javax.ws.rs
+ javax.ws.rs-api
+ provided
+
+
+ io.swagger
+ swagger-jaxrs
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-yaml
+
+
+ javax.ws.rs
+ jsr311-api
+
+
+ com.google.guava
+ guava
+
+
+
+
+ com.fasterxml.jackson.jaxrs
+ jackson-jaxrs-json-provider
+ provided
+
+
+ org.wso2.carbon.identity.notification.push
+ org.wso2.carbon.identity.notification.push.device.handler
+ provided
+
+
+ org.wso2.carbon.identity.user.api
+ org.wso2.carbon.identity.api.user.push.common
+ provided
+
+
+ org.wso2.carbon.identity.user.api
+ org.wso2.carbon.identity.api.user.common
+ provided
+
+
+
+
\ No newline at end of file
diff --git a/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/DevicesApi.java b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/DevicesApi.java
new file mode 100644
index 00000000..03bca22a
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/DevicesApi.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. 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.identity.rest.api.user.push.v1;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.apache.cxf.jaxrs.ext.multipart.Attachment;
+import org.apache.cxf.jaxrs.ext.multipart.Multipart;
+import java.io.InputStream;
+import java.util.List;
+
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.DeviceDTO;
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.Error;
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.RegistrationRequestDTO;
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.RegistrationResponseDTO;
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.RemoveRequestDTO;
+import org.wso2.carbon.identity.rest.api.user.push.v1.DevicesApiService;
+
+import javax.validation.Valid;
+import javax.ws.rs.*;
+import javax.ws.rs.core.Response;
+import io.swagger.annotations.*;
+
+import javax.validation.constraints.*;
+
+@Path("/devices")
+@Api(description = "The devices API")
+
+public class DevicesApi {
+
+ @Autowired
+ private DevicesApiService delegate;
+
+ @Valid
+ @DELETE
+ @Path("/{deviceId}")
+
+ @Produces({ "application/json" })
+ @ApiOperation(value = "Remove a registered device", notes = "This API is used to remove a registered device. ", response = Void.class, tags={ "me", })
+ @ApiResponses(value = {
+ @ApiResponse(code = 204, message = "The device was removed.", response = Void.class),
+ @ApiResponse(code = 400, message = "Invalid input in the request.", response = Error.class),
+ @ApiResponse(code = 401, message = "Authentication information is missing or invalid.", response = Void.class),
+ @ApiResponse(code = 403, message = "Access forbidden.", response = Void.class),
+ @ApiResponse(code = 500, message = "Internal server error.", response = Error.class),
+ @ApiResponse(code = 501, message = "Not Implemented.", response = Error.class)
+ })
+ public Response deleteDeviceById(@ApiParam(value = "ID of the device to be removed",required=true) @PathParam("deviceId") String deviceId) {
+
+ return delegate.deleteDeviceById(deviceId );
+ }
+
+ @Valid
+ @GET
+ @Path("/{deviceId}")
+
+ @Produces({ "application/json" })
+ @ApiOperation(value = "Get mobile device details by device ID.", notes = "This API is used to get a specific registered device ", response = DeviceDTO.class, tags={ "me", })
+ @ApiResponses(value = {
+ @ApiResponse(code = 200, message = "Successfully returned the device belongs to the ID", response = DeviceDTO.class),
+ @ApiResponse(code = 400, message = "Invalid input in the request.", response = Error.class),
+ @ApiResponse(code = 401, message = "Authentication information is missing or invalid.", response = Void.class),
+ @ApiResponse(code = 403, message = "Access forbidden.", response = Void.class),
+ @ApiResponse(code = 500, message = "Internal server error.", response = Error.class),
+ @ApiResponse(code = 501, message = "Not Implemented.", response = Error.class)
+ })
+ public Response getDeviceById(@ApiParam(value = "ID of the device to be returned",required=true) @PathParam("deviceId") String deviceId) {
+
+ return delegate.getDeviceById(deviceId );
+ }
+
+ @Valid
+ @POST
+
+ @Consumes({ "application/json" })
+ @Produces({ "application/json" })
+ @ApiOperation(value = "Register mobile devices to receive push notifications.", notes = "This API is used to register a push notification device into the Identity Server. This API will be invoked from the mobile device. ", response = RegistrationResponseDTO.class, tags={ "mobile", })
+ @ApiResponses(value = {
+ @ApiResponse(code = 201, message = "Registered a new device", response = RegistrationResponseDTO.class),
+ @ApiResponse(code = 400, message = "Invalid input in the request.", response = Error.class),
+ @ApiResponse(code = 401, message = "Authentication information is missing or invalid.", response = Void.class),
+ @ApiResponse(code = 403, message = "Access forbidden.", response = Void.class),
+ @ApiResponse(code = 500, message = "Internal server error.", response = Error.class),
+ @ApiResponse(code = 501, message = "Not Implemented.", response = Error.class)
+ })
+ public Response registerDevice(@ApiParam(value = "Request body sent by a device for registration." ,required=true) @Valid RegistrationRequestDTO registrationRequestDTO) {
+
+ return delegate.registerDevice(registrationRequestDTO );
+ }
+
+ @Valid
+ @POST
+ @Path("/{deviceId}/remove")
+ @Consumes({ "application/json" })
+ @Produces({ "application/json" })
+ @ApiOperation(value = "Remove a registered device from the mobile device.", notes = "This API is used to remove a registered device through mobile device. ", response = Void.class, tags={ "mobile" })
+ @ApiResponses(value = {
+ @ApiResponse(code = 204, message = "The device was removed.", response = Void.class),
+ @ApiResponse(code = 400, message = "Invalid input in the request.", response = Error.class),
+ @ApiResponse(code = 401, message = "Authentication information is missing or invalid.", response = Void.class),
+ @ApiResponse(code = 403, message = "Access forbidden.", response = Void.class),
+ @ApiResponse(code = 500, message = "Internal server error.", response = Error.class),
+ @ApiResponse(code = 501, message = "Not Implemented.", response = Error.class)
+ })
+ public Response removeDeviceFromMobile(@ApiParam(value = "ID of the device to be removed",required=true) @PathParam("deviceId") String deviceId, @ApiParam(value = "Remove request sent from the device." ,required=true) @Valid RemoveRequestDTO removeRequestDTO) {
+
+ return delegate.removeDeviceFromMobile(deviceId, removeRequestDTO );
+ }
+
+}
diff --git a/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/DevicesApiService.java b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/DevicesApiService.java
new file mode 100644
index 00000000..24bff3f5
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/DevicesApiService.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. 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.identity.rest.api.user.push.v1;
+
+import org.wso2.carbon.identity.rest.api.user.push.v1.*;
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.*;
+import org.apache.cxf.jaxrs.ext.multipart.Attachment;
+import org.apache.cxf.jaxrs.ext.multipart.Multipart;
+import java.io.InputStream;
+import java.util.List;
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.DeviceDTO;
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.Error;
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.RegistrationRequestDTO;
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.RegistrationResponseDTO;
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.RemoveRequestDTO;
+import javax.ws.rs.core.Response;
+
+
+public interface DevicesApiService {
+
+ public Response deleteDeviceById(String deviceId);
+
+ public Response getDeviceById(String deviceId);
+
+ public Response registerDevice(RegistrationRequestDTO registrationRequestDTO);
+
+ public Response removeDeviceFromMobile(String deviceId, RemoveRequestDTO removeRequestDTO);
+}
diff --git a/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/DiscoveryDataApi.java b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/DiscoveryDataApi.java
new file mode 100644
index 00000000..8c9edf51
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/DiscoveryDataApi.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. 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.identity.rest.api.user.push.v1;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.apache.cxf.jaxrs.ext.multipart.Attachment;
+import org.apache.cxf.jaxrs.ext.multipart.Multipart;
+import java.io.InputStream;
+import java.util.List;
+
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.DiscoveryDataDTO;
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.Error;
+import org.wso2.carbon.identity.rest.api.user.push.v1.DiscoveryDataApiService;
+
+import javax.validation.Valid;
+import javax.ws.rs.*;
+import javax.ws.rs.core.Response;
+import io.swagger.annotations.*;
+
+import javax.validation.constraints.*;
+
+@Path("/discovery-data")
+@Api(description = "The discovery-data API")
+
+public class DiscoveryDataApi {
+
+ @Autowired
+ private DiscoveryDataApiService delegate;
+
+ @Valid
+ @GET
+
+
+ @Produces({ "application/json" })
+ @ApiOperation(value = "Generate data for device registration. ", notes = "This API is used to generate discovery data for the device registration QR code. ", response = DiscoveryDataDTO.class, tags={ "me" })
+ @ApiResponses(value = {
+ @ApiResponse(code = 200, message = "Successfully generated registration discovery data.", response = DiscoveryDataDTO.class),
+ @ApiResponse(code = 400, message = "Invalid input in the request.", response = Error.class),
+ @ApiResponse(code = 401, message = "Authentication information is missing or invalid.", response = Void.class),
+ @ApiResponse(code = 403, message = "Access forbidden.", response = Void.class),
+ @ApiResponse(code = 500, message = "Internal server error.", response = Error.class),
+ @ApiResponse(code = 501, message = "Not Implemented.", response = Error.class)
+ })
+ public Response getRegistrationDiscoveryData() {
+
+ return delegate.getRegistrationDiscoveryData();
+ }
+
+}
diff --git a/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/DiscoveryDataApiService.java b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/DiscoveryDataApiService.java
new file mode 100644
index 00000000..24993e8c
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/DiscoveryDataApiService.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. 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.identity.rest.api.user.push.v1;
+
+import org.wso2.carbon.identity.rest.api.user.push.v1.*;
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.*;
+import org.apache.cxf.jaxrs.ext.multipart.Attachment;
+import org.apache.cxf.jaxrs.ext.multipart.Multipart;
+import java.io.InputStream;
+import java.util.List;
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.DiscoveryDataDTO;
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.Error;
+import javax.ws.rs.core.Response;
+
+
+public interface DiscoveryDataApiService {
+
+ public Response getRegistrationDiscoveryData();
+}
diff --git a/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/factories/DevicesApiServiceFactory.java b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/factories/DevicesApiServiceFactory.java
new file mode 100644
index 00000000..4e98d562
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/factories/DevicesApiServiceFactory.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. 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.identity.rest.api.user.push.v1.factories;
+
+import org.wso2.carbon.identity.rest.api.user.push.v1.DevicesApiService;
+import org.wso2.carbon.identity.rest.api.user.push.v1.impl.DevicesApiServiceImpl;
+
+public class DevicesApiServiceFactory {
+
+ private final static DevicesApiService service = new DevicesApiServiceImpl();
+
+ public static DevicesApiService getDevicesApi()
+ {
+ return service;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/factories/DiscoveryDataApiServiceFactory.java b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/factories/DiscoveryDataApiServiceFactory.java
new file mode 100644
index 00000000..fd9df4bf
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/factories/DiscoveryDataApiServiceFactory.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. 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.identity.rest.api.user.push.v1.factories;
+
+import org.wso2.carbon.identity.rest.api.user.push.v1.DiscoveryDataApiService;
+import org.wso2.carbon.identity.rest.api.user.push.v1.impl.DiscoveryDataApiServiceImpl;
+
+public class DiscoveryDataApiServiceFactory {
+
+ private final static DiscoveryDataApiService service = new DiscoveryDataApiServiceImpl();
+
+ public static DiscoveryDataApiService getDiscoveryDataApi()
+ {
+ return service;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/model/DeviceDTO.java b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/model/DeviceDTO.java
new file mode 100644
index 00000000..80887710
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/model/DeviceDTO.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. 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.identity.rest.api.user.push.v1.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import javax.validation.constraints.*;
+
+/**
+ * Model for the registered device object
+ **/
+
+import io.swagger.annotations.*;
+import java.util.Objects;
+import javax.validation.Valid;
+import javax.xml.bind.annotation.*;
+@ApiModel(description = "Model for the registered device object")
+public class DeviceDTO {
+
+ private String deviceId;
+ private String name;
+ private String model;
+ private String provider;
+
+ /**
+ **/
+ public DeviceDTO deviceId(String deviceId) {
+
+ this.deviceId = deviceId;
+ return this;
+ }
+
+ @ApiModelProperty(example = "b03f90c9-6723-48f6-863b-a35f1ac77f57", value = "")
+ @JsonProperty("deviceId")
+ @Valid
+ public String getDeviceId() {
+ return deviceId;
+ }
+ public void setDeviceId(String deviceId) {
+ this.deviceId = deviceId;
+ }
+
+ /**
+ **/
+ public DeviceDTO name(String name) {
+
+ this.name = name;
+ return this;
+ }
+
+ @ApiModelProperty(example = "My Phone", value = "")
+ @JsonProperty("name")
+ @Valid
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ **/
+ public DeviceDTO model(String model) {
+
+ this.model = model;
+ return this;
+ }
+
+ @ApiModelProperty(example = "iPhone 16", value = "")
+ @JsonProperty("model")
+ @Valid
+ public String getModel() {
+ return model;
+ }
+ public void setModel(String model) {
+ this.model = model;
+ }
+
+ /**
+ **/
+ public DeviceDTO provider(String provider) {
+
+ this.provider = provider;
+ return this;
+ }
+
+ @ApiModelProperty(example = "fcm", value = "")
+ @JsonProperty("provider")
+ @Valid
+ public String getProvider() {
+ return provider;
+ }
+ public void setProvider(String provider) {
+ this.provider = provider;
+ }
+
+
+
+ @Override
+ public boolean equals(java.lang.Object o) {
+
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ DeviceDTO deviceDTO = (DeviceDTO) o;
+ return Objects.equals(this.deviceId, deviceDTO.deviceId) &&
+ Objects.equals(this.name, deviceDTO.name) &&
+ Objects.equals(this.model, deviceDTO.model) &&
+ Objects.equals(this.provider, deviceDTO.provider);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(deviceId, name, model, provider);
+ }
+
+ @Override
+ public String toString() {
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("class DeviceDTO {\n");
+
+ sb.append(" deviceId: ").append(toIndentedString(deviceId)).append("\n");
+ sb.append(" name: ").append(toIndentedString(name)).append("\n");
+ sb.append(" model: ").append(toIndentedString(model)).append("\n");
+ sb.append(" provider: ").append(toIndentedString(provider)).append("\n");
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces
+ * (except the first line).
+ */
+ private String toIndentedString(java.lang.Object o) {
+
+ if (o == null) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n");
+ }
+}
+
diff --git a/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/model/DiscoveryDataDTO.java b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/model/DiscoveryDataDTO.java
new file mode 100644
index 00000000..66ea3cc0
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/model/DiscoveryDataDTO.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. 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.identity.rest.api.user.push.v1.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import javax.validation.constraints.*;
+
+/**
+ * Device registration information
+ **/
+
+import io.swagger.annotations.*;
+import java.util.Objects;
+import javax.validation.Valid;
+import javax.xml.bind.annotation.*;
+@ApiModel(description = "Device registration information")
+public class DiscoveryDataDTO {
+
+ private String did;
+ private String un;
+ private String td;
+ private String ae;
+ private String re;
+ private String rde;
+ private String chg;
+
+ /**
+ * Device ID
+ **/
+ public DiscoveryDataDTO did(String did) {
+
+ this.did = did;
+ return this;
+ }
+
+ @ApiModelProperty(example = "b03f90c9-6723-48f6-863b-a35f1ac77f57", value = "Device ID")
+ @JsonProperty("did")
+ @Valid
+ public String getDid() {
+ return did;
+ }
+ public void setDid(String did) {
+ this.did = did;
+ }
+
+ /**
+ * Username
+ **/
+ public DiscoveryDataDTO un(String un) {
+
+ this.un = un;
+ return this;
+ }
+
+ @ApiModelProperty(example = "admin", value = "Username")
+ @JsonProperty("un")
+ @Valid
+ public String getUn() {
+ return un;
+ }
+ public void setUn(String un) {
+ this.un = un;
+ }
+
+ /**
+ * Tenant domain or Organization
+ **/
+ public DiscoveryDataDTO td(String td) {
+
+ this.td = td;
+ return this;
+ }
+
+ @ApiModelProperty(example = "carbon.super", value = "Tenant domain or Organization")
+ @JsonProperty("td")
+ @Valid
+ public String getTd() {
+ return td;
+ }
+ public void setTd(String td) {
+ this.td = td;
+ }
+
+ /**
+ * Authentication endpoint
+ **/
+ public DiscoveryDataDTO ae(String ae) {
+
+ this.ae = ae;
+ return this;
+ }
+
+ @ApiModelProperty(example = "https://localhost:9443/push-auth/authenticate", value = "Authentication endpoint")
+ @JsonProperty("ae")
+ @Valid
+ public String getAe() {
+ return ae;
+ }
+ public void setAe(String ae) {
+ this.ae = ae;
+ }
+
+ /**
+ * Registration endpoint
+ **/
+ public DiscoveryDataDTO re(String re) {
+
+ this.re = re;
+ return this;
+ }
+
+ @ApiModelProperty(example = "https://localhost:9443/api/users/v1/me/push/devices", value = "Registration endpoint")
+ @JsonProperty("re")
+ @Valid
+ public String getRe() {
+ return re;
+ }
+ public void setRe(String re) {
+ this.re = re;
+ }
+
+ /**
+ * Remove device endpoint
+ **/
+ public DiscoveryDataDTO rde(String rde) {
+
+ this.rde = rde;
+ return this;
+ }
+
+ @ApiModelProperty(example = "https://localhost:9443/api/users/v1/me/push/devices/deviceId/remove", value = "Remove device endpoint")
+ @JsonProperty("rde")
+ @Valid
+ public String getRde() {
+ return rde;
+ }
+ public void setRde(String rde) {
+ this.rde = rde;
+ }
+
+ /**
+ * Challenge
+ **/
+ public DiscoveryDataDTO chg(String chg) {
+
+ this.chg = chg;
+ return this;
+ }
+
+ @ApiModelProperty(example = "b03f90c9-6723-48f6-863b-a35f1ac77f57", value = "Challenge")
+ @JsonProperty("chg")
+ @Valid
+ public String getChg() {
+ return chg;
+ }
+ public void setChg(String chg) {
+ this.chg = chg;
+ }
+
+
+
+ @Override
+ public boolean equals(java.lang.Object o) {
+
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ DiscoveryDataDTO discoveryDataDTO = (DiscoveryDataDTO) o;
+ return Objects.equals(this.did, discoveryDataDTO.did) &&
+ Objects.equals(this.un, discoveryDataDTO.un) &&
+ Objects.equals(this.td, discoveryDataDTO.td) &&
+ Objects.equals(this.ae, discoveryDataDTO.ae) &&
+ Objects.equals(this.re, discoveryDataDTO.re) &&
+ Objects.equals(this.rde, discoveryDataDTO.rde) &&
+ Objects.equals(this.chg, discoveryDataDTO.chg);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(did, un, td, ae, re, rde, chg);
+ }
+
+ @Override
+ public String toString() {
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("class DiscoveryDataDTO {\n");
+
+ sb.append(" did: ").append(toIndentedString(did)).append("\n");
+ sb.append(" un: ").append(toIndentedString(un)).append("\n");
+ sb.append(" td: ").append(toIndentedString(td)).append("\n");
+ sb.append(" ae: ").append(toIndentedString(ae)).append("\n");
+ sb.append(" re: ").append(toIndentedString(re)).append("\n");
+ sb.append(" rde: ").append(toIndentedString(rde)).append("\n");
+ sb.append(" chg: ").append(toIndentedString(chg)).append("\n");
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces
+ * (except the first line).
+ */
+ private String toIndentedString(java.lang.Object o) {
+
+ if (o == null) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n");
+ }
+}
+
diff --git a/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/model/Error.java b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/model/Error.java
new file mode 100644
index 00000000..e6067c5a
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/model/Error.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. 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.identity.rest.api.user.push.v1.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import javax.validation.constraints.*;
+
+
+import io.swagger.annotations.*;
+import java.util.Objects;
+import javax.validation.Valid;
+import javax.xml.bind.annotation.*;
+
+public class Error {
+
+ private String code;
+ private String message;
+ private String description;
+ private String traceId;
+
+ /**
+ * An error code.
+ **/
+ public Error code(String code) {
+
+ this.code = code;
+ return this;
+ }
+
+ @ApiModelProperty(example = "UOM-00000", required = true, value = "An error code.")
+ @JsonProperty("code")
+ @Valid
+ @NotNull(message = "Property code cannot be null.")
+
+ public String getCode() {
+ return code;
+ }
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ /**
+ * An error message.
+ **/
+ public Error message(String message) {
+
+ this.message = message;
+ return this;
+ }
+
+ @ApiModelProperty(example = "Some Error Message", required = true, value = "An error message.")
+ @JsonProperty("message")
+ @Valid
+ @NotNull(message = "Property message cannot be null.")
+
+ public String getMessage() {
+ return message;
+ }
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ /**
+ * An error description.
+ **/
+ public Error description(String description) {
+
+ this.description = description;
+ return this;
+ }
+
+ @ApiModelProperty(example = "Some Error Description", value = "An error description.")
+ @JsonProperty("description")
+ @Valid
+ public String getDescription() {
+ return description;
+ }
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ /**
+ * An error trace identifier.
+ **/
+ public Error traceId(String traceId) {
+
+ this.traceId = traceId;
+ return this;
+ }
+
+ @ApiModelProperty(example = "e0fbcfeb-3617-43c4-8dd0-7b7d38e13047", value = "An error trace identifier.")
+ @JsonProperty("traceId")
+ @Valid
+ public String getTraceId() {
+ return traceId;
+ }
+ public void setTraceId(String traceId) {
+ this.traceId = traceId;
+ }
+
+
+
+ @Override
+ public boolean equals(java.lang.Object o) {
+
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Error error = (Error) o;
+ return Objects.equals(this.code, error.code) &&
+ Objects.equals(this.message, error.message) &&
+ Objects.equals(this.description, error.description) &&
+ Objects.equals(this.traceId, error.traceId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(code, message, description, traceId);
+ }
+
+ @Override
+ public String toString() {
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("class Error {\n");
+
+ sb.append(" code: ").append(toIndentedString(code)).append("\n");
+ sb.append(" message: ").append(toIndentedString(message)).append("\n");
+ sb.append(" description: ").append(toIndentedString(description)).append("\n");
+ sb.append(" traceId: ").append(toIndentedString(traceId)).append("\n");
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces
+ * (except the first line).
+ */
+ private String toIndentedString(java.lang.Object o) {
+
+ if (o == null) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n");
+ }
+}
+
diff --git a/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/model/RegistrationRequestDTO.java b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/model/RegistrationRequestDTO.java
new file mode 100644
index 00000000..b0671265
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/model/RegistrationRequestDTO.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. 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.identity.rest.api.user.push.v1.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import javax.validation.constraints.*;
+
+/**
+ * The registration request body sent from the mobile device
+ **/
+
+import io.swagger.annotations.*;
+import java.util.Objects;
+import javax.validation.Valid;
+import javax.xml.bind.annotation.*;
+@ApiModel(description = "The registration request body sent from the mobile device")
+public class RegistrationRequestDTO {
+
+ private String deviceId;
+ private String model;
+ private String name;
+ private String deviceToken;
+ private String publicKey;
+ private String signature;
+
+ /**
+ * Unique UUID for the device
+ **/
+ public RegistrationRequestDTO deviceId(String deviceId) {
+
+ this.deviceId = deviceId;
+ return this;
+ }
+
+ @ApiModelProperty(example = "b03f90c9-6723-48f6-863b-a35f1ac77f57", value = "Unique UUID for the device")
+ @JsonProperty("deviceId")
+ @Valid
+ public String getDeviceId() {
+ return deviceId;
+ }
+ public void setDeviceId(String deviceId) {
+ this.deviceId = deviceId;
+ }
+
+ /**
+ * Model of the device
+ **/
+ public RegistrationRequestDTO model(String model) {
+
+ this.model = model;
+ return this;
+ }
+
+ @ApiModelProperty(example = "iPhone 16", value = "Model of the device")
+ @JsonProperty("model")
+ @Valid
+ public String getModel() {
+ return model;
+ }
+ public void setModel(String model) {
+ this.model = model;
+ }
+
+ /**
+ * Name of the device
+ **/
+ public RegistrationRequestDTO name(String name) {
+
+ this.name = name;
+ return this;
+ }
+
+ @ApiModelProperty(example = "My Device", value = "Name of the device")
+ @JsonProperty("name")
+ @Valid
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * device token unique to the device
+ **/
+ public RegistrationRequestDTO deviceToken(String deviceToken) {
+
+ this.deviceToken = deviceToken;
+ return this;
+ }
+
+ @ApiModelProperty(example = "fuRr8s_eQrmB88nu5Tz8oa:APA91bFMqYbuzDYyOGK28VoiLHWYXZYzGNVg3tfxfNwKPH-jDIFpNDdUHkmq5wqBUySYZnuHfpycyQvUrPhwV3UZ1YzjUNLvb9gzFZudfJd1N3fWuU0w2nq_hVJc0UPRabvNPuJy8wMB", value = "device token unique to the device")
+ @JsonProperty("deviceToken")
+ @Valid
+ public String getDeviceToken() {
+ return deviceToken;
+ }
+ public void setDeviceToken(String deviceToken) {
+ this.deviceToken = deviceToken;
+ }
+
+ /**
+ * Public key of the keypair generated by the device for the account
+ **/
+ public RegistrationRequestDTO publicKey(String publicKey) {
+
+ this.publicKey = publicKey;
+ return this;
+ }
+
+ @ApiModelProperty(example = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOhCpj5pAEqdCdyxuHii0oLFAgnTePMI1EeomZHCRaZZNGv8fdcHyme9rpknNx/caAz9Gck5HrB/vto86cHpBkAghsBBLLWPUlblWNZCBX4pqFhZu+uZKvOnSqp1SwP13yx72nLKbjHRRJGgwCrg/mbdSGN/QKxRU+UhdKVVpQIDAQAB", value = "Public key of the keypair generated by the device for the account")
+ @JsonProperty("publicKey")
+ @Valid
+ public String getPublicKey() {
+ return publicKey;
+ }
+ public void setPublicKey(String publicKey) {
+ this.publicKey = publicKey;
+ }
+
+ /**
+ * Signature string comprising of the pushId and the challenge
+ **/
+ public RegistrationRequestDTO signature(String signature) {
+
+ this.signature = signature;
+ return this;
+ }
+
+ @ApiModelProperty(example = "rT/VxgPYMioT6wHajYg0mJpBv46HvFBm/elZ/VL4ClUIFfX7i3Ou5ER5sEiFtehaurLXPNsA8hF4SQAueVBRymEAmchhwYlT160g3wv6kDQvWLkTqnLWGfn++wg5xRManOoN9zG9GhxCgRr9y+lk9rtvydfX0lTcdEZBkynSJnM=", value = "Signature string comprising of the pushId and the challenge")
+ @JsonProperty("signature")
+ @Valid
+ public String getSignature() {
+ return signature;
+ }
+ public void setSignature(String signature) {
+ this.signature = signature;
+ }
+
+
+
+ @Override
+ public boolean equals(java.lang.Object o) {
+
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ RegistrationRequestDTO registrationRequestDTO = (RegistrationRequestDTO) o;
+ return Objects.equals(this.deviceId, registrationRequestDTO.deviceId) &&
+ Objects.equals(this.model, registrationRequestDTO.model) &&
+ Objects.equals(this.name, registrationRequestDTO.name) &&
+ Objects.equals(this.deviceToken, registrationRequestDTO.deviceToken) &&
+ Objects.equals(this.publicKey, registrationRequestDTO.publicKey) &&
+ Objects.equals(this.signature, registrationRequestDTO.signature);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(deviceId, model, name, deviceToken, publicKey, signature);
+ }
+
+ @Override
+ public String toString() {
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("class RegistrationRequestDTO {\n");
+
+ sb.append(" deviceId: ").append(toIndentedString(deviceId)).append("\n");
+ sb.append(" model: ").append(toIndentedString(model)).append("\n");
+ sb.append(" name: ").append(toIndentedString(name)).append("\n");
+ sb.append(" deviceToken: ").append(toIndentedString(deviceToken)).append("\n");
+ sb.append(" publicKey: ").append(toIndentedString(publicKey)).append("\n");
+ sb.append(" signature: ").append(toIndentedString(signature)).append("\n");
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces
+ * (except the first line).
+ */
+ private String toIndentedString(java.lang.Object o) {
+
+ if (o == null) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n");
+ }
+}
+
diff --git a/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/model/RegistrationResponseDTO.java b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/model/RegistrationResponseDTO.java
new file mode 100644
index 00000000..7d1f59da
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/model/RegistrationResponseDTO.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. 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.identity.rest.api.user.push.v1.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import javax.validation.constraints.*;
+
+/**
+ * The registration response sent after successful device registration.
+ **/
+
+import io.swagger.annotations.*;
+import java.util.Objects;
+import javax.validation.Valid;
+import javax.xml.bind.annotation.*;
+@ApiModel(description = "The registration response sent after successful device registration.")
+public class RegistrationResponseDTO {
+
+ private String deviceId;
+
+ /**
+ * Unique UUID for the device.
+ **/
+ public RegistrationResponseDTO deviceId(String deviceId) {
+
+ this.deviceId = deviceId;
+ return this;
+ }
+
+ @ApiModelProperty(example = "b03f90c9-6723-48f6-863b-a35f1ac77f57", value = "Unique UUID for the device.")
+ @JsonProperty("deviceId")
+ @Valid
+ public String getDeviceId() {
+ return deviceId;
+ }
+ public void setDeviceId(String deviceId) {
+ this.deviceId = deviceId;
+ }
+
+
+
+ @Override
+ public boolean equals(java.lang.Object o) {
+
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ RegistrationResponseDTO registrationResponseDTO = (RegistrationResponseDTO) o;
+ return Objects.equals(this.deviceId, registrationResponseDTO.deviceId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(deviceId);
+ }
+
+ @Override
+ public String toString() {
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("class RegistrationResponseDTO {\n");
+
+ sb.append(" deviceId: ").append(toIndentedString(deviceId)).append("\n");
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces
+ * (except the first line).
+ */
+ private String toIndentedString(java.lang.Object o) {
+
+ if (o == null) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n");
+ }
+}
+
diff --git a/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/model/RemoveRequestDTO.java b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/model/RemoveRequestDTO.java
new file mode 100644
index 00000000..e82828c2
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/gen/java/org/wso2/carbon/identity/rest/api/user/push/v1/model/RemoveRequestDTO.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. 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.identity.rest.api.user.push.v1.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import javax.validation.constraints.*;
+
+/**
+ * Remove device request body sent from the mobile device
+ **/
+
+import io.swagger.annotations.*;
+import java.util.Objects;
+import javax.validation.Valid;
+import javax.xml.bind.annotation.*;
+@ApiModel(description = "Remove device request body sent from the mobile device")
+public class RemoveRequestDTO {
+
+ private String token;
+
+ /**
+ * JWT containing the remove device information signed with a unique private key
+ **/
+ public RemoveRequestDTO token(String token) {
+
+ this.token = token;
+ return this;
+ }
+
+ @ApiModelProperty(example = "signedDeviceToken", required = true, value = "JWT containing the remove device information signed with a unique private key")
+ @JsonProperty("token")
+ @Valid
+ @NotNull(message = "Property token cannot be null.")
+
+ public String getToken() {
+ return token;
+ }
+ public void setToken(String token) {
+ this.token = token;
+ }
+
+
+
+ @Override
+ public boolean equals(java.lang.Object o) {
+
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ RemoveRequestDTO removeRequestDTO = (RemoveRequestDTO) o;
+ return Objects.equals(this.token, removeRequestDTO.token);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(token);
+ }
+
+ @Override
+ public String toString() {
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("class RemoveRequestDTO {\n");
+
+ sb.append(" token: ").append(toIndentedString(token)).append("\n");
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces
+ * (except the first line).
+ */
+ private String toIndentedString(java.lang.Object o) {
+
+ if (o == null) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n");
+ }
+}
+
diff --git a/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/main/java/org/wso2/carbon/identity/rest/api/user/push/v1/core/PushDeviceManagementService.java b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/main/java/org/wso2/carbon/identity/rest/api/user/push/v1/core/PushDeviceManagementService.java
new file mode 100644
index 00000000..6347567b
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/main/java/org/wso2/carbon/identity/rest/api/user/push/v1/core/PushDeviceManagementService.java
@@ -0,0 +1,127 @@
+package org.wso2.carbon.identity.rest.api.user.push.v1.core;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+import org.wso2.carbon.identity.api.user.common.ContextLoader;
+import org.wso2.carbon.identity.api.user.push.common.PushDeviceManagerServiceDataHolder;
+import org.wso2.carbon.identity.application.common.model.User;
+import org.wso2.carbon.identity.notification.push.device.handler.exception.PushDeviceHandlerException;
+import org.wso2.carbon.identity.notification.push.device.handler.model.Device;
+import org.wso2.carbon.identity.notification.push.device.handler.model.RegistrationDiscoveryData;
+import org.wso2.carbon.identity.notification.push.device.handler.model.RegistrationRequest;
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.DeviceDTO;
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.DiscoveryDataDTO;
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.RegistrationRequestDTO;
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.RegistrationResponseDTO;
+
+import static org.wso2.carbon.identity.rest.api.user.push.v1.util.Util.handlePushDeviceHandlerException;
+
+/**
+ * Service class for push device management.
+ */
+public class PushDeviceManagementService {
+
+ private static final Log log = LogFactory.getLog(PushDeviceManagementService.class);
+
+ /**
+ * Get registration discovery data.
+ *
+ * @return Registration discovery data.
+ */
+ public DiscoveryDataDTO getRegistrationDiscoveryData() {
+
+ User user = ContextLoader.getUserFromContext();
+ String username = user.toFullQualifiedUsername();
+ String tenantDomain = user.getTenantDomain();
+ try {
+ RegistrationDiscoveryData data = PushDeviceManagerServiceDataHolder.getDeviceHandlerService()
+ .getRegistrationDiscoveryData(username, tenantDomain);
+ return buildDiscoveryDataDTO(data);
+ } catch (PushDeviceHandlerException e) {
+ throw handlePushDeviceHandlerException(e);
+ }
+ }
+
+ public DeviceDTO getDevice(String deviceId) {
+
+ try {
+ Device device = PushDeviceManagerServiceDataHolder.getDeviceHandlerService().getDevice(deviceId);
+ return buildDeviceDTO(device);
+ } catch (PushDeviceHandlerException e) {
+ throw handlePushDeviceHandlerException(e);
+ }
+ }
+
+ public void removeDevice(String deviceId) {
+
+ try {
+ PushDeviceManagerServiceDataHolder.getDeviceHandlerService().unregisterDevice(deviceId);
+ } catch (PushDeviceHandlerException e) {
+ throw handlePushDeviceHandlerException(e);
+ }
+ }
+
+ public void removeDeviceFromMobile(String deviceId, String token) {
+
+ try {
+ PushDeviceManagerServiceDataHolder.getDeviceHandlerService().unregisterDeviceMobile(deviceId, token);
+ } catch (PushDeviceHandlerException e) {
+ throw handlePushDeviceHandlerException(e);
+ }
+ }
+
+ public RegistrationResponseDTO registerDevice(RegistrationRequestDTO registrationRequestDTO) {
+
+ String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
+ RegistrationRequest request = buildRegistrationRequest(registrationRequestDTO);
+ try {
+ Device device = PushDeviceManagerServiceDataHolder.getDeviceHandlerService()
+ .registerDevice(request, tenantDomain);
+ RegistrationResponseDTO responseDTO = new RegistrationResponseDTO();
+ responseDTO.setDeviceId(device.getDeviceId());
+ return responseDTO;
+ } catch (PushDeviceHandlerException e) {
+ throw handlePushDeviceHandlerException(e);
+ }
+ }
+
+ private DiscoveryDataDTO buildDiscoveryDataDTO(RegistrationDiscoveryData data) {
+
+ DiscoveryDataDTO discoveryDataDTO = new DiscoveryDataDTO();
+ discoveryDataDTO.setDid(data.getDeviceId());
+ discoveryDataDTO.setUn(data.getUsername());
+ discoveryDataDTO.setTd(data.getTenantDomain());
+ if (StringUtils.isNotBlank(data.getOrganizationName())) {
+ discoveryDataDTO.setTd(data.getOrganizationName());
+ }
+ discoveryDataDTO.setChg(data.getChallenge());
+ discoveryDataDTO.setRe(data.getRegistrationEndpoint());
+ discoveryDataDTO.setAe(data.getAuthenticationEndpoint());
+ discoveryDataDTO.setRde(data.getRemoveDeviceEndpoint());
+ return discoveryDataDTO;
+ }
+
+ private DeviceDTO buildDeviceDTO(Device device) {
+
+ DeviceDTO deviceDTO = new DeviceDTO();
+ deviceDTO.setDeviceId(device.getDeviceId());
+ deviceDTO.setName(device.getDeviceName());
+ deviceDTO.setModel(device.getDeviceModel());
+ deviceDTO.setProvider(device.getProvider());
+ return deviceDTO;
+ }
+
+ private RegistrationRequest buildRegistrationRequest(RegistrationRequestDTO dto) {
+
+ RegistrationRequest request = new RegistrationRequest();
+ request.setDeviceId(dto.getDeviceId());
+ request.setDeviceName(dto.getName());
+ request.setDeviceModel(dto.getModel());
+ request.setDeviceToken(dto.getDeviceToken());
+ request.setPublicKey(dto.getPublicKey());
+ request.setSignature(dto.getSignature());
+ return request;
+ }
+}
diff --git a/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/main/java/org/wso2/carbon/identity/rest/api/user/push/v1/exception/PushDeviceManagementException.java b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/main/java/org/wso2/carbon/identity/rest/api/user/push/v1/exception/PushDeviceManagementException.java
new file mode 100644
index 00000000..a8ab6140
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/main/java/org/wso2/carbon/identity/rest/api/user/push/v1/exception/PushDeviceManagementException.java
@@ -0,0 +1,23 @@
+package org.wso2.carbon.identity.rest.api.user.push.v1.exception;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+/**
+ * Custom exception for push device management.
+ */
+public class PushDeviceManagementException extends WebApplicationException {
+
+ public PushDeviceManagementException(Response.Status status, Error error) {
+
+ super(Response.status(status).entity(error).header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
+ .build());
+ }
+
+ public PushDeviceManagementException(Response.Status status) {
+
+ super(Response.status(status).build());
+ }
+}
diff --git a/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/main/java/org/wso2/carbon/identity/rest/api/user/push/v1/impl/DevicesApiServiceImpl.java b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/main/java/org/wso2/carbon/identity/rest/api/user/push/v1/impl/DevicesApiServiceImpl.java
new file mode 100644
index 00000000..93228983
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/main/java/org/wso2/carbon/identity/rest/api/user/push/v1/impl/DevicesApiServiceImpl.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. 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.identity.rest.api.user.push.v1.impl;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.wso2.carbon.identity.rest.api.user.push.v1.DevicesApiService;
+import org.wso2.carbon.identity.rest.api.user.push.v1.core.PushDeviceManagementService;
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.DeviceDTO;
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.RegistrationRequestDTO;
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.RegistrationResponseDTO;
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.RemoveRequestDTO;
+
+import javax.ws.rs.core.Response;
+
+/**
+ * Implementation class of Push device Handler User APIs.
+ */
+public class DevicesApiServiceImpl implements DevicesApiService {
+
+ @Autowired
+ private PushDeviceManagementService pushDeviceManagementService;
+
+ @Override
+ public Response deleteDeviceById(String deviceId) {
+
+ pushDeviceManagementService.removeDevice(deviceId);
+ return Response.noContent().build();
+ }
+
+ @Override
+ public Response getDeviceById(String deviceId) {
+
+ DeviceDTO deviceDTO = pushDeviceManagementService.getDevice(deviceId);
+ return Response.ok().entity(deviceDTO).build();
+ }
+
+ @Override
+ public Response registerDevice(RegistrationRequestDTO registrationRequestDTO) {
+
+ RegistrationResponseDTO responseDTO = pushDeviceManagementService.registerDevice(registrationRequestDTO);
+ return Response.ok().entity(responseDTO).build();
+ }
+
+ @Override
+ public Response removeDeviceFromMobile(String deviceId, RemoveRequestDTO removeRequestDTO) {
+
+ String token = removeRequestDTO.getToken();
+ pushDeviceManagementService.removeDeviceFromMobile(deviceId, token);
+ return Response.noContent().build();
+ }
+}
diff --git a/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/main/java/org/wso2/carbon/identity/rest/api/user/push/v1/impl/DiscoveryDataApiServiceImpl.java b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/main/java/org/wso2/carbon/identity/rest/api/user/push/v1/impl/DiscoveryDataApiServiceImpl.java
new file mode 100644
index 00000000..21950600
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/main/java/org/wso2/carbon/identity/rest/api/user/push/v1/impl/DiscoveryDataApiServiceImpl.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. 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.identity.rest.api.user.push.v1.impl;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.wso2.carbon.identity.rest.api.user.push.v1.DiscoveryDataApiService;
+import org.wso2.carbon.identity.rest.api.user.push.v1.core.PushDeviceManagementService;
+import org.wso2.carbon.identity.rest.api.user.push.v1.model.DiscoveryDataDTO;
+
+import javax.ws.rs.core.Response;
+
+/**
+ * Implementation class of Push device Handler User APIs.
+ */
+public class DiscoveryDataApiServiceImpl implements DiscoveryDataApiService {
+
+ @Autowired
+ private PushDeviceManagementService pushDeviceManagementService;
+
+ @Override
+ public Response getRegistrationDiscoveryData() {
+
+ DiscoveryDataDTO responseDTO = pushDeviceManagementService.getRegistrationDiscoveryData();
+ return Response.ok().entity(responseDTO).build();
+ }
+}
diff --git a/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/main/java/org/wso2/carbon/identity/rest/api/user/push/v1/util/Util.java b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/main/java/org/wso2/carbon/identity/rest/api/user/push/v1/util/Util.java
new file mode 100644
index 00000000..872532bd
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/main/java/org/wso2/carbon/identity/rest/api/user/push/v1/util/Util.java
@@ -0,0 +1,45 @@
+package org.wso2.carbon.identity.rest.api.user.push.v1.util;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.identity.api.user.common.error.APIError;
+import org.wso2.carbon.identity.api.user.common.error.ErrorResponse;
+import org.wso2.carbon.identity.notification.push.device.handler.exception.PushDeviceHandlerClientException;
+import org.wso2.carbon.identity.notification.push.device.handler.exception.PushDeviceHandlerException;
+
+import javax.ws.rs.core.Response;
+
+/**
+ * Util class for push device management.
+ */
+public class Util {
+
+ private static final Log LOG = LogFactory.getLog(Util.class);
+
+ /**
+ * Handle push device handler exception.
+ *
+ * @param e PushDeviceHandlerException.
+ * @return APIError.
+ */
+ public static APIError handlePushDeviceHandlerException(PushDeviceHandlerException e) {
+
+ if (e instanceof PushDeviceHandlerClientException) {
+ ErrorResponse errorResponse = getErrorBuilder(e).build(LOG, e.getMessage());
+ return new APIError(Response.Status.BAD_REQUEST, errorResponse);
+ }
+ ErrorResponse errorResponse = getErrorBuilder(e).build(LOG, e, e.getMessage());
+ return new APIError(Response.Status.INTERNAL_SERVER_ERROR, errorResponse);
+ }
+
+ /**
+ * Get error builder.
+ *
+ * @param e PushDeviceHandlerException.
+ * @return ErrorResponse.Builder.
+ */
+ private static ErrorResponse.Builder getErrorBuilder(PushDeviceHandlerException e) {
+
+ return new ErrorResponse.Builder().withCode(e.getErrorCode()).withMessage(e.getMessage());
+ }
+}
diff --git a/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/main/resources/META-INF/cxf/push-device-management-v1-cxf.xml b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/main/resources/META-INF/cxf/push-device-management-v1-cxf.xml
new file mode 100644
index 00000000..8908e201
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/main/resources/META-INF/cxf/push-device-management-v1-cxf.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/main/resources/push.yaml b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/main/resources/push.yaml
new file mode 100644
index 00000000..6fa4a1cf
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/org.wso2.carbon.identity.rest.api.user.push.v1/src/main/resources/push.yaml
@@ -0,0 +1,338 @@
+openapi: 3.0.0
+info:
+ version: "v1"
+ title: 'WSO2 Identity Server - User Push Notification Device Management API Definition'
+ description: 'This is the RESTful API for managing devices used for the push notification feature by the user in WSO2 Identity Server.'
+ contact:
+ name: WSO2
+ url: 'http://wso2.com/products/identity-server/'
+ email: iam-dev@wso2.org
+ license:
+ name: Apache 2.0
+ url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
+servers:
+ - url: 'https://localhost:9443/t/{tenant-domain}/api/users/v1/me/push'
+ variables:
+ tenant-domain:
+ default: petstore
+
+tags:
+ - name: me
+ description: Operations for the authenticated user.
+ - name: mobile
+ description: Operations initiated through user's device.
+
+paths:
+ /discovery-data:
+ get:
+ tags:
+ - me
+ description: |
+ This API is used to generate discovery data for the device registration QR code.
+ summary: |
+ Generate data for device registration.
+ operationId: getRegistrationDiscoveryData
+ responses:
+ '200':
+ description: Successfully generated registration discovery data.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DiscoveryDataDTO'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+ '500':
+ $ref: '#/components/responses/ServerError'
+ '501':
+ $ref: '#/components/responses/NotImplemented'
+ /devices:
+ post:
+ tags:
+ - mobile
+ description: |
+ This API is used to register a push notification device into the Identity Server. This API will be invoked from the mobile device.
+ summary: Register mobile devices to receive push notifications.
+ operationId: registerDevice
+ requestBody:
+ description: Request body sent by a device for registration.
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/RegistrationRequestDTO'
+ responses:
+ '201':
+ description: Registered a new device
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/RegistrationResponseDTO'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+ '500':
+ $ref: '#/components/responses/ServerError'
+ '501':
+ $ref: '#/components/responses/NotImplemented'
+ /devices/{deviceId}:
+ get:
+ tags:
+ - me
+ description: |
+ This API is used to get a specific registered device
+ summary: Get mobile device details by device ID.
+ operationId: getDeviceById
+ parameters:
+ - name: deviceId
+ in: path
+ description: ID of the device to be returned
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: Successfully returned the device belongs to the ID
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DeviceDTO'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+ '500':
+ $ref: '#/components/responses/ServerError'
+ '501':
+ $ref: '#/components/responses/NotImplemented'
+ delete:
+ tags:
+ - me
+ description: |
+ This API is used to remove a registered device.
+ summary: Remove a registered device
+ operationId: deleteDeviceById
+ parameters:
+ - name: deviceId
+ in: path
+ description: ID of the device to be removed
+ required: true
+ schema:
+ type: string
+ responses:
+ '204':
+ description: The device was removed.
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+ '500':
+ $ref: '#/components/responses/ServerError'
+ '501':
+ $ref: '#/components/responses/NotImplemented'
+ /devices/{deviceId}/remove:
+ post:
+ tags:
+ - mobile
+ description: |
+ This API is used to remove a registered device through mobile device.
+ summary: Remove a registered device from the mobile device.
+ operationId: removeDeviceFromMobile
+ parameters:
+ - name: deviceId
+ in: path
+ description: ID of the device to be removed
+ required: true
+ schema:
+ type: string
+ requestBody:
+ description: Remove request sent from the device.
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/RemoveRequestDTO'
+ responses:
+ '204':
+ description: The device was removed.
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+ '500':
+ $ref: '#/components/responses/ServerError'
+ '501':
+ $ref: '#/components/responses/NotImplemented'
+
+
+components:
+ schemas:
+ DiscoveryDataDTO:
+ type: object
+ description: Device registration information
+ properties:
+ did:
+ description: Device ID
+ type: string
+ example: b03f90c9-6723-48f6-863b-a35f1ac77f57
+ un:
+ description: Username
+ type: string
+ example: admin
+ td:
+ description: Tenant domain or Organization
+ type: string
+ example: carbon.super
+ ae:
+ description: Authentication endpoint
+ type: string
+ format: url
+ example: https://localhost:9443/push-auth/authenticate
+ re:
+ description: Registration endpoint
+ type: string
+ format: url
+ example: https://localhost:9443/api/users/v1/me/push/devices
+ rde:
+ description: Remove device endpoint
+ type: string
+ format: url
+ example: https://localhost:9443/api/users/v1/me/push/devices/deviceId/remove
+ chg:
+ description: Challenge
+ type: string
+ example: b03f90c9-6723-48f6-863b-a35f1ac77f57
+
+ RegistrationRequestDTO:
+ type: object
+ description: The registration request body sent from the mobile device
+ properties:
+ deviceId:
+ type: string
+ description: Unique UUID for the device
+ example: b03f90c9-6723-48f6-863b-a35f1ac77f57
+ model:
+ type: string
+ description: Model of the device
+ example: iPhone 16
+ name:
+ type: string
+ description: Name of the device
+ example: My Device
+ deviceToken:
+ type: string
+ description: device token unique to the device
+ example: 'fuRr8s_eQrmB88nu5Tz8oa:APA91bFMqYbuzDYyOGK28VoiLHWYXZYzGNVg3tfxfNwKPH-jDIFpNDdUHkmq5wqBUySYZnuHfpycyQvUrPhwV3UZ1YzjUNLvb9gzFZudfJd1N3fWuU0w2nq_hVJc0UPRabvNPuJy8wMB'
+ publicKey:
+ type: string
+ description: Public key of the keypair generated by the device for the account
+ example: 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOhCpj5pAEqdCdyxuHii0oLFAgnTePMI1EeomZHCRaZZNGv8fdcHyme9rpknNx/caAz9Gck5HrB/vto86cHpBkAghsBBLLWPUlblWNZCBX4pqFhZu+uZKvOnSqp1SwP13yx72nLKbjHRRJGgwCrg/mbdSGN/QKxRU+UhdKVVpQIDAQAB'
+ signature:
+ type: string
+ description: Signature string comprising of the pushId and the challenge
+ example: 'rT/VxgPYMioT6wHajYg0mJpBv46HvFBm/elZ/VL4ClUIFfX7i3Ou5ER5sEiFtehaurLXPNsA8hF4SQAueVBRymEAmchhwYlT160g3wv6kDQvWLkTqnLWGfn++wg5xRManOoN9zG9GhxCgRr9y+lk9rtvydfX0lTcdEZBkynSJnM='
+
+ RegistrationResponseDTO:
+ type: object
+ description: The registration response sent after successful device registration.
+ properties:
+ deviceId:
+ type: string
+ description: Unique UUID for the device.
+ example: b03f90c9-6723-48f6-863b-a35f1ac77f57
+
+ DeviceDTO:
+ type: object
+ description: Model for the registered device object
+ properties:
+ deviceId:
+ type: string
+ example: b03f90c9-6723-48f6-863b-a35f1ac77f57
+ name:
+ type: string
+ example: My Phone
+ model:
+ type: string
+ example: iPhone 16
+ provider:
+ type: string
+ example: fcm
+
+ RemoveRequestDTO:
+ type: object
+ description: Remove device request body sent from the mobile device
+ required:
+ - token
+ properties:
+ token:
+ type: string
+ description: JWT containing the remove device information signed with a unique private key
+ example: 'signedDeviceToken'
+
+ Error:
+ type: object
+ required:
+ - code
+ - message
+ properties:
+ code:
+ type: string
+ example: UOM-00000
+ description: An error code.
+ message:
+ type: string
+ example: Some Error Message
+ description: An error message.
+ description:
+ type: string
+ example: Some Error Description
+ description: An error description.
+ traceId:
+ type: string
+ example: e0fbcfeb-3617-43c4-8dd0-7b7d38e13047
+ description: An error trace identifier.
+
+ #--------------------------------------------------------
+ # Descriptions of error responses.
+ #--------------------------------------------------------
+ responses:
+ BadRequest:
+ description: Invalid input in the request.
+ content:
+ 'application/json':
+ schema:
+ $ref: '#/components/schemas/Error'
+ NotFound:
+ description: Resource is not found.
+ content:
+ 'application/json':
+ schema:
+ $ref: '#/components/schemas/Error'
+ Unauthorized:
+ description: Authentication information is missing or invalid.
+ Forbidden:
+ description: Access forbidden.
+ ServerError:
+ description: Internal server error.
+ content:
+ 'application/json':
+ schema:
+ $ref: '#/components/schemas/Error'
+ NotImplemented:
+ description: Not Implemented.
+ content:
+ 'application/json':
+ schema:
+ $ref: '#/components/schemas/Error'
diff --git a/components/org.wso2.carbon.identity.api.user.push/pom.xml b/components/org.wso2.carbon.identity.api.user.push/pom.xml
new file mode 100644
index 00000000..bb32a1ba
--- /dev/null
+++ b/components/org.wso2.carbon.identity.api.user.push/pom.xml
@@ -0,0 +1,27 @@
+
+
+ 4.0.0
+
+ org.wso2.carbon.identity.user.api
+ identity-api-user
+ 1.3.39
+ ../../pom.xml
+
+
+ org.wso2.carbon.identity.api.user.push
+ pom
+
+
+ org.wso2.carbon.identity.rest.api.user.push.v1
+ org.wso2.carbon.identity.api.user.push.common
+
+
+
+ 17
+ 17
+ UTF-8
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 4f97899c..93e377e3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -198,6 +198,12 @@
${identity.org.mgt.core.version}
provided
+
+ org.wso2.carbon.identity.notification.push
+ org.wso2.carbon.identity.notification.push.device.handler
+ ${identity.notification.push.version}
+ provided
+
org.wso2.carbon.extension.identity.authenticator.outbound.totp
@@ -233,6 +239,12 @@
provided
${project.version}
+
+ org.wso2.carbon.identity.user.api
+ org.wso2.carbon.identity.api.user.push.common
+ provided
+ ${project.version}
+
org.wso2.carbon.identity.user.api
org.wso2.carbon.identity.api.user.functionality.common
@@ -486,6 +498,8 @@
1.12.0
7.0.169
1.1.17
+ 1.0.0-SNAPSHOT
+ [1.0.0, 2.0.0)
6.9.10
5.4.7
3.3.1
@@ -514,6 +528,7 @@
components/org.wso2.carbon.identity.api.user.idv
components/org.wso2.carbon.identity.api.user.organization
components/org.wso2.carbon.identity.api.user.onboard
+ components/org.wso2.carbon.identity.api.user.push