Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Your Name <your@email.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.owncloud.android.lib.resources.notifications

import com.nextcloud.common.JSONRequestBody
import com.nextcloud.common.NextcloudClient
import com.nextcloud.operations.PostMethod
import com.owncloud.android.lib.common.operations.RemoteOperation
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.common.utils.Log_OC
import org.apache.commons.httpclient.util.HttpURLConnection

class ActivateWebPushRegistrationOperation(
val activationToken: String
): RemoteOperation<Void>() {

override fun run(client: NextcloudClient): RemoteOperationResult<Void> {
var result: RemoteOperationResult<Void>
var post: PostMethod? = null
try {
val body = JSONRequestBody(ACTIVATION_TOKEN, activationToken)
post = PostMethod("${client.baseUri}$OCS_ROUTE", true, body.get())

val status = client.execute(post)
val response = post.getResponseBodyAsString()
when (status) {
HttpURLConnection.HTTP_ACCEPTED -> {
Log_OC.d(TAG, "Web push registration activated (status=202)")
result = RemoteOperationResult(true, post)
}
HttpURLConnection.HTTP_OK -> {
Log_OC.d(TAG, "Web push registration already activated (status=200)")
result = RemoteOperationResult(true, post)
}
else -> {
Log_OC.d(TAG, "Cannot activate web push registration (status=$status): $response")
result = RemoteOperationResult(false, post)
}
}
} catch (e: Exception) {
result = RemoteOperationResult(e)
Log_OC.e(TAG, "Exception while activating web push registration", e)
} finally {
post?.releaseConnection()
}
return result
}

companion object {
// OCS Route
private const val OCS_ROUTE = "/ocs/v2.php/apps/notifications/api/v2/webpush/activate"
private const val ACTIVATION_TOKEN = "activationToken"

private val TAG = ActivateWebPushRegistrationOperation::class.java.getSimpleName()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Your Name <your@email.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.owncloud.android.lib.resources.notifications

import com.nextcloud.common.NextcloudClient
import com.nextcloud.operations.GetMethod
import com.owncloud.android.lib.common.operations.RemoteOperation
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.lib.resources.notifications.models.VapidResponse
import org.json.JSONObject

class GetVAPIDOperation(): RemoteOperation<VapidResponse>() {

override fun run(client: NextcloudClient): RemoteOperationResult<VapidResponse> {
var result: RemoteOperationResult<VapidResponse>
var get: GetMethod? = null
try {
get = GetMethod("${client.baseUri}$OCS_ROUTE", true)

val status = client.execute(get)
val response = get.getResponseBodyAsString()

if (get.isSuccess()) {
result = RemoteOperationResult(true, get)
val vapid = JSONObject(response)
.getJSONObject(OCS)
.getJSONObject(DATA)
.getString(VAPID)
result.resultData = VapidResponse(vapid)
Log_OC.d(TAG, "VAPID key found: $vapid")
} else {
Log_OC.e(TAG, "Failed getting VAPID key (status=$status): $response")
result = RemoteOperationResult(false, get)
}
} catch (e: Exception) {
result = RemoteOperationResult(e)
Log_OC.e(TAG, "Exception while getting VAPID key", e)
} finally {
get?.releaseConnection()
}
return result
}

companion object {
// OCS Route
private const val OCS_ROUTE = "/ocs/v2.php/apps/notifications/api/v2/webpush/vapid$JSON_FORMAT"
private const val OCS = "ocs"
private const val DATA = "data"
private const val VAPID = "vapid"

private val TAG = GetVAPIDOperation::class.java.getSimpleName()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Your Name <your@email.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.owncloud.android.lib.resources.notifications

import com.nextcloud.common.JSONRequestBody
import com.nextcloud.common.NextcloudClient
import com.nextcloud.operations.PostMethod
import com.owncloud.android.lib.common.operations.RemoteOperation
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.common.utils.Log_OC
import org.apache.commons.httpclient.util.HttpURLConnection

class RegisterAccountDeviceForWebPushOperation(
val endpoint: String,
val auth: String,
val uaPublicKey: String,
val appTypes: List<String>
): RemoteOperation<Void>() {

override fun run(client: NextcloudClient): RemoteOperationResult<Void> {
var result: RemoteOperationResult<Void>
var post: PostMethod? = null
try {
val body = JSONRequestBody(ENDPOINT, endpoint)
body.put(AUTH, auth)
body.put(UA_PUBLIC_KEY, uaPublicKey)
body.put(APPTYPES, appTypes.joinToString(","))
post = PostMethod("${client.baseUri}$OCS_ROUTE", true, body.get())

val status = client.execute(post)
val response = post.getResponseBodyAsString()
when (status) {
HttpURLConnection.HTTP_CREATED -> {
Log_OC.d(TAG, "New web push registration created (status=201)")
result = RemoteOperationResult(true, post)
}
HttpURLConnection.HTTP_OK -> {
Log_OC.d(TAG, "Web push registration already activated (status=200)")
result = RemoteOperationResult(true, post)
}
else -> {
Log_OC.e(TAG, "Web push registration refused (status=$status): $response")
result = RemoteOperationResult(false, post)
}
}
} catch (e: Exception) {
result = RemoteOperationResult(e)
Log_OC.e(TAG, "Exception while registering web push", e)
} finally {
post?.releaseConnection()
}
return result
}

companion object {
// OCS Route
private const val OCS_ROUTE = "/ocs/v2.php/apps/notifications/api/v2/webpush"
private const val ENDPOINT = "endpoint"
private const val AUTH = "auth"
private const val UA_PUBLIC_KEY = "uaPublicKey"
private const val APPTYPES = "appTypes"

private val TAG = RegisterAccountDeviceForWebPushOperation::class.java.getSimpleName()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Your Name <your@email.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.owncloud.android.lib.resources.notifications

import com.nextcloud.common.NextcloudClient
import com.nextcloud.operations.DeleteMethod
import com.owncloud.android.lib.common.operations.RemoteOperation
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.common.utils.Log_OC
import org.apache.commons.httpclient.util.HttpURLConnection

class UnregisterAccountDeviceForWebPushOperation(): RemoteOperation<Void>() {

override fun run(client: NextcloudClient): RemoteOperationResult<Void> {
var result: RemoteOperationResult<Void>
var delete: DeleteMethod? = null
try {
delete = DeleteMethod("${client.baseUri}$OCS_ROUTE", true)

val status = client.execute(delete)
val response = delete.getResponseBodyAsString()
when (status) {
HttpURLConnection.HTTP_ACCEPTED -> {
Log_OC.d(TAG, "Web push registration deleted (status=202)")
result = RemoteOperationResult(true, delete)
}
HttpURLConnection.HTTP_OK -> {
Log_OC.d(TAG, "Web push registration already deleted (status=200)")
result = RemoteOperationResult(true, delete)
}
else -> {
Log_OC.e(TAG, "Web push registration refused (status=$status): $response")
result = RemoteOperationResult(false, delete)
}
}
} catch (e: Exception) {
result = RemoteOperationResult(e)
Log_OC.e(TAG, "Exception while registering web push", e)
} finally {
delete?.releaseConnection()
}
return result
}

companion object {
// OCS Route
private const val OCS_ROUTE = "/ocs/v2.php/apps/notifications/api/v2/webpush"

private val TAG = UnregisterAccountDeviceForWebPushOperation::class.java.getSimpleName()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Your Name <your@email.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.owncloud.android.lib.resources.notifications.models

data class VapidResponse(val vapid: String)
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ public class GetCapabilitiesRemoteOperation extends RemoteOperation {
// v1 notifications
private static final String NODE_NOTIFICATIONS = "notifications";
private static final String PROPERTY_OCSENDPOINT = "ocs-endpoints";
private static final String PROPERTY_PUSH = "push";
private static final String PROPERTY_WEBPUSH = "webpush";

// v2 notifications
private static final String PROPERTY_ICONS = "icons";
Expand Down Expand Up @@ -549,6 +551,7 @@ private OCCapability parseResponse(String response) throws JSONException {
JSONObject respNotifications = respCapabilities.getJSONObject(NODE_NOTIFICATIONS);
JSONArray respNotificationSupportArray = respNotifications.getJSONArray(
PROPERTY_OCSENDPOINT);
JSONArray respNotificationPushArray = respNotifications.getJSONArray(PROPERTY_PUSH);
for (int i = 0; i < respNotificationSupportArray.length(); i++) {
String propertyString = respNotificationSupportArray.getString(i);
if (PROPERTY_RICH_STRINGS.equals(propertyString)
Expand All @@ -557,6 +560,13 @@ private OCCapability parseResponse(String response) throws JSONException {
break;
}
}
for (int i = 0; i < respNotificationPushArray.length(); i++) {
String propertyString = respNotificationPushArray.getString(i);
if (PROPERTY_WEBPUSH.equals(propertyString)) {
capability.setSupportsWebPush(CapabilityBooleanType.TRUE);
break;
}
}
if (capability.getSupportsNotificationsV2() != CapabilityBooleanType.TRUE) {
capability.setSupportsNotificationsV1(CapabilityBooleanType.TRUE);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class OCCapability {

var supportsNotificationsV1 = CapabilityBooleanType.UNKNOWN
var supportsNotificationsV2 = CapabilityBooleanType.UNKNOWN
var supportsWebPush = CapabilityBooleanType.UNKNOWN

var externalLinks = CapabilityBooleanType.UNKNOWN

Expand Down
Loading