Füge Unterstützung für die Installation-ID in Push-Token-Registrierung hinzu: Aktualisiere API- und Datenbank-Logik zur Speicherung der Installation-ID.
All checks were successful
Code Analysis and Production Deploy / analyze (push) Successful in 3m36s
Code Analysis and Production Deploy / deploy-production (push) Has been skipped
Code Analysis and Production Deploy / deploy-test (push) Successful in 2m25s

This commit is contained in:
Torsten Schulz (local)
2026-09-09 14:04:41 +02:00
parent 5e8006323b
commit dc08ae98ea
6 changed files with 18 additions and 8 deletions

View File

@@ -283,6 +283,7 @@ data class PushTokenRequest(
val token: String,
val platform: String = "android",
val appVersion: String? = null,
val installationId: String? = null,
)
data class BirthdayDto(
val name: String = "",

View File

@@ -21,7 +21,7 @@ class HarheimerMessagingService : FirebaseMessagingService() {
override fun onNewToken(token: String) {
super.onNewToken(token)
serviceScope.launch {
pushTokenRepository.registerToken(token)
pushTokenRepository.registerCurrentDevice()
}
}

View File

@@ -1,6 +1,7 @@
package de.harheimertc.repositories
import android.util.Log
import com.google.firebase.installations.FirebaseInstallations
import com.google.firebase.messaging.FirebaseMessaging
import de.harheimertc.BuildConfig
import de.harheimertc.data.ApiService
@@ -15,16 +16,18 @@ class PushTokenRepository @Inject constructor(
) {
suspend fun registerCurrentDevice(): Result<Unit> = runCatching {
val token = FirebaseMessaging.getInstance().token.await()
registerToken(token).getOrThrow()
val installationId = FirebaseInstallations.getInstance().id.await()
registerToken(token, installationId).getOrThrow()
}
suspend fun registerToken(token: String): Result<Unit> = runCatching {
suspend fun registerToken(token: String, installationId: String? = null): Result<Unit> = runCatching {
if (token.isBlank()) return@runCatching
retryOnNetworkFailure {
val response = api.registerPushToken(
PushTokenRequest(
token = token,
appVersion = "${BuildConfig.VERSION_NAME}+${BuildConfig.VERSION_CODE}",
installationId = installationId,
),
)
if (!response.isSuccessful) {

View File

@@ -22,7 +22,8 @@ export default defineEventHandler(async (event) => {
upsertPushToken(users[userIndex], {
token: body.token,
platform: body.platform || 'android',
appVersion: body.appVersion || null
appVersion: body.appVersion || null,
installationId: body.installationId || null
})
await writeUsers(users)
return { success: true, message: 'Push-Token gespeichert.' }

View File

@@ -85,16 +85,21 @@ function pushTokensForUser(user) {
: []
}
export function upsertPushToken(user, { token, platform = 'android', appVersion = null }) {
export function upsertPushToken(user, { token, platform = 'android', appVersion = null, installationId = null }) {
const normalizedToken = String(token || '').trim()
if (!normalizedToken) return user
const normalizedInstallationId = String(installationId || '').trim().slice(0, 200) || null
const now = new Date().toISOString()
const tokens = Array.isArray(user.pushTokens) ? user.pushTokens : []
const next = tokens.filter(entry => entry?.token !== normalizedToken)
// A Firebase token can rotate for the same app installation. Retain tokens
// from other devices, but replace the previous token of this installation.
const next = tokens.filter(entry => entry?.token !== normalizedToken &&
(!normalizedInstallationId || entry?.installationId !== normalizedInstallationId))
next.push({
token: normalizedToken,
platform: String(platform || 'android').slice(0, 30),
appVersion: appVersion ? String(appVersion).slice(0, 80) : null,
installationId: normalizedInstallationId,
updatedAt: now,
createdAt: tokens.find(entry => entry?.token === normalizedToken)?.createdAt || now
})

View File

@@ -247,7 +247,7 @@ describe('Config & Profil Endpoints', () => {
it('speichert Android-Push-Token am Benutzer', async () => {
const event = createEvent({ headers: { authorization: 'Bearer android-token' } })
mockSuccessReadBody({ token: 'fcm-token', platform: 'android', appVersion: '1.0+1' })
mockSuccessReadBody({ token: 'fcm-token', platform: 'android', appVersion: '1.0+1', installationId: 'firebase-installation-id' })
const users = [{ id: '1', email: 'max@test.de', roles: ['mitglied'] }]
authUtils.verifyToken.mockReturnValue({ id: '1' })
authUtils.getUserFromToken.mockResolvedValue(users[0])
@@ -260,7 +260,7 @@ describe('Config & Profil Endpoints', () => {
expect(authUtils.writeUsers).toHaveBeenCalledWith([
expect.objectContaining({
id: '1',
pushTokens: [expect.objectContaining({ token: 'fcm-token', platform: 'android', appVersion: '1.0+1' })]
pushTokens: [expect.objectContaining({ token: 'fcm-token', platform: 'android', appVersion: '1.0+1', installationId: 'firebase-installation-id' })]
})
])
})