Skip to content

Commit

Permalink
Re-Enable Examples running during PRs (#460)
Browse files Browse the repository at this point in the history
* Re Enable Examples

* Ensure Tests are always run because they are non deterministic.
  • Loading branch information
handstandsam authored Sep 29, 2022
1 parent dc69c9f commit 460d63b
Show file tree
Hide file tree
Showing 38 changed files with 413 additions and 363 deletions.
10 changes: 7 additions & 3 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@ jobs:
- run: python -m pip install ply && pip install six

- name: Grant execute permissions
run: chmod +x gradlew && chmod +x update-submodules
&& chmod +x generate-ci-auth-file && chmod +x scripts/run-examples
&& chmod +x scripts/check-clean-git-status
run: chmod +x gradlew
&& chmod +x update-submodules
&& chmod +x generate-ci-auth-file
&& chmod +x scripts/check-clean-git-status

- name: Set up submodules
run: ./update-submodules
Expand All @@ -61,6 +62,9 @@ jobs:
- name: Check
run: ./gradlew check

- name: Run Integration Tests for Examples
run: ./gradlew :examples:examples:test -Pci=true --info

- name: Run Integration Tests - OkHttpRequestor
run: ./gradlew -Pcom.dropbox.test.httpRequestor=OkHttpRequestor -Pcom.dropbox.test.authInfoFile=../auth_output integrationTest &&
./gradlew -Pcom.dropbox.test.httpRequestor=OkHttpRequestor -Pcom.dropbox.test.authInfoFile=../auth_output proguardTest
Expand Down
51 changes: 0 additions & 51 deletions .github/workflows/examples.yml

This file was deleted.

36 changes: 26 additions & 10 deletions examples/examples/build.gradle
Original file line number Diff line number Diff line change
@@ -1,16 +1,32 @@
apply plugin: 'java'
apply plugin: 'kotlin'
apply from: '../../gradle/integration-test-config.gradle'
plugins {
id("java")
id("kotlin")
}

description = 'Consolidated Examples'

java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}

dependencies {
testImplementation 'org.eclipse.jetty.aggregate:jetty-server:8.1.18.v20150929'
testImplementation 'javax.servlet:javax.servlet-api:3.1.0'
testImplementation 'org.apache.commons:commons-lang3:3.4'
testImplementation 'com.fasterxml.jackson.core:jackson-core:2.7.9'
testImplementation 'com.fasterxml.jackson.core:jackson-databind:2.7.4'
implementation(project(":dropbox-sdk-java"))
implementation("org.eclipse.jetty.aggregate:jetty-server:8.1.18.v20150929")
implementation("javax.servlet:javax.servlet-api:3.1.0")
implementation("org.apache.commons:commons-lang3:3.4")
implementation("com.fasterxml.jackson.core:jackson-core:2.7.9")
implementation("com.fasterxml.jackson.core:jackson-databind:2.7.4")
implementation(dropboxJavaSdkLibs.okhttp3)
implementation("org.json:json:20220320")

testImplementation(dropboxJavaSdkLibs.test.junit)
testImplementation(dropboxJavaSdkLibs.okhttp3)
testImplementation("org.json:json:20220320")
}

