Add support for token-based authentication.
This commit is contained in:
parent
13fa966557
commit
fc4c9139c5
@ -10,6 +10,7 @@ public class ConfigManager {
|
||||
private static final String PREFERENCES_NAME = "MINICARDS_PREFERENCES";
|
||||
private static final String TOKEN_KEY = "PROGRAMAKER_API_TOKEN";
|
||||
private static final String BRIDGE_ID_KEY = "PROGRAMAKER_BRIDGE_ID";
|
||||
private static final String BRIDGE_AUTHENTICATION_TOKEN_KEY = "BRIDGE_AUTHENTICATION_TOKEN";
|
||||
private static final String BRIDGE_CONNECTION_ID_KEY = "PROGRAMAKER_BRIDGE_CONNECTION_ID";
|
||||
|
||||
public ConfigManager(Context ctx) {
|
||||
@ -63,4 +64,17 @@ public class ConfigManager {
|
||||
SharedPreferences preferences = this.context.getSharedPreferences(PREFERENCES_NAME, MODE_PRIVATE);
|
||||
return preferences.getString(BRIDGE_CONNECTION_ID_KEY, null);
|
||||
}
|
||||
|
||||
public void setBridgeAuthenticationToken(String bridgeAuthToken) {
|
||||
SharedPreferences preferences = this.context.getSharedPreferences(PREFERENCES_NAME, MODE_PRIVATE);
|
||||
SharedPreferences.Editor edit = preferences.edit();
|
||||
|
||||
edit.putString(BRIDGE_AUTHENTICATION_TOKEN_KEY, bridgeAuthToken);
|
||||
edit.commit();
|
||||
}
|
||||
|
||||
public String getBridgeAuthenticationToken() {
|
||||
SharedPreferences preferences = this.context.getSharedPreferences(PREFERENCES_NAME, MODE_PRIVATE);
|
||||
return preferences.getString(BRIDGE_AUTHENTICATION_TOKEN_KEY, null);
|
||||
}
|
||||
}
|
||||
|
@ -15,8 +15,8 @@ public class ProgramakerAndroidBridge {
|
||||
private StatusStreamer statusStreamer = null;
|
||||
|
||||
// Static
|
||||
public static ProgramakerAndroidBridge configure(Context ctx, String userId, String bridgeId) {
|
||||
return new ProgramakerAndroidBridge(ctx, userId, bridgeId);
|
||||
public static ProgramakerAndroidBridge configure(Context ctx, String userId, String bridgeId, String bridgeToken) {
|
||||
return new ProgramakerAndroidBridge(ctx, userId, bridgeId, bridgeToken);
|
||||
}
|
||||
|
||||
public static String GetBridgeName(Context ctx) {
|
||||
@ -29,11 +29,13 @@ public class ProgramakerAndroidBridge {
|
||||
private final Context ctx;
|
||||
private final String userId;
|
||||
private final String bridgeId;
|
||||
private final String bridgeToken;
|
||||
|
||||
private ProgramakerAndroidBridge(Context ctx, String userId, String bridgeId) {
|
||||
private ProgramakerAndroidBridge(Context ctx, String userId, String bridgeId, String bridgeToken) {
|
||||
this.ctx = ctx;
|
||||
this.userId = userId;
|
||||
this.bridgeId = bridgeId;
|
||||
this.bridgeToken = bridgeToken;
|
||||
}
|
||||
|
||||
public void start(Runnable onReady, Runnable onComplete) {
|
||||
@ -43,7 +45,7 @@ public class ProgramakerAndroidBridge {
|
||||
DefaultAndroidBlocks.GetBuilder(this.ctx).Build()
|
||||
);
|
||||
|
||||
this.bridgeRunner = new ProgramakerBridge(this.bridgeId, this.userId, configuration, onReady, onComplete);
|
||||
this.bridgeRunner = new ProgramakerBridge(this.bridgeId, this.userId, this.bridgeToken, configuration, onReady, onComplete);
|
||||
this.bridgeRunner.run();
|
||||
|
||||
this.statusStreamer = new StatusStreamer(this.ctx, this.bridgeRunner);
|
||||
|
@ -30,6 +30,7 @@ enum ServiceState {
|
||||
public class ProgramakerBridgeService extends Service {
|
||||
public static final String BridgeUserNotificationChannel = "PROGRAMAKER_BRIDGE_USER_NOTIFICATION";
|
||||
public static final CharSequence BridgeUserNotificationChannelName = "User notifications";
|
||||
private static final String AUTOGENERATED_TOKEN_NAME = "Auto-generated";
|
||||
public static String BridgeUserVibrationNotificationChannel = "PROGRAMAKER_BRIDGE_USER_VIBRATION_NOTIFICATIONS";
|
||||
public static CharSequence BridgeUserVibrationNotificationChannelName = "User-triggered vibration";
|
||||
|
||||
@ -160,12 +161,21 @@ public class ProgramakerBridgeService extends Service {
|
||||
bridgeIdCheck = api.createBridge(ProgramakerAndroidBridge.GetBridgeName(this));
|
||||
config.setBridgeId(bridgeIdCheck);
|
||||
}
|
||||
|
||||
String bridgeAuthCheck = config.getBridgeAuthenticationToken();
|
||||
if (bridgeAuthCheck == null) {
|
||||
bridgeAuthCheck = api.createBridgeAuthenticationToken(bridgeIdCheck, ProgramakerBridgeService.AUTOGENERATED_TOKEN_NAME);
|
||||
config.setBridgeAuthenticationToken(bridgeAuthCheck);
|
||||
}
|
||||
|
||||
final String bridgeId = bridgeIdCheck;
|
||||
final String bridgeAuth = bridgeAuthCheck;
|
||||
|
||||
ProgramakerBridgeService.this.bridge = ProgramakerAndroidBridge.configure(
|
||||
this,
|
||||
userId,
|
||||
bridgeId);
|
||||
bridgeId,
|
||||
bridgeAuth);
|
||||
ProgramakerBridgeService.this.bridge.start(
|
||||
() -> { // On ready
|
||||
setBridgeStatusNotification(getString(R.string.bridge_service_online), ServiceState.RUNNING, null);
|
||||
|
@ -211,6 +211,29 @@ class ProgramakerApi(private val ApiRoot: String="https://programaker.com/api")
|
||||
return result.getBridgeId()
|
||||
}
|
||||
|
||||
|
||||
fun createBridgeAuthenticationToken(bridgeId: String, tokenName: String): String {
|
||||
val conn = URL(getCreateBridgeAuthenticationTokenUrl(bridgeId)).openConnection() as HttpURLConnection
|
||||
conn.setRequestProperty("Content-Type", "application/json")
|
||||
addAuthHeader(conn)
|
||||
|
||||
conn.requestMethod = "POST";
|
||||
conn.doOutput = true;
|
||||
|
||||
val postData = JSONObject(hashMapOf(
|
||||
"name" to tokenName
|
||||
) as Map<*, *>)
|
||||
|
||||
val wr = DataOutputStream(conn.outputStream)
|
||||
wr.writeBytes(postData.toString());
|
||||
wr.flush();
|
||||
wr.close();
|
||||
|
||||
val result: ProgramakerFullBridgeInfo
|
||||
result = parseJson(conn.inputStream, ProgramakerFullBridgeInfo::class.java)
|
||||
return result.key
|
||||
}
|
||||
|
||||
fun establishConnection(bridgeId: String): Boolean {
|
||||
// NOTE: This establishes a connection to a bridge as long as it can be done without interaction
|
||||
|
||||
@ -292,9 +315,14 @@ class ProgramakerApi(private val ApiRoot: String="https://programaker.com/api")
|
||||
return "$ApiRoot/v0/users/$userName/bridges"
|
||||
}
|
||||
|
||||
private fun getCreateBridgeAuthenticationTokenUrl(bridgeId: String): String {
|
||||
this.withUserId()
|
||||
return "$ApiRoot/v0/bridges/by-id/$bridgeId/tokens"
|
||||
}
|
||||
|
||||
private fun getPrepareConnectionUrl(bridgeId: String): String {
|
||||
this.withUserName()
|
||||
return "$ApiRoot/v0/users/$userName/services/id/$bridgeId/how-to-enable"
|
||||
this.withUserId()
|
||||
return "$ApiRoot/v0/services/by-id/$bridgeId/how-to-enable"
|
||||
}
|
||||
|
||||
private fun getEstablishConnectionUrl(bridgeId: String): String {
|
||||
|
@ -0,0 +1,6 @@
|
||||
package com.programaker.api.data.api_results
|
||||
|
||||
class ProgramakerFullBridgeInfo (
|
||||
val key: String
|
||||
) {
|
||||
}
|
@ -14,6 +14,7 @@ import java.util.concurrent.TimeUnit
|
||||
class ProgramakerBridge(
|
||||
private val bridge_id: String,
|
||||
private val user_id: String,
|
||||
private val bridge_token: String,
|
||||
private val config: ProgramakerBridgeConfiguration,
|
||||
private val onReady: Runnable,
|
||||
private val onComplete: Runnable
|
||||
@ -49,6 +50,16 @@ class ProgramakerBridge(
|
||||
// Websocket management
|
||||
override fun onOpen(webSocket: WebSocket, response: Response) {
|
||||
this.webSocket = webSocket
|
||||
|
||||
val auth = JSONObject(hashMapOf(
|
||||
"type" to "AUTHENTICATION",
|
||||
"value" to hashMapOf (
|
||||
"token" to this.bridge_token
|
||||
)
|
||||
) as Map<*, *>).toString()
|
||||
|
||||
webSocket.send(auth)
|
||||
|
||||
webSocket.send(config.serialize())
|
||||
onReady.run()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user