diff options
author | Stefan Niedermann <info@niedermann.it> | 2020-06-20 13:55:36 +0300 |
---|---|---|
committer | Stefan Niedermann <info@niedermann.it> | 2020-06-20 13:55:36 +0300 |
commit | 7ca8fe14a3d63c0ab0f733a79ba1a3c87a47dd59 (patch) | |
tree | 03bbaf67ba097d27fa55c2238e2f42d2b526e4a3 | |
parent | a914ff3a32f2c5e81178fc60bd29b4c04053609b (diff) |
Move SSO Glide integration into own module
15 files changed, 204 insertions, 67 deletions
diff --git a/app/build.gradle b/app/build.gradle index 663a61d8a..835a8b4d2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -62,6 +62,7 @@ dependencies { // Glide implementation 'com.github.bumptech.glide:glide:4.11.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0' + implementation project(path: ':glide-sso-integration') // Markdown implementation 'com.yydcdut:markdown-processor:0.1.3' diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherViewHolder.java index 86c857576..9de4185b1 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherViewHolder.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherViewHolder.java @@ -8,13 +8,12 @@ import androidx.core.util.Consumer; import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide; -import com.bumptech.glide.load.model.GlideUrl; import com.bumptech.glide.request.RequestOptions; +import it.niedermann.android.glidesso.SingleSignOnUrl; import it.niedermann.nextcloud.deck.R; import it.niedermann.nextcloud.deck.databinding.ItemAccountChooseBinding; import it.niedermann.nextcloud.deck.model.Account; -import it.niedermann.nextcloud.deck.util.glide.SingleSignOnOriginHeader; import static it.niedermann.nextcloud.deck.util.DimensionUtil.dpToPx; @@ -31,7 +30,7 @@ public class AccountSwitcherViewHolder extends RecyclerView.ViewHolder { binding.accountName.setText(account.getUserName()); binding.accountHost.setText(Uri.parse(account.getUrl()).getHost()); Glide.with(itemView.getContext()) - .load(new GlideUrl(account.getAvatarUrl(dpToPx(binding.accountItemAvatar.getContext(), R.dimen.avatar_size)), new SingleSignOnOriginHeader(account))) + .load(new SingleSignOnUrl(account.getName(), account.getAvatarUrl(dpToPx(binding.accountItemAvatar.getContext(), R.dimen.avatar_size)))) .error(R.drawable.ic_person_grey600_24dp) .apply(RequestOptions.circleCropTransform()) .into(binding.accountItemAvatar); diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/manageaccounts/ManageAccountViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/manageaccounts/ManageAccountViewHolder.java index 0208d57d7..231e3f124 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/manageaccounts/ManageAccountViewHolder.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/manageaccounts/ManageAccountViewHolder.java @@ -9,13 +9,12 @@ import androidx.core.util.Consumer; import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide; -import com.bumptech.glide.load.model.GlideUrl; import com.bumptech.glide.request.RequestOptions; +import it.niedermann.android.glidesso.SingleSignOnUrl; import it.niedermann.nextcloud.deck.R; import it.niedermann.nextcloud.deck.databinding.ItemAccountChooseBinding; import it.niedermann.nextcloud.deck.model.Account; -import it.niedermann.nextcloud.deck.util.glide.SingleSignOnOriginHeader; import static android.view.View.GONE; import static android.view.View.VISIBLE; @@ -34,7 +33,7 @@ public class ManageAccountViewHolder extends RecyclerView.ViewHolder { binding.accountName.setText(account.getUserName()); binding.accountHost.setText(Uri.parse(account.getUrl()).getHost()); Glide.with(itemView.getContext()) - .load(new GlideUrl(account.getAvatarUrl(dpToPx(binding.accountItemAvatar.getContext(), R.dimen.avatar_size)), new SingleSignOnOriginHeader(account))) + .load(new SingleSignOnUrl(account.getName(), account.getAvatarUrl(dpToPx(binding.accountItemAvatar.getContext(), R.dimen.avatar_size)))) .error(R.drawable.ic_person_grey600_24dp) .apply(RequestOptions.circleCropTransform()) .into(binding.accountItemAvatar); diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/util/CustomAppGlideModule.java b/app/src/main/java/it/niedermann/nextcloud/deck/util/CustomAppGlideModule.java new file mode 100644 index 000000000..c8b5365f8 --- /dev/null +++ b/app/src/main/java/it/niedermann/nextcloud/deck/util/CustomAppGlideModule.java @@ -0,0 +1,18 @@ +package it.niedermann.nextcloud.deck.util; + +import android.content.Context; + +import androidx.annotation.NonNull; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.Registry; +import com.bumptech.glide.annotation.GlideModule; +import com.bumptech.glide.module.AppGlideModule; + +@GlideModule +public class CustomAppGlideModule extends AppGlideModule { + @Override + public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) { + super.registerComponents(context, glide, registry); + } +}
\ No newline at end of file diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/util/glide/SingleSignOnOriginHeader.java b/app/src/main/java/it/niedermann/nextcloud/deck/util/glide/SingleSignOnOriginHeader.java deleted file mode 100644 index 0c7d1e5a2..000000000 --- a/app/src/main/java/it/niedermann/nextcloud/deck/util/glide/SingleSignOnOriginHeader.java +++ /dev/null @@ -1,38 +0,0 @@ -package it.niedermann.nextcloud.deck.util.glide; - -import androidx.annotation.NonNull; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.load.model.Headers; -import com.bumptech.glide.load.model.LazyHeaders; -import com.nextcloud.android.sso.helper.SingleAccountHelper; -import com.nextcloud.android.sso.model.SingleSignOnAccount; - -import java.util.Map; - -import it.niedermann.nextcloud.deck.model.Account; - -public class SingleSignOnOriginHeader implements Headers { - - private LazyHeaders headers; - - /** - * Use this header and set the {@link SingleSignOnAccount} name property as value - * Format of the value needs to be - */ - public static final String X_HEADER_SSO_ACCOUNT_NAME = "X-SSO-Account-Name"; - - /** - * Use this as {@link Headers} if you want to do a {@link Glide} request for an {@link SingleSignOnAccount} which is not set by {@link SingleAccountHelper} as current {@link SingleSignOnAccount}. - * - * @param account Account from which host the request should be fired - */ - public SingleSignOnOriginHeader(@NonNull Account account) { - this.headers = new LazyHeaders.Builder().addHeader(X_HEADER_SSO_ACCOUNT_NAME, account.getName()).build(); - } - - @Override - public Map<String, String> getHeaders() { - return this.headers.getHeaders(); - } -} diff --git a/glide-sso-integration/.gitignore b/glide-sso-integration/.gitignore new file mode 100644 index 000000000..42afabfd2 --- /dev/null +++ b/glide-sso-integration/.gitignore @@ -0,0 +1 @@ +/build
\ No newline at end of file diff --git a/glide-sso-integration/build.gradle b/glide-sso-integration/build.gradle new file mode 100644 index 000000000..1f8cddf59 --- /dev/null +++ b/glide-sso-integration/build.gradle @@ -0,0 +1,34 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion 29 + buildToolsVersion "29.0.3" + + defaultConfig { + minSdkVersion 14 + targetSdkVersion 29 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles "consumer-rules.pro" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + // Nextcloud SSO + implementation "com.github.nextcloud:Android-SingleSignOn:0.5.1" + + // Glide + implementation 'com.github.bumptech.glide:glide:4.11.0' + annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0' + + implementation fileTree(dir: "libs", include: ["*.jar"]) +}
\ No newline at end of file diff --git a/glide-sso-integration/consumer-rules.pro b/glide-sso-integration/consumer-rules.pro new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/glide-sso-integration/consumer-rules.pro diff --git a/glide-sso-integration/proguard-rules.pro b/glide-sso-integration/proguard-rules.pro new file mode 100644 index 000000000..481bb4348 --- /dev/null +++ b/glide-sso-integration/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile
\ No newline at end of file diff --git a/glide-sso-integration/src/main/AndroidManifest.xml b/glide-sso-integration/src/main/AndroidManifest.xml new file mode 100644 index 000000000..88728afb3 --- /dev/null +++ b/glide-sso-integration/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ +<manifest package="it.niedermann.android.glidesso"> + + / +</manifest>
\ No newline at end of file diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/util/glide/SingleSignOnLibraryGlideModule.java b/glide-sso-integration/src/main/java/it/niedermann/android/glidesso/SingleSignOnLibraryGlideModule.java index 389d31871..6669d5da1 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/util/glide/SingleSignOnLibraryGlideModule.java +++ b/glide-sso-integration/src/main/java/it/niedermann/android/glidesso/SingleSignOnLibraryGlideModule.java @@ -1,6 +1,7 @@ -package it.niedermann.nextcloud.deck.util.glide; +package it.niedermann.android.glidesso; import android.content.Context; +import android.util.Log; import androidx.annotation.NonNull; @@ -8,21 +9,25 @@ import com.bumptech.glide.Glide; import com.bumptech.glide.Registry; import com.bumptech.glide.annotation.GlideModule; import com.bumptech.glide.load.model.GlideUrl; -import com.bumptech.glide.module.AppGlideModule; +import com.bumptech.glide.module.LibraryGlideModule; import java.io.InputStream; /** - * Registers Nextcloud Single-Sign-On related classes via Glide's annotation processor. + * Registers OkHttp related classes via Glide's annotation processor. * - * <p>For Applications that depend on this library and include an {@link AppGlideModule} and Glide's + * <p>For Applications that depend on this library and include an {@link LibraryGlideModule} and Glide's * annotation processor, this class will be automatically included. */ @GlideModule -public final class SingleSignOnLibraryGlideModule extends AppGlideModule { +public final class SingleSignOnLibraryGlideModule extends LibraryGlideModule { + + private static final String TAG = SingleSignOnLibraryGlideModule.class.getSimpleName(); + @Override public void registerComponents( @NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) { + Log.v(TAG, "Replacing default implementation for " + GlideUrl.class.getSimpleName() + "."); registry.replace(GlideUrl.class, InputStream.class, new SingleSignOnUrlLoader.Factory(context)); } } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/util/glide/SingleSignOnStreamFetcher.java b/glide-sso-integration/src/main/java/it/niedermann/android/glidesso/SingleSignOnStreamFetcher.java index b83461e73..10f708890 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/util/glide/SingleSignOnStreamFetcher.java +++ b/glide-sso-integration/src/main/java/it/niedermann/android/glidesso/SingleSignOnStreamFetcher.java @@ -1,6 +1,7 @@ -package it.niedermann.nextcloud.deck.util.glide; +package it.niedermann.android.glidesso; import android.content.Context; +import android.util.Log; import androidx.annotation.NonNull; @@ -8,6 +9,7 @@ import com.bumptech.glide.Priority; import com.bumptech.glide.load.DataSource; import com.bumptech.glide.load.data.DataFetcher; import com.bumptech.glide.load.model.GlideUrl; +import com.google.gson.GsonBuilder; import com.nextcloud.android.sso.AccountImporter; import com.nextcloud.android.sso.aidl.NextcloudRequest; import com.nextcloud.android.sso.api.NextcloudAPI; @@ -25,16 +27,19 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import it.niedermann.nextcloud.deck.DeckLog; -import it.niedermann.nextcloud.deck.api.GsonConfig; - -import static it.niedermann.nextcloud.deck.util.glide.SingleSignOnOriginHeader.X_HEADER_SSO_ACCOUNT_NAME; - /** * Fetches an {@link InputStream} using the Nextcloud SSO library. */ public class SingleSignOnStreamFetcher implements DataFetcher<InputStream> { + + /** + * Use this header and set the {@link SingleSignOnAccount} name property as value + * Format of the value needs to be + */ + public static final String X_HEADER_SSO_ACCOUNT_NAME = "X-SSO-Account-Name"; + + private static final String TAG = SingleSignOnStreamFetcher.class.getSimpleName(); private static final String METHOD_GET = "GET"; private static final Map<String, NextcloudAPI> INITIALIZED_APIs = new HashMap<>(); @@ -62,22 +67,21 @@ public class SingleSignOnStreamFetcher implements DataFetcher<InputStream> { client = INITIALIZED_APIs.get(ssoAccount.name); boolean didInitialize = false; if (client == null) { - client = new NextcloudAPI(context, ssoAccount, GsonConfig.getGson(), new NextcloudAPI.ApiConnectedListener() { + client = new NextcloudAPI(context, ssoAccount, new GsonBuilder().create(), new NextcloudAPI.ApiConnectedListener() { @Override public void onConnected() { - DeckLog.log("success: init SSO-Api"); + Log.v(TAG, "SSO API successfully initialized"); } @Override - public void onError(Exception e) { - DeckLog.logError(e); + public void onError(Exception ex) { + Log.e(TAG, ex.getMessage(), ex); } }); INITIALIZED_APIs.put(ssoAccount.name, client); didInitialize = true; } - // FIXME shouldn't this go into the onConnected() callback if client is null? NextcloudRequest.Builder requestBuilder; try { requestBuilder = new NextcloudRequest.Builder() @@ -91,18 +95,19 @@ public class SingleSignOnStreamFetcher implements DataFetcher<InputStream> { } requestBuilder.setHeader(header); NextcloudRequest nextcloudRequest = requestBuilder.build(); + Log.v(TAG, nextcloudRequest.toString()); Response response = client.performNetworkRequestV2(nextcloudRequest); callback.onDataReady(response.getBody()); } catch (MalformedURLException e) { callback.onLoadFailed(e); } catch (TokenMismatchException e) { if (!didInitialize) { - DeckLog.warn("SSO Glide loader failed with TokenMismatchException, trying to re-initialize..."); + Log.w(TAG, "SSO Glide loader failed with TokenMismatchException, trying to re-initialize..."); client.stop(); INITIALIZED_APIs.remove(ssoAccount.name); loadData(priority, callback); } else { - DeckLog.logError(e); + e.printStackTrace(); callback.onLoadFailed(e); } } catch (Exception e) { diff --git a/glide-sso-integration/src/main/java/it/niedermann/android/glidesso/SingleSignOnUrl.java b/glide-sso-integration/src/main/java/it/niedermann/android/glidesso/SingleSignOnUrl.java new file mode 100644 index 000000000..b8f359757 --- /dev/null +++ b/glide-sso-integration/src/main/java/it/niedermann/android/glidesso/SingleSignOnUrl.java @@ -0,0 +1,88 @@ +package it.niedermann.android.glidesso; + +import android.content.Context; + +import androidx.annotation.NonNull; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.model.GlideUrl; +import com.bumptech.glide.load.model.Headers; +import com.bumptech.glide.load.model.LazyHeaders; +import com.nextcloud.android.sso.helper.SingleAccountHelper; +import com.nextcloud.android.sso.model.SingleSignOnAccount; + +import java.net.URL; +import java.util.Map; + +import static it.niedermann.android.glidesso.SingleSignOnStreamFetcher.X_HEADER_SSO_ACCOUNT_NAME; + +/** + * Use this as kind of {@link GlideUrl} if you want to do a {@link Glide} request from a {@link SingleSignOnAccount} which is not set by {@link SingleAccountHelper#setCurrentAccount(Context, String)}. + */ +public class SingleSignOnUrl extends GlideUrl { + + public SingleSignOnUrl(@NonNull SingleSignOnAccount ssoAccount, @NonNull String url) { + this(ssoAccount.name, url); + } + + public SingleSignOnUrl(@NonNull SingleSignOnAccount ssoAccount, @NonNull URL url) { + this(ssoAccount.name, url); + } + + public SingleSignOnUrl(@NonNull SingleSignOnAccount ssoAccount, @NonNull String url, @NonNull Headers headers) { + this(ssoAccount.name, url, headers); + } + + public SingleSignOnUrl(@NonNull SingleSignOnAccount ssoAccount, @NonNull URL url, @NonNull Headers headers) { + this(ssoAccount.name, url, headers); + } + + public SingleSignOnUrl(@NonNull String ssoAccountName, @NonNull String url) { + super(url, new SingleSignOnOriginHeader(ssoAccountName)); + } + + public SingleSignOnUrl(@NonNull String ssoAccountName, @NonNull URL url) { + super(url, new SingleSignOnOriginHeader(ssoAccountName)); + } + + public SingleSignOnUrl(@NonNull String ssoAccountName, @NonNull String url, @NonNull Headers headers) { + super(url, new SingleSignOnOriginHeader(ssoAccountName, headers)); + } + + public SingleSignOnUrl(@NonNull String ssoAccountName, @NonNull URL url, @NonNull Headers headers) { + super(url, new SingleSignOnOriginHeader(ssoAccountName, headers)); + } + + private static class SingleSignOnOriginHeader implements Headers { + + private Headers headers; + + /** + * Use this as {@link Headers} if you want to do a {@link Glide} request for an {@link SingleSignOnAccount} which is not set by {@link SingleAccountHelper} as current {@link SingleSignOnAccount}. + * + * @param ssoAccountName Account name from which host the request should be fired (needs to match {@link SingleSignOnAccount#name}) + */ + public SingleSignOnOriginHeader(@NonNull String ssoAccountName) { + this.headers = new LazyHeaders.Builder().addHeader(X_HEADER_SSO_ACCOUNT_NAME, ssoAccountName).build(); + } + + /** + * Use this as {@link Headers} if you want to do a {@link Glide} request for an {@link SingleSignOnAccount} which is not set by {@link SingleAccountHelper} as current {@link SingleSignOnAccount}. + * + * @param ssoAccountName Account name from which host the request should be fired (needs to match {@link SingleSignOnAccount#name}) + */ + public SingleSignOnOriginHeader(@NonNull String ssoAccountName, Headers headers) { + LazyHeaders.Builder builder = new LazyHeaders.Builder(); + for (Map.Entry<String, String> entry : headers.getHeaders().entrySet()) { + builder.addHeader(entry.getKey(), entry.getValue()); + } + builder.addHeader(X_HEADER_SSO_ACCOUNT_NAME, ssoAccountName).build(); + this.headers = builder.build(); + } + + @Override + public Map<String, String> getHeaders() { + return this.headers.getHeaders(); + } + } +} diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/util/glide/SingleSignOnUrlLoader.java b/glide-sso-integration/src/main/java/it/niedermann/android/glidesso/SingleSignOnUrlLoader.java index 41ab323fc..10f990b3e 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/util/glide/SingleSignOnUrlLoader.java +++ b/glide-sso-integration/src/main/java/it/niedermann/android/glidesso/SingleSignOnUrlLoader.java @@ -1,4 +1,4 @@ -package it.niedermann.nextcloud.deck.util.glide; +package it.niedermann.android.glidesso; import android.content.Context; @@ -10,15 +10,14 @@ import com.bumptech.glide.load.model.ModelLoader; import com.bumptech.glide.load.model.ModelLoaderFactory; import com.bumptech.glide.load.model.MultiModelLoaderFactory; -import org.jetbrains.annotations.NotNull; - import java.io.InputStream; /** - * A simple model loader for fetching media over http/https using Nextcloud SSO. + * A simple model loader for fetching media over http/https using OkHttp. */ public class SingleSignOnUrlLoader implements ModelLoader<GlideUrl, InputStream> { + private static final String TAG = SingleSignOnUrlLoader.class.getSimpleName(); private final Context context; // Public API. @@ -55,7 +54,7 @@ public class SingleSignOnUrlLoader implements ModelLoader<GlideUrl, InputStream> @NonNull @Override - public ModelLoader<GlideUrl, InputStream> build(@NotNull MultiModelLoaderFactory multiFactory) { + public ModelLoader<GlideUrl, InputStream> build(@NonNull MultiModelLoaderFactory multiFactory) { return loader; } diff --git a/settings.gradle b/settings.gradle index edf1d2bdb..baff05e2d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,4 @@ include ':app' include ':cross-tab-drag-and-drop' +include ':glide-sso-integration' include ':tab-layout-helper' |