Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

App Config With Restriction Manager #12884

Merged
merged 22 commits into from May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
8a48da3
Use restriction manager for app config
alperozturk96 Apr 15, 2024
7b46e6d
Use androidx.enterprise:enterprise-feedback for give feedback to cust…
alperozturk96 Apr 15, 2024
22e9a40
Simplify AppConfigManager
alperozturk96 Apr 15, 2024
ac1c41b
Simplify AppConfigManager
alperozturk96 Apr 15, 2024
cab8405
Revert lenient option
alperozturk96 Apr 16, 2024
b727fc3
Add base url config, is_branded_plus, remove enterprise reporter
alperozturk96 Apr 18, 2024
d429a76
Add AppConfigManagerTests
alperozturk96 Apr 18, 2024
325dc86
Only branded plus client can use app config
alperozturk96 Apr 18, 2024
2d8840b
Add is client branded functions
alperozturk96 Apr 18, 2024
05ec75b
Add is_branded_plus condition for is_branded if statements
alperozturk96 Apr 18, 2024
b7defed
Revert isBrandedClient checks
alperozturk96 Apr 22, 2024
ad3ec21
Revert filterAssistantMenuItem usage
alperozturk96 Apr 22, 2024
cf61ce2
Fix code analytics
alperozturk96 Apr 22, 2024
9a0f69e
Add base url to app_config.xml
alperozturk96 Apr 22, 2024
d54c86e
Revert drawer activity header
alperozturk96 Apr 22, 2024
ba4a61c
abort setting proxy when either host or port is not valid
tobiasKaminsky Apr 29, 2024
b55962e
init RestrictionsManager only for branded plus clients
alperozturk96 May 3, 2024
c9b277e
Listen app config changes only for branded plus clients
alperozturk96 May 3, 2024
8ed89d7
Fix tests
alperozturk96 May 6, 2024
ce0bb85
Dont set default proxy settings
alperozturk96 May 6, 2024
51709a0
Fix code analytics
alperozturk96 May 6, 2024
1565b32
reset proxy
tobiasKaminsky May 10, 2024
File filter

Filter by extension

Filter by extension

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

package com.nextcloud.utils

import android.os.Bundle
import com.owncloud.android.AbstractIT
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory
import com.owncloud.android.utils.appConfig.AppConfigKeys
import com.owncloud.android.utils.appConfig.AppConfigManager
import org.junit.AfterClass
import org.junit.Test

class AppConfigManagerTests : AbstractIT() {

private val testBaseUrl = "nextcloud.cloud.cloud"
private val testProxyHost = "nextcloud.cloud.cloud.com"

@Suppress("MagicNumber")
private val testProxyPort = 8800

@Test
fun testSetProxyConfigWhenGivenClientBrandedPlusAndCorrectBundleDataProxyConfigurationShouldSet() {
val proxySetting = Bundle().apply {
putString(AppConfigKeys.ProxyHost.key, testProxyHost)
putInt(AppConfigKeys.ProxyPort.key, testProxyPort)
}

AppConfigManager(targetContext, proxySetting).run {
setProxyConfig(true)
}

val proxyHost = OwnCloudClientManagerFactory.getProxyHost()
val proxyPort = OwnCloudClientManagerFactory.getProxyPort()

assert(proxyHost.equals(testProxyHost))
assert(proxyPort == testProxyPort)
}

@Test
fun testSetProxyConfigWhenGivenClientNotBrandedPlusAndCorrectBundleDataProxyConfigurationShouldNotSet() {
val proxySetting = Bundle().apply {
putString(AppConfigKeys.ProxyHost.key, testProxyHost)
putInt(AppConfigKeys.ProxyPort.key, testProxyPort)
}

AppConfigManager(targetContext, proxySetting).run {
setProxyConfig(false)
}

val proxyHost = OwnCloudClientManagerFactory.getProxyHost()
val proxyPort = OwnCloudClientManagerFactory.getProxyPort()

assert(proxyHost.equals(""))
assert(proxyPort == -1)
}

@Test
fun testGetBaseUrlConfigWhenGivenClientBrandedPlusAndCorrectBundleDataBaseUrlConfigurationShouldSet() {
val baseUrlConfig = Bundle().apply {
putString(AppConfigKeys.BaseUrl.key, testBaseUrl)
}
val sut = AppConfigManager(targetContext, baseUrlConfig)
assert(!sut.getBaseUrl(true).isNullOrEmpty())
}

@Test
fun testGetBaseUrlConfigWhenGivenClientBrandedPlusAndBrokenBundleDataBaseUrlConfigurationShouldNotSet() {
val baseUrlConfig = Bundle()
val sut = AppConfigManager(targetContext, baseUrlConfig)
assert(sut.getBaseUrl(true).isNullOrEmpty())
}

companion object {
@JvmStatic
@AfterClass
fun tearDown() {
OwnCloudClientManagerFactory.setProxyHost("")
OwnCloudClientManagerFactory.setProxyPort(-1)
}
}
}
4 changes: 4 additions & 0 deletions app/src/main/AndroidManifest.xml
Expand Up @@ -126,6 +126,10 @@
android:usesCleartextTraffic="true"
tools:ignore="UnusedAttribute"
tools:replace="android:allowBackup">

