Custom RTMP saved accounts, RTMP test server, composition pipeline
- Backend: POST /providers/accounts/custom-rtmp to save reusable RTMP servers - Backend: Encrypt rtmpUrl/streamKey in existing token fields, decrypt on GET - Backend: Skip token revocation on DELETE for CUSTOM_RTMP accounts - Backend: Decrypt CUSTOM_RTMP credentials into destinations on plan create/update - Android: Add rtmpUrl/streamKey to LinkedAccount entity + shared parcelable (Room v6) - Android: Add Custom RTMP dialog in AccountsScreen, auto-fill in plan destination picker - Android: Handle CUSTOM_RTMP accounts in CreatePlanViewModel.loadExistingPlan - Add local RTMP test server (tools/rtmp-server.js) with auto-ffplay on publish - Add composition pipeline native code
This commit is contained in:
@@ -302,15 +302,28 @@ class LckControlService : Service() {
|
||||
|
||||
// ── Auth logic ──────────────────────────────────────────
|
||||
|
||||
private fun extractJwtSub(jwt: String): String? {
|
||||
return try {
|
||||
val parts = jwt.split(".")
|
||||
if (parts.size < 2) return null
|
||||
val payload = String(android.util.Base64.decode(parts[1], android.util.Base64.URL_SAFE or android.util.Base64.NO_WRAP))
|
||||
org.json.JSONObject(payload).optString("sub", "").ifEmpty { null }
|
||||
} catch (_: Exception) { null }
|
||||
}
|
||||
|
||||
private suspend fun doAutoLogin() {
|
||||
// Try token refresh first
|
||||
val refreshToken = tokenStore.getRefreshToken()
|
||||
val oldJwt = tokenStore.getJwt()
|
||||
val oldSub = oldJwt?.let { extractJwtSub(it) }
|
||||
Log.d(TAG, "doAutoLogin: hasRefreshToken=${refreshToken != null}, currentUserId=$oldSub")
|
||||
if (refreshToken != null) {
|
||||
Log.d(TAG, "Attempting token refresh...")
|
||||
try {
|
||||
val response = apiService.refreshSession(RefreshRequest(refreshToken))
|
||||
val newSub = extractJwtSub(response.accessToken)
|
||||
Log.d(TAG, "Token refresh successful, userId=$newSub (was $oldSub)")
|
||||
tokenStore.saveSession(response.accessToken, response.refreshToken)
|
||||
Log.d(TAG, "Token refresh successful")
|
||||
broadcastAuthStateChanged(true)
|
||||
return
|
||||
} catch (e: Exception) {
|
||||
@@ -320,6 +333,7 @@ class LckControlService : Service() {
|
||||
}
|
||||
|
||||
// Full Quest SDK login
|
||||
Log.d(TAG, "Starting Quest SDK login (previous userId=$oldSub)")
|
||||
doQuestLogin()
|
||||
}
|
||||
|
||||
@@ -358,8 +372,9 @@ class LckControlService : Service() {
|
||||
)
|
||||
)
|
||||
|
||||
val loginSub = extractJwtSub(response.accessToken)
|
||||
tokenStore.saveSession(response.accessToken, response.refreshToken)
|
||||
Log.d(TAG, "Quest SDK login successful")
|
||||
Log.d(TAG, "Quest SDK login successful, userId=$loginSub")
|
||||
broadcastAuthStateChanged(true)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user