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 PREFERENCES_NAME = "MINICARDS_PREFERENCES";
|
||||||
private static final String TOKEN_KEY = "PROGRAMAKER_API_TOKEN";
|
private static final String TOKEN_KEY = "PROGRAMAKER_API_TOKEN";
|
||||||
private static final String BRIDGE_ID_KEY = "PROGRAMAKER_BRIDGE_ID";
|
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";
|
private static final String BRIDGE_CONNECTION_ID_KEY = "PROGRAMAKER_BRIDGE_CONNECTION_ID";
|
||||||
|
|
||||||
public ConfigManager(Context ctx) {
|
public ConfigManager(Context ctx) {
|
||||||
@ -63,4 +64,17 @@ public class ConfigManager {
|
|||||||
SharedPreferences preferences = this.context.getSharedPreferences(PREFERENCES_NAME, MODE_PRIVATE);
|
SharedPreferences preferences = this.context.getSharedPreferences(PREFERENCES_NAME, MODE_PRIVATE);
|
||||||
return preferences.getString(BRIDGE_CONNECTION_ID_KEY, null);
|
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;
|
private StatusStreamer statusStreamer = null;
|
||||||
|
|
||||||
// Static
|
// Static
|
||||||
public static ProgramakerAndroidBridge configure(Context ctx, String userId, String bridgeId) {
|
public static ProgramakerAndroidBridge configure(Context ctx, String userId, String bridgeId, String bridgeToken) {
|
||||||
return new ProgramakerAndroidBridge(ctx, userId, bridgeId);
|
return new ProgramakerAndroidBridge(ctx, userId, bridgeId, bridgeToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String GetBridgeName(Context ctx) {
|
public static String GetBridgeName(Context ctx) {
|
||||||
@ -29,11 +29,13 @@ public class ProgramakerAndroidBridge {
|
|||||||
private final Context ctx;
|
private final Context ctx;
|
||||||
private final String userId;
|
private final String userId;
|
||||||
private final String bridgeId;
|
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.ctx = ctx;
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
this.bridgeId = bridgeId;
|
this.bridgeId = bridgeId;
|
||||||
|
this.bridgeToken = bridgeToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start(Runnable onReady, Runnable onComplete) {
|
public void start(Runnable onReady, Runnable onComplete) {
|
||||||
@ -43,7 +45,7 @@ public class ProgramakerAndroidBridge {
|
|||||||
DefaultAndroidBlocks.GetBuilder(this.ctx).Build()
|
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.bridgeRunner.run();
|
||||||
|
|
||||||
this.statusStreamer = new StatusStreamer(this.ctx, this.bridgeRunner);
|
this.statusStreamer = new StatusStreamer(this.ctx, this.bridgeRunner);
|
||||||
|
@ -30,6 +30,7 @@ enum ServiceState {
|
|||||||
public class ProgramakerBridgeService extends Service {
|
public class ProgramakerBridgeService extends Service {
|
||||||
public static final String BridgeUserNotificationChannel = "PROGRAMAKER_BRIDGE_USER_NOTIFICATION";
|
public static final String BridgeUserNotificationChannel = "PROGRAMAKER_BRIDGE_USER_NOTIFICATION";
|
||||||
public static final CharSequence BridgeUserNotificationChannelName = "User notifications";
|
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 String BridgeUserVibrationNotificationChannel = "PROGRAMAKER_BRIDGE_USER_VIBRATION_NOTIFICATIONS";
|
||||||
public static CharSequence BridgeUserVibrationNotificationChannelName = "User-triggered vibration";
|
public static CharSequence BridgeUserVibrationNotificationChannelName = "User-triggered vibration";
|
||||||
|
|
||||||
@ -160,12 +161,21 @@ public class ProgramakerBridgeService extends Service {
|
|||||||
bridgeIdCheck = api.createBridge(ProgramakerAndroidBridge.GetBridgeName(this));
|
bridgeIdCheck = api.createBridge(ProgramakerAndroidBridge.GetBridgeName(this));
|
||||||
config.setBridgeId(bridgeIdCheck);
|
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 bridgeId = bridgeIdCheck;
|
||||||
|
final String bridgeAuth = bridgeAuthCheck;
|
||||||
|
|
||||||
ProgramakerBridgeService.this.bridge = ProgramakerAndroidBridge.configure(
|
ProgramakerBridgeService.this.bridge = ProgramakerAndroidBridge.configure(
|
||||||
this,
|
this,
|
||||||
userId,
|
userId,
|
||||||
bridgeId);
|
bridgeId,
|
||||||
|
bridgeAuth);
|
||||||
ProgramakerBridgeService.this.bridge.start(
|
ProgramakerBridgeService.this.bridge.start(
|
||||||
() -> { // On ready
|
() -> { // On ready
|
||||||
setBridgeStatusNotification(getString(R.string.bridge_service_online), ServiceState.RUNNING, null);
|
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()
|
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 {
|
fun establishConnection(bridgeId: String): Boolean {
|
||||||
// NOTE: This establishes a connection to a bridge as long as it can be done without interaction
|
// 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"
|
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 {
|
private fun getPrepareConnectionUrl(bridgeId: String): String {
|
||||||
this.withUserName()
|
this.withUserId()
|
||||||
return "$ApiRoot/v0/users/$userName/services/id/$bridgeId/how-to-enable"
|
return "$ApiRoot/v0/services/by-id/$bridgeId/how-to-enable"
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getEstablishConnectionUrl(bridgeId: String): String {
|
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(
|
class ProgramakerBridge(
|
||||||
private val bridge_id: String,
|
private val bridge_id: String,
|
||||||
private val user_id: String,
|
private val user_id: String,
|
||||||
|
private val bridge_token: String,
|
||||||
private val config: ProgramakerBridgeConfiguration,
|
private val config: ProgramakerBridgeConfiguration,
|
||||||
private val onReady: Runnable,
|
private val onReady: Runnable,
|
||||||
private val onComplete: Runnable
|
private val onComplete: Runnable
|
||||||
@ -49,6 +50,16 @@ class ProgramakerBridge(
|
|||||||
// Websocket management
|
// Websocket management
|
||||||
override fun onOpen(webSocket: WebSocket, response: Response) {
|
override fun onOpen(webSocket: WebSocket, response: Response) {
|
||||||
this.webSocket = webSocket
|
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())
|
webSocket.send(config.serialize())
|
||||||
onReady.run()
|
onReady.run()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user