test {
// Uses the "ci" gradle property and sets it as an environment variable for the test
environment("ci", project.findProperty("ci"))

// Ensure that tests are always run because integration tests are non-deterministic
outputs.upToDateWhen { false }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.dropbox.core.examples

import com.dropbox.core.DbxAuthInfo
import com.dropbox.core.DbxHost
import com.dropbox.core.oauth.DbxCredential
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONObject
import java.io.File

object CredentialsUtil {

private val okhttp = OkHttpClient.Builder().build()

data class OAuth2TokenInputs(
val appKey: String?,
val appSecret: String?,
val refreshToken: String?,
) {
companion object {
fun fromEnvironment(): OAuth2TokenInputs {
val appKey = System.getenv("APP_KEY")
val appSecret = System.getenv("APP_SECRET")
val refreshToken = System.getenv("REFRESH_TOKEN")

require(appKey?.isNotEmpty() == true) { "APP_KEY is not set as an environment variable." }
require(appSecret?.isNotEmpty() == true) { "APP_SECRET is not set as an environment variable." }
require(refreshToken?.isNotEmpty() == true) { "REFRESH_TOKEN is not set as an environment variable." }

return OAuth2TokenInputs(
appKey = appKey,
appSecret = appSecret,
refreshToken = refreshToken
)
}
}
}

/**
* Will call the token API and get a new Access Token in exchange for a Refresh Token and App Key
*/
private fun credsFromRefreshToken(refreshToken: String, appKey: String): DbxCredential {
val request = Request.Builder()
.url(
"https://api.dropbox.com/oauth2/token"
.toHttpUrl()
.newBuilder()
.apply {
addQueryParameter("grant_type", "refresh_token")
addQueryParameter("refresh_token", refreshToken)
addQueryParameter("client_id", appKey)
}.build()
)
.post("".toRequestBody())
.build()

val response = okhttp.newCall(request).execute()
val jsonObj = JSONObject(response.body?.string())
val accessToken = jsonObj.getString("access_token")
return DbxCredential(accessToken)
}

private val authOutputFile = File("../../auth_output")

fun getDbxCredential(): DbxCredential {
return DbxCredential.Reader.readFromFile(authOutputFile)
}

fun getAuthInfo(): DbxAuthInfo {
return DbxAuthInfo.Reader.readFromFile(authOutputFile)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,24 @@ package com.dropbox.core.examples.account_info

import com.dropbox.core.DbxException
import com.dropbox.core.DbxRequestConfig
import com.dropbox.core.examples.CredentialsUtil.getDbxCredential
import com.dropbox.core.examples.CredentialsUtil.isRunningInCI
import com.dropbox.core.examples.CredentialsUtil
import com.dropbox.core.oauth.DbxCredential
import com.dropbox.core.v2.DbxClientV2
import org.junit.Test
import java.io.IOException

/**
* An example command-line application that grab access token and refresh token from credential
* file, and then call APIV2. If the access token has expired, SDK will automatically refresh and
* get a new one, and store them into the original DbxCredential object.
*/
class AccountInfoExample {
object AccountInfoExample {

@Test
fun test() {
if (!isRunningInCI()) {
// Only run in CI
return
}
val credential = getDbxCredential()
@JvmStatic
fun main(args: Array<String>) {
val credential = CredentialsUtil.getDbxCredential()
runExample(credential)
}

fun runExample(credential: DbxCredential) {
// Create a DbxClientV2, which is what you use to make API calls.
val requestConfig = DbxRequestConfig("examples-account-info")
// Use DbxCredential to create dbx client.
Expand All @@ -35,4 +33,4 @@ class AccountInfoExample {
throw RuntimeException("Error making API call: " + ex.message)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,31 +1,26 @@
package com.dropbox.core.examples.account_info_legacy

import com.dropbox.core.DbxAuthInfo
import com.dropbox.core.DbxRequestConfig
import com.dropbox.core.DbxWebAuth
import com.dropbox.core.examples.CredentialsUtil
import com.dropbox.core.examples.CredentialsUtil.getAuthInfo
import com.dropbox.core.examples.CredentialsUtil.isRunningInCI
import com.dropbox.core.stone.StoneDeserializerLogger
import com.dropbox.core.v2.DbxClientV2
import com.dropbox.core.v2.users.Name
import org.junit.Ignore
import org.junit.Test

/**
* An example command-line application that runs through the web-based OAuth
* flow (using [DbxWebAuth]).
*/
class AccountInfoLegacyExample {
object AccountInfoLegacyExample {

@Ignore("Not Enabling Yet")
@Test
fun test() {
if (!isRunningInCI()) {
// Only run in CI
return
}
// Read auth info file.
val authInfo = getAuthInfo()
@JvmStatic
fun main(args: Array<String>) {
val authInfo = CredentialsUtil.getAuthInfo()
runExample(authInfo)
}

fun runExample(authInfo: DbxAuthInfo) {
// Create a DbxClientV2, which is what you use to make API calls.
val requestConfig = DbxRequestConfig("examples-account-info")
val dbxClient = DbxClientV2(requestConfig, authInfo.accessToken, authInfo.host)
Expand All @@ -39,4 +34,4 @@ class AccountInfoLegacyExample {
val dbxAccountInfo = dbxClient.users().currentAccount
print(dbxAccountInfo.toStringMultiline())
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package com.dropbox.core.examples.authorize

import com.dropbox.core.DbxAppInfo
import com.dropbox.core.DbxAuthFinish
import com.dropbox.core.json.JsonReader
import com.dropbox.core.oauth.DbxCredential
import java.io.File
import java.io.IOException
import java.util.logging.Level
import java.util.logging.Logger

/**
*
* An example command-line application that runs through the web-based OAuth
* flow (using [DbxWebAuth]). It grabs short-live token as well as
* refresh token from server. It stores all authentication related data into the new
* DbxCredential object and save them to file.
*/
object AuthorizeExample {
@JvmStatic
fun main(args: Array<String>) {
// Only display important log messages.
Logger.getLogger("").level = Level.WARNING
if (args.size != 3) {
System.err.println("Usage: COMMAND <app-info-file> <auth-file-output> <mode>")
System.err.println("")
System.err.println("<app-info-file>: a JSON file with information about your API app. Example:")
System.err.println("")
System.err.println(" {")
System.err.println(" \"key\": \"Your Dropbox API app key...\",")
System.err.println(" \"secret\": \"Your Dropbox API app secret...\"")
System.err.println(" }")
System.err.println("")
System.err.println(" Get an API app key by registering with Dropbox:")
System.err.println(" https://dropbox.com/developers/apps")
System.err.println("")
System.err.println("<auth-file-output>: If authorization is successful, the resulting API")
System.err.println(" credential will be saved to this file, which can then be used with")
System.err.println(" other example programs, such as the one in \"examples/account-info\".")
System.err.println("")
System.err.println("<mode>: value can only be short_live_token, pkce, scope, or incremental.")
System.err.println(" short_live_token: authorization will request short_lived_token")
System.err.println(" together with refresh token and expiration time.")
System.err.println(" pkce: authorization will run short_live_token without app secret")
System.err.println(" use that when you have a client side only app without server.")
System.err.println(" scope: authorization will request specific scope.")
System.err.println("")
System.exit(1)
return
}
val argAppInfoFile = args[0]
val argAuthFileOutput = args[1]

// Read app info file (contains app key and app secret)
val appInfo: DbxAppInfo
appInfo = try {
DbxAppInfo.Reader.readFromFile(argAppInfoFile)
} catch (ex: JsonReader.FileLoadException) {
System.err.println("Error reading <app-info-file>: " + ex.message)
System.exit(1)
return
}

// Run through Dropbox API authorization process
var authFinish: DbxAuthFinish? = null
when (args[2]) {
"short_live_token" -> authFinish = ShortLiveTokenAuthorize().authorize(appInfo)
"pkce" -> authFinish = PkceAuthorize().authorize(appInfo)
"scope" -> authFinish = ScopeAuthorize().authorize(appInfo)
else -> {
System.err.println("Error reading <mode> : " + args[2])
System.exit(1)
}
}
println("Authorization complete.")
println("- User ID: " + authFinish!!.userId)
println("- Account ID: " + authFinish.accountId)
println("- Access Token: " + authFinish.accessToken)
println("- Expires At: " + authFinish.expiresAt)
println("- Refresh Token: " + authFinish.refreshToken)
println("- Scope: " + authFinish.scope)

// Save auth information the new DbxCredential instance. It also contains app_key and
// app_secret which is required to do refresh call.
val credential = DbxCredential(
authFinish.accessToken, authFinish
.expiresAt, authFinish.refreshToken, appInfo.key, appInfo.secret
)
val output = File(argAuthFileOutput)
try {
DbxCredential.Writer.writeToFile(credential, output)
println("Saved authorization information to \"" + output.canonicalPath + "\".")
} catch (ex: IOException) {
System.err.println("Error saving to <auth-file-out>: " + ex.message)
System.err.println("Dumping to stderr instead:")
DbxCredential.Writer.writeToStream(credential, System.err)
System.exit(1)
return
}
}
}
Loading

0 comments on commit 460d63b

Please sign in to comment.