<meta-data android:name="android.content.APP_RESTRICTIONS"
android:resource="@xml/app_config" />

<activity
android:name="com.nextcloud.ui.composeActivity.ComposeActivity"
android:exported="false" />
Expand Down
49 changes: 44 additions & 5 deletions app/src/main/java/com/owncloud/android/MainApp.java
Expand Up @@ -21,9 +21,12 @@
import android.app.Application;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.RestrictionsManager;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
Expand Down Expand Up @@ -55,6 +58,7 @@
import com.nextcloud.client.preferences.AppPreferences;
import com.nextcloud.client.preferences.AppPreferencesImpl;
import com.nextcloud.client.preferences.DarkMode;
import com.nextcloud.utils.extensions.ContextExtensionsKt;
import com.nmc.android.ui.LauncherActivity;
import com.owncloud.android.authentication.AuthenticatorActivity;
import com.owncloud.android.authentication.PassCodeManager;
Expand All @@ -63,6 +67,7 @@
import com.owncloud.android.datamodel.MediaFolder;
import com.owncloud.android.datamodel.MediaFolderType;
import com.owncloud.android.datamodel.MediaProvider;
import com.owncloud.android.datamodel.ReceiverFlag;
import com.owncloud.android.datamodel.SyncedFolder;
import com.owncloud.android.datamodel.SyncedFolderProvider;
import com.owncloud.android.datamodel.ThumbnailsCacheManager;
Expand All @@ -75,6 +80,7 @@
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
import com.owncloud.android.ui.activity.SyncedFoldersActivity;
import com.owncloud.android.ui.notifications.NotificationUtils;
import com.owncloud.android.utils.appConfig.AppConfigManager;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.FilesSyncHelper;
import com.owncloud.android.utils.PermissionUtil;
Expand Down Expand Up @@ -191,6 +197,8 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector {
@SuppressWarnings("unused")
private boolean mBound;

private AppConfigManager appConfigManager;

private static AppComponent appComponent;

/**
Expand Down Expand Up @@ -281,6 +289,7 @@ public static AppComponent getAppComponent() {
return appComponent;
}


@SuppressFBWarnings("ST")
@Override
public void onCreate() {
Expand Down Expand Up @@ -314,11 +323,15 @@ public void onCreate() {

OwnCloudClientManagerFactory.setUserAgent(getUserAgent());

try {
OwnCloudClientManagerFactory.setProxyHost(getResources().getString(R.string.proxy_host));
OwnCloudClientManagerFactory.setProxyPort(getResources().getInteger(R.integer.proxy_port));
} catch (Resources.NotFoundException e) {
// no proxy set
if (isClientBrandedPlus()) {
RestrictionsManager restrictionsManager = (RestrictionsManager) getSystemService(Context.RESTRICTIONS_SERVICE);
appConfigManager = new AppConfigManager(this, restrictionsManager.getApplicationRestrictions());
appConfigManager.setProxyConfig(isClientBrandedPlus());

// Listen app config changes
ContextExtensionsKt.registerBroadcastReceiver(this, restrictionsReceiver, restrictionsFilter, ReceiverFlag.NotExported);
} else {
setProxyForNonBrandedPlusClients();
}

// initialise thumbnails cache on background thread
Expand Down Expand Up @@ -364,9 +377,35 @@ public void onCreate() {
} else if (event == Lifecycle.Event.ON_STOP) {
passCodeManager.setCanAskPin(true);
Log_OC.d(TAG, "APP IN BACKGROUND");
} else if (event == Lifecycle.Event.ON_RESUME) {
if (appConfigManager == null) return;
appConfigManager.setProxyConfig(isClientBrandedPlus());
Log_OC.d(TAG, "APP ON RESUME");
}
});

private void setProxyForNonBrandedPlusClients() {
try {
OwnCloudClientManagerFactory.setProxyHost(getResources().getString(R.string.proxy_host));
OwnCloudClientManagerFactory.setProxyPort(getResources().getInteger(R.integer.proxy_port));
} catch (Resources.NotFoundException e) {
Log_OC.d(TAG, "Error caught at setProxyForNonBrandedPlusClients: " + e);
}
}

public static boolean isClientBrandedPlus() {
return (getAppContext().getResources().getBoolean(R.bool.is_branded_plus_client));
}

private final IntentFilter restrictionsFilter = new IntentFilter(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED);

private final BroadcastReceiver restrictionsReceiver = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
if (appConfigManager == null) return;
appConfigManager.setProxyConfig(isClientBrandedPlus());
}
};

private void registerGlobalPassCodeProtection() {
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {

Expand Down
Expand Up @@ -21,6 +21,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.RestrictionsManager;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
Expand Down Expand Up @@ -83,6 +84,7 @@
import com.owncloud.android.lib.common.OwnCloudCredentials;
import com.owncloud.android.lib.common.OwnCloudCredentialsFactory;
import com.owncloud.android.lib.common.UserInfo;
import com.owncloud.android.lib.common.accounts.AccountUtils;
import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
import com.owncloud.android.lib.common.accounts.AccountUtils.Constants;
import com.owncloud.android.lib.common.network.CertificateCombinedException;
Expand Down Expand Up @@ -111,6 +113,7 @@
import com.owncloud.android.utils.ErrorMessageAdapter;
import com.owncloud.android.utils.PermissionUtil;
import com.owncloud.android.utils.WebViewUtil;
import com.owncloud.android.utils.appConfig.AppConfigManager;
import com.owncloud.android.utils.theme.CapabilityUtils;
import com.owncloud.android.utils.theme.ViewThemeUtils;

Expand Down Expand Up @@ -318,9 +321,18 @@ protected void onCreate(Bundle savedInstanceState) {
mIsFirstAuthAttempt = savedInstanceState.getBoolean(KEY_AUTH_IS_FIRST_ATTEMPT_TAG);
}

String webloginUrl = null;
boolean webViewLoginMethod;
if (getIntent().getBooleanExtra(EXTRA_USE_PROVIDER_AS_WEBLOGIN, false)) {
String webloginUrl = null;

alperozturk96 marked this conversation as resolved.
Show resolved Hide resolved
if (MainApp.isClientBrandedPlus()) {
RestrictionsManager restrictionsManager = (RestrictionsManager) getSystemService(Context.RESTRICTIONS_SERVICE);
AppConfigManager appConfigManager = new AppConfigManager(this, restrictionsManager.getApplicationRestrictions());
webloginUrl = appConfigManager.getBaseUrl(MainApp.isClientBrandedPlus());
}

if (webloginUrl != null) {
webViewLoginMethod = true;
} else if (getIntent().getBooleanExtra(EXTRA_USE_PROVIDER_AS_WEBLOGIN, false)) {
webViewLoginMethod = true;
webloginUrl = getString(R.string.provider_registration_server);
} else {
Expand Down Expand Up @@ -1375,7 +1387,7 @@ protected boolean createAccount(RemoteOperationResult<UserInfo> authResult) {
// can be anything: email, name, name with whitespaces
String loginName = webViewUser;

String accountName = com.owncloud.android.lib.common.accounts.AccountUtils.buildAccountName(uri, loginName);
String accountName = AccountUtils.buildAccountName(uri, loginName);
Account newAccount = new Account(accountName, accountType);
if (accountManager.exists(newAccount)) {
// fail - not a new account, but an existing one; disallow
Expand Down Expand Up @@ -1480,7 +1492,7 @@ private void startQRScanner() {
public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == PermissionUtil.PERMISSIONS_CAMERA) {// If request is cancelled, result arrays are empty.
if (requestCode == PERMISSIONS_CAMERA) {// If request is cancelled, result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted
startQRScanner();
Expand Down
Expand Up @@ -46,6 +46,7 @@
import com.nextcloud.common.NextcloudClient;
import com.nextcloud.ui.fileactions.FileActionsBottomSheet;
import com.nextcloud.utils.extensions.BundleExtensionsKt;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.databinding.FragmentPreviewMediaBinding;
import com.owncloud.android.datamodel.OCFile;
Expand Down
Expand Up @@ -11,6 +11,7 @@
import android.view.Menu;

import com.nextcloud.client.account.User;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.lib.resources.status.OCCapability;

Expand Down
@@ -0,0 +1,17 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2024 Your Name <your@email.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.owncloud.android.utils.appConfig

/**
* These keys are connected to app_config.xml
*/
enum class AppConfigKeys(val key: String) {
BaseUrl("base_url"),
ProxyHost("proxy_host"),
ProxyPort("proxy_port")
}
@@ -0,0 +1,68 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2024 Your Name <your@email.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.owncloud.android.utils.appConfig

import android.content.Context
import android.content.res.Resources
import android.os.Bundle
import android.text.TextUtils
import com.owncloud.android.R
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory
import com.owncloud.android.lib.common.utils.Log_OC

class AppConfigManager(private val context: Context, private val appRestrictions: Bundle) {

private val tag = "AppConfigManager"

fun setProxyConfig(isBrandedPlus: Boolean) {
if (!isBrandedPlus) {
Log_OC.d(tag, "Proxy configuration cannot be set. Client is not branded plus.")
return
}

val host = if (appRestrictions.containsKey(AppConfigKeys.ProxyHost.key)) {
appRestrictions.getString(AppConfigKeys.ProxyHost.key)
} else {
context.getString(R.string.proxy_host)
}

val port = if (appRestrictions.containsKey(AppConfigKeys.ProxyPort.key)) {
appRestrictions.getInt(AppConfigKeys.ProxyPort.key)
} else {
context.resources.getInteger(R.integer.proxy_port)
}

if (TextUtils.isEmpty(host) || port == -1) {
Log_OC.d(tag, "Proxy configuration cannot be found")
return
}

try {
OwnCloudClientManagerFactory.setProxyHost(host)
alperozturk96 marked this conversation as resolved.
Show resolved Hide resolved
OwnCloudClientManagerFactory.setProxyPort(port)

Log_OC.d(tag, "Proxy configuration successfully set")
} catch (e: Resources.NotFoundException) {
Log_OC.e(tag, "Proxy config cannot able to set due to: $e")
}
}

fun getBaseUrl(isBrandedPlus: Boolean): String? {
if (!isBrandedPlus) {
Log_OC.d(tag, "Proxy configuration cannot be set. Client is not branded plus. Default url applied")
return null
}

return if (appRestrictions.containsKey(AppConfigKeys.BaseUrl.key)) {
appRestrictions.getString(AppConfigKeys.BaseUrl.key)
} else {
Log_OC.d(tag, "BaseUrl configuration cannot be found, default url applied")
null
}
}
}
1 change: 1 addition & 0 deletions app/src/main/res/values/setup.xml
Expand Up @@ -43,6 +43,7 @@
<bool name="show_external_links">true</bool>
<bool name="show_outdated_server_warning">true</bool>
<bool name="is_branded_client">false</bool>
<bool name="is_branded_plus_client">false</bool>

<!-- Calendar & Contacts backup -->
<string name="contacts_backup_folder">/.Contacts-Backup</string>
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/res/values/strings.xml
Expand Up @@ -26,6 +26,10 @@

<string name="ecosystem_apps_display_assistant">Assistant</string>

<string name="app_config_base_url_title">Base Url</string>
<string name="app_config_proxy_host_title">Proxy Host Name</string>
<string name="app_config_proxy_port_title">Proxy Port</string>

<string name="assistant_screen_task_types_error_state_message">Unable to fetch task types, please check your internet connection.</string>
<string name="assistant_screen_task_list_error_state_message">Unable to fetch task list, please check your internet connection.</string>

Expand Down