diff --git a/library/src/androidTest/java/com/nextcloud/android/lib/resources/users/GenerateOneTimeAppPasswordRemoteOperationIT.java b/library/src/androidTest/java/com/nextcloud/android/lib/resources/users/GenerateOneTimeAppPasswordRemoteOperationIT.java new file mode 100644 index 0000000000..2edec338e8 --- /dev/null +++ b/library/src/androidTest/java/com/nextcloud/android/lib/resources/users/GenerateOneTimeAppPasswordRemoteOperationIT.java @@ -0,0 +1,40 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2020-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2020 Tobias Kaminsky + * SPDX-License-Identifier: MIT + */ +package com.nextcloud.android.lib.resources.users; + +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; + +import android.text.TextUtils; + +import com.owncloud.android.AbstractIT; +import com.owncloud.android.lib.common.operations.RemoteOperationResult; + +import org.junit.Test; + +public class GenerateOneTimeAppPasswordRemoteOperationIT extends AbstractIT { + + @Test + public void generateAppPassword() { + // nc://onetime-login/user:user1&password:Z8i8J-QLDbr-mSn9A-ijXzN-NSBSt&server:https://qr.ltd3.nextcloud.com + + // nextcloudClient.setBaseUri(Uri.parse("https://qr.ltd3.nextcloud.com")); + // nextcloudClient.setCredentials(Credentials.basic("user1", "user1")); + + GenerateOneTimeAppPasswordRemoteOperation sut = new GenerateOneTimeAppPasswordRemoteOperation(); + RemoteOperationResult result = sut.execute(nextcloudClient); + + assertTrue(result.isSuccess()); + + String appPassword = result.getResultData(); + assertFalse(TextUtils.isEmpty(appPassword)); + + // re-using onetime password should fail + assertFalse(new GenerateOneTimeAppPasswordRemoteOperation().execute(nextcloudClient).isSuccess()); + } +} diff --git a/library/src/main/java/com/nextcloud/android/lib/resources/users/GenerateOneTimeAppPasswordRemoteOperation.java b/library/src/main/java/com/nextcloud/android/lib/resources/users/GenerateOneTimeAppPasswordRemoteOperation.java new file mode 100644 index 0000000000..56620d56bc --- /dev/null +++ b/library/src/main/java/com/nextcloud/android/lib/resources/users/GenerateOneTimeAppPasswordRemoteOperation.java @@ -0,0 +1,66 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2025 Tobias Kaminsky + * SPDX-License-Identifier: MIT + */ +package com.nextcloud.android.lib.resources.users; + + +import com.nextcloud.common.NextcloudClient; +import com.nextcloud.operations.GetMethod; +import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import com.owncloud.android.lib.common.utils.Log_OC; +import com.owncloud.android.lib.resources.OCSRemoteOperation; + +import org.apache.commons.httpclient.HttpStatus; +import org.json.JSONObject; + +/** + * Generate an app password via username / login and **onetime** password. Available since Nextcloud 33 + */ + + +public class GenerateOneTimeAppPasswordRemoteOperation extends OCSRemoteOperation { + private static final String TAG = GenerateOneTimeAppPasswordRemoteOperation.class.getSimpleName(); + private static final String DIRECT_ENDPOINT = "/ocs/v2.php/core/getapppassword-onetime"; + + // JSON node names + private static final String NODE_OCS = "ocs"; + private static final String NODE_DATA = "data"; + private static final String NODE_APPPASSWORD = "apppassword"; + + public RemoteOperationResult run(NextcloudClient client) { + RemoteOperationResult result; + GetMethod getMethod = null; + + try { + getMethod = new GetMethod(client.getBaseUri() + DIRECT_ENDPOINT + JSON_FORMAT, true); + + // remote request + int status = client.execute(getMethod); + + if (status == HttpStatus.SC_OK) { + String response = getMethod.getResponseBodyAsString(); + + JSONObject respJSON = new JSONObject(response); + String password = respJSON.getJSONObject(NODE_OCS).getJSONObject(NODE_DATA).getString(NODE_APPPASSWORD); + + result = new RemoteOperationResult<>(true, getMethod); + result.setResultData(password); + } else { + result = new RemoteOperationResult<>(false, getMethod); + } + } catch (Exception e) { + result = new RemoteOperationResult<>(e); + Log_OC.e(TAG, "Generate app password failed: " + result.getLogMessage(), + result.getException()); + } finally { + if (getMethod != null) { + getMethod.releaseConnection(); + } + } + return result; + } +}