Skip to content

Commit

Permalink
Merge pull request #18 from shankari/switch_to_new_auth
Browse files Browse the repository at this point in the history
Generalize the plugin to make it easier to add new providers
  • Loading branch information
shankari authored Aug 21, 2017
2 parents 8eb1144 + f25bf22 commit d04a504
Show file tree
Hide file tree
Showing 21 changed files with 1,002 additions and 248 deletions.
16 changes: 13 additions & 3 deletions plugin.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0"
id="edu.berkeley.eecs.emission.cordova.auth"
version="1.0.1">
version="1.1.0">

<name>JWTAuth</name>
<description>Get the user email and associated JWT tokens from both native
Expand Down Expand Up @@ -46,7 +46,12 @@

<source-file src="src/android/JWTAuthPlugin.java" target-dir="src/edu/berkeley/eecs/emission/cordova/jwtauth"/>
<source-file src="src/android/GoogleAccountManagerAuth.java" target-dir="src/edu/berkeley/eecs/emission/cordova/jwtauth"/>
<source-file src="src/android/DummyDevAuth.java" target-dir="src/edu/berkeley/eecs/emission/cordova/jwtauth"/>
<source-file src="src/android/UserProfile.java" target-dir="src/edu/berkeley/eecs/emission/cordova/jwtauth"/>
<source-file src="src/android/AuthResult.java" target-dir="src/edu/berkeley/eecs/emission/cordova/jwtauth"/>
<source-file src="src/android/AuthPendingResult.java" target-dir="src/edu/berkeley/eecs/emission/cordova/jwtauth"/>
<source-file src="src/android/AuthTokenCreator.java" target-dir="src/edu/berkeley/eecs/emission/cordova/jwtauth"/>
<source-file src="src/android/AuthTokenCreationFactory.java" target-dir="src/edu/berkeley/eecs/emission/cordova/jwtauth"/>
</platform>

<platform name="ios">
Expand All @@ -63,10 +68,15 @@
<framework src="GoogleSignIn" type="podspec" spec="~> 4.0.0"/>

<header-file src="src/ios/BEMJWTAuth.h"/>
<header-file src="src/ios/AuthCompletionHandler.h"/>
<header-file src="src/ios/GoogleSigninAuth.h"/>
<header-file src="src/ios/DummyDevAuth.h"/>
<header-file src="src/ios/AuthTokenCreator.h"/>
<header-file src="src/ios/AuthTokenCreationFactory.h"/>

<source-file src="src/ios/BEMJWTAuth.m"/>
<source-file src="src/ios/AuthCompletionHandler.m"/>
<source-file src="src/ios/GoogleSigninAuth.m"/>
<source-file src="src/ios/DummyDevAuth.m"/>
<source-file src="src/ios/AuthTokenCreationFactory.m"/>

</platform>
</plugin>
153 changes: 153 additions & 0 deletions src/android/AuthPendingResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package edu.berkeley.eecs.emission.cordova.jwtauth;

import android.os.AsyncTask;
import android.support.annotation.NonNull;

import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.common.api.CommonStatusCodes;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;

import java.util.concurrent.TimeUnit;

import edu.berkeley.eecs.emission.BuildConfig;
import android.util.Log;

public class AuthPendingResult extends PendingResult<AuthResult> {
private static final String TAG = "AuthPendingResult";
private final Object syncToken = new Object();

private AuthResult mAuthResult;
private boolean mCancelled;
private ResultCallback<? super AuthResult> mResultCallback;

protected AuthPendingResult() {
mAuthResult = null;
mResultCallback = null;
mCancelled = false;
}

@NonNull
@Override
public AuthResult await() {
synchronized (syncToken) {
if (mAuthResult != null) {
return mAuthResult;
} // else
try {
syncToken.wait();
if (BuildConfig.DEBUG) {
if (mAuthResult == null) {
throw new RuntimeException("in await, notify received,"
+ " but mAuthResult = null");
}
}
} catch (InterruptedException e) {
mAuthResult = new AuthResult(new Status(CommonStatusCodes.INTERRUPTED), null, null);
}
return mAuthResult;
}
}

@NonNull
@Override
public AuthResult await(long l, @NonNull TimeUnit timeUnit) {
synchronized (syncToken) {
if (mAuthResult != null) {
return mAuthResult;
}
try {
syncToken.wait(timeUnit.toMillis(l));
if (BuildConfig.DEBUG) {
if (mAuthResult == null) {
throw new RuntimeException("in await, notify received,"
+ " but mAuthResult = null");
}
}
} catch (InterruptedException e) {
mAuthResult = new AuthResult(new Status(CommonStatusCodes.INTERRUPTED), null, null);
}
}
return mAuthResult;
}

@Override
public void cancel() {
synchronized(syncToken) {
mAuthResult = new AuthResult(new Status(CommonStatusCodes.CANCELED), null, null);
mCancelled = true;
syncToken.notify();
if (mResultCallback != null) {
mResultCallback.onResult(mAuthResult);
}
}
}

@Override
public boolean isCanceled() {
return mCancelled;
}

@Override
public void setResultCallback(@NonNull ResultCallback<? super AuthResult> resultCallback) {
synchronized (syncToken) {
mResultCallback = resultCallback;
if (mAuthResult != null) {
mResultCallback.onResult(mAuthResult);
}
}
}

@Override
public void setResultCallback(@NonNull ResultCallback<? super AuthResult> resultCallback, long l, @NonNull TimeUnit timeUnit) {
synchronized (syncToken) {
mResultCallback = resultCallback;
if (mAuthResult != null) {
mResultCallback.onResult(mAuthResult);
}
}
if (mAuthResult == null) {
AsyncTask<Long, Integer, Void> sleepTask = new AsyncTask<Long, Integer, Void>() {
@Override
protected Void doInBackground(Long... millis) {
try {
long millisecs = millis[0];
Thread.sleep(millisecs);
synchronized (syncToken) {
if (mAuthResult == null) {
AuthResult timeoutResult = new AuthResult(
new com.google.android.gms.common.api.Status(CommonStatusCodes.TIMEOUT), null, null);
mResultCallback.onResult(timeoutResult);
mResultCallback = null;
} else {
Log.d(TAG, "Result already set, nothing to do");
}
}
} catch (InterruptedException e) {
synchronized (syncToken) {
AuthResult timeoutResult = new AuthResult(
new com.google.android.gms.common.api.Status(CommonStatusCodes.INTERRUPTED), null, null);
mResultCallback.onResult(timeoutResult);
mResultCallback = null;
}
}
return null;
}
};
sleepTask.execute(timeUnit.toMillis(l));
} else {
Log.d(TAG, "Result already set, nothing to do");
}
}

protected void setResult(AuthResult result) {
synchronized (syncToken) {
mAuthResult = result;
syncToken.notifyAll();
if (mResultCallback != null) {
mResultCallback.onResult(mAuthResult);
}
}
}
}
35 changes: 35 additions & 0 deletions src/android/AuthResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package edu.berkeley.eecs.emission.cordova.jwtauth;

import com.google.android.gms.common.api.Result;
import com.google.android.gms.common.api.Status;

/**
* Result class for async operation.
* Unsure whether we should use PendingResult for callbacks
* but it is certainly more consistent with the new google APIs
*/

public class AuthResult implements Result {
private Status status;
private String email;
private String token;

public AuthResult(Status istatus, String iemail, String itoken) {
status = istatus;
email = iemail;
token = itoken;
}

@Override
public Status getStatus() {
return status;
}

public String getEmail() {
return email;
}

public String getToken() {
return token;
}
}
27 changes: 27 additions & 0 deletions src/android/AuthTokenCreationFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package edu.berkeley.eecs.emission.cordova.jwtauth;

import android.content.Context;

import edu.berkeley.eecs.emission.cordova.connectionsettings.ConnectionSettings;

/**
* Created by shankari on 8/19/17.
*
* Factory to generate AuthTokenCreator instances based on the connection settings
*/

public class AuthTokenCreationFactory {
public static AuthTokenCreator getInstance(Context ctxt) {
String authMethod = ConnectionSettings.getAuthMethod(ctxt);
if ("google-authutil".equals(authMethod)) {
return new GoogleAccountManagerAuth(ctxt);
} else if ("dummy-dev".equals(authMethod)) {
return new DummyDevAuth(ctxt);
} else {
// Return dummy dev sign-in handler by default so that:
// - we know that this will never return null
// - dev users can start working without any configuration stuff
return new DummyDevAuth(ctxt);
}
}
}
26 changes: 26 additions & 0 deletions src/android/AuthTokenCreator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package edu.berkeley.eecs.emission.cordova.jwtauth;

import android.content.Intent;
import org.apache.cordova.CordovaPlugin;

/**
* Created by shankari on 8/19/17.
*
* Interface that defines the methods that all auth handlers must define.
*/

public interface AuthTokenCreator {
// Method to sign in via the UI
public AuthPendingResult uiSignIn(CordovaPlugin plugin);

// Method to retrieve signed-in user information
// Result is only guaranteed to have requested information filled in
public AuthPendingResult getUserEmail();
public AuthPendingResult getServerToken();

// Callback to get the signin information, if provided through activity result
public void onActivityResult(int requestCode, int resultCode, Intent data);

// Callback to get the signin information, if provided through a custom URL
public void onNewIntent(Intent intent);
}
Loading

0 comments on commit d04a504

Please sign in to comment.