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

adding support for calling the public branding APIs from the SDK. #74

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
52 changes: 52 additions & 0 deletions app/sdk/utils/branding/BrandingConfiguration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package sdk.utils.branding;

import com.fasterxml.jackson.annotation.JsonProperty;

/**
* Author: Karis Sponsler
* Date: 11/22/17
*/

public class BrandingConfiguration {
Copy link
Contributor

@SamOrozco SamOrozco Nov 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should consider adding @JsonIgnoreProperties(ignoreUnknown = true) If the response changes it will break this request.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed.

@JsonProperty("appID")
public String appId;
@JsonProperty("version")
public String appVersion;
@JsonProperty("appName")
public String appName;
public String logoURL;
@JsonProperty("logoName")
public String logoName;
@JsonProperty("brandingSettings")
public BrandingSettings branding;

public static class BrandingSettings {
@JsonProperty("invertColors")
public boolean invertColors;
@JsonProperty("primaryIOS")
public String primaryIOS;
@JsonProperty("primaryLightIOS")
public String primaryLightIOS;
@JsonProperty("primaryDarkIOS")
public String primaryDarkIOS;
@JsonProperty("primaryTextIOS")
public String primaryTextIOS;
@JsonProperty("secondaryTextIOS")
public String secondaryTextIOS;
@JsonProperty("accentIOS")
public String accentIOS;

@JsonProperty("primaryAndroid")
public String primaryAndroid;
@JsonProperty("primaryLightAndroid")
public String primaryLightAndroid;
@JsonProperty("primaryDarkAndroid")
public String primaryDarkAndroid;
@JsonProperty("primaryTextAndroid")
public String primaryTextAndroid;
@JsonProperty("secondaryTextAndroid")
public String secondaryTextAndroid;
@JsonProperty("accentAndroid")
public String accentAndroid;
}
}
126 changes: 126 additions & 0 deletions app/sdk/utils/branding/BrandingManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package sdk.utils.branding;

import akka.stream.Materializer;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import org.apache.commons.net.util.Base64;
import org.apache.http.client.utils.URIBuilder;
import org.asynchttpclient.AsyncHttpClientConfig;
import org.asynchttpclient.DefaultAsyncHttpClientConfig;
import play.api.libs.ws.WSClientConfig;
import play.api.libs.ws.ahc.AhcConfigBuilder;
import play.api.libs.ws.ahc.AhcWSClientConfig;
import play.api.libs.ws.ahc.AhcWSClientConfigFactory;
import play.api.libs.ws.ssl.SSLConfigFactory;
import play.libs.ws.WSClient;
import play.libs.ws.WSRequest;
import play.mvc.Http;
import scala.concurrent.duration.Duration;
import sdk.utils.JsonUtils;

import javax.inject.Inject;
import java.net.URISyntaxException;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;

/**
* Author: Karis Sponsler
* Date: 11/22/17
*/
public class BrandingManager {
private static WSClient wsClient;
@Inject
private static Materializer materializer;

public static CompletionStage<Branding> getBranding(String appId, String version, String os) {
WSRequest request;
String routerUrl = "https://go-monolith-v2-sbx.herokuapp.com";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The router URL should be parameterized, or otherwise configurable

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed.

try {
request = proxylessClient().url(
new URIBuilder(routerUrl)
.setPath("/client/1/config/brandingConfig")
.build()
.toString()).setHeader("X-APPTREE-APPLICATION-ID", appId).setHeader("X-APPTREE-VERSION", version);
} catch (URISyntaxException e) {
return CompletableFuture.supplyAsync(() -> null);
}
return request
.get()
.thenApply(wsResponse -> {
// Use default branding (baseline page styles) if request failed
if (wsResponse.getStatus() != Http.Status.OK) {
return null;
}

JsonNode json = wsResponse.asJson();
return Optional.ofNullable(JsonUtils.fromJson(json, Branding.class)).orElse(null);
Copy link
Contributor

@SamOrozco SamOrozco Nov 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't Optional.ofNullable return value if not null or Optional.empty() if it is null? I'm not sure why you need orElse(null)

})
.thenCompose(branding -> {
if (branding == null) {
return CompletableFuture.supplyAsync(() -> null);
}

// Get the branding logo data URI
WSRequest logoUrlRequest;
try {
logoUrlRequest = proxylessClient().url(
new URIBuilder(routerUrl).setPath(
String.format("/1/cache/branding/logo/%s", branding.configuration.logoName)
).addParameter("appid", appId).build().toString()
);
} catch (URISyntaxException e) {
return CompletableFuture.supplyAsync(() -> branding);
}

return logoUrlRequest
.get()
.thenApply(wsResponse -> {
// Use unchanged branding (baseline page styles) if request failed
if (wsResponse.getStatus() == Http.Status.OK) {
String logoData =
Base64.encodeBase64String(wsResponse.asByteArray());
branding.configuration.logoURL = String.format("data:image/png;base64,%s", logoData);
}
return branding;
});
})
.exceptionally(throwable -> null);
}

public static WSClient proxylessClient() {
if ( wsClient != null ) {
return wsClient;
}

// Set up the client config (you can also use a parser here):
scala.Option<String> noneString = scala.None$.empty();
WSClientConfig wsClientConfig = new WSClientConfig(
Duration.apply(120, TimeUnit.SECONDS), // connectionTimeout
Duration.apply(120, TimeUnit.SECONDS), // idleTimeout
Duration.apply(120, TimeUnit.SECONDS), // requestTimeout
true, // followRedirects
false, // useProxyProperties
noneString, // userAgent
true, // compressionEnabled / enforced
SSLConfigFactory.defaultConfig());

AhcWSClientConfig clientConfig = AhcWSClientConfigFactory.forClientConfig(wsClientConfig);

AhcConfigBuilder builder = new AhcConfigBuilder(clientConfig);
DefaultAsyncHttpClientConfig.Builder ahcBuilder = builder.configure();
AsyncHttpClientConfig.AdditionalChannelInitializer logging = channel ->
channel.pipeline().addFirst("log", new io.netty.handler.logging.LoggingHandler("debug"));
ahcBuilder.setHttpAdditionalChannelInitializer(logging);

wsClient = new play.libs.ws.ahc.AhcWSClient(ahcBuilder.build(), materializer);

return wsClient;
}

public static class Branding {
@JsonProperty("brandingConfig")
public BrandingConfiguration configuration;
}
}