feat(release): prepare 1.1.0 candidate
This commit is contained in:
parent
5a34f66981
commit
5205dcdfa9
736 changed files with 115667 additions and 12203 deletions
88
server/supabase/functions/_shared/google-pubsub.test.ts
Normal file
88
server/supabase/functions/_shared/google-pubsub.test.ts
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
import {
|
||||
GooglePubSubError,
|
||||
parseGooglePlayRtdn,
|
||||
validateGoogleOidcClaims,
|
||||
} from './google-pubsub.ts'
|
||||
|
||||
function assert(condition: boolean, message: string): asserts condition {
|
||||
if (!condition) throw new Error(message)
|
||||
}
|
||||
|
||||
Deno.test('Google Pub/Sub OIDC claims require exact audience and service identity', () => {
|
||||
validateGoogleOidcClaims({
|
||||
aud: 'https://project.functions.supabase.co/google-play-rtdn',
|
||||
email: 'pubsub-push@example.iam.gserviceaccount.com',
|
||||
email_verified: 'true',
|
||||
exp: '2000000000',
|
||||
iss: 'https://accounts.google.com',
|
||||
}, 'https://project.functions.supabase.co/google-play-rtdn',
|
||||
'pubsub-push@example.iam.gserviceaccount.com', 1900000000)
|
||||
|
||||
for (const claims of [
|
||||
{ aud: 'wrong', email: 'pubsub-push@example.iam.gserviceaccount.com', email_verified: true, exp: 2000000000, iss: 'https://accounts.google.com' },
|
||||
{ aud: 'https://project.functions.supabase.co/google-play-rtdn', email: 'attacker@example.test', email_verified: true, exp: 2000000000, iss: 'https://accounts.google.com' },
|
||||
{ aud: 'https://project.functions.supabase.co/google-play-rtdn', email: 'pubsub-push@example.iam.gserviceaccount.com', email_verified: true, exp: 1800000000, iss: 'https://accounts.google.com' },
|
||||
]) {
|
||||
let error: unknown
|
||||
try {
|
||||
validateGoogleOidcClaims(
|
||||
claims,
|
||||
'https://project.functions.supabase.co/google-play-rtdn',
|
||||
'pubsub-push@example.iam.gserviceaccount.com',
|
||||
1900000000,
|
||||
)
|
||||
} catch (candidate) {
|
||||
error = candidate
|
||||
}
|
||||
assert(error instanceof GooglePubSubError, 'invalid OIDC claims must fail closed')
|
||||
}
|
||||
})
|
||||
|
||||
Deno.test('Google Play RTDN parser accepts only the canonical package and subscription payload', () => {
|
||||
const payload = {
|
||||
version: '1.0',
|
||||
packageName: 'com.d3ro.voice',
|
||||
eventTimeMillis: '1787241600000',
|
||||
subscriptionNotification: {
|
||||
version: '1.0',
|
||||
notificationType: 3,
|
||||
purchaseToken: 'registered-google-play-token',
|
||||
},
|
||||
}
|
||||
const notification = parseGooglePlayRtdn({
|
||||
message: {
|
||||
messageId: 'pubsub-message-1',
|
||||
data: btoa(JSON.stringify(payload)),
|
||||
},
|
||||
})
|
||||
assert(notification.kind === 'subscription', 'subscription payload must be discriminated')
|
||||
assert(notification.packageName === 'com.d3ro.voice', 'package must be canonical')
|
||||
assert(notification.notificationType === 3, 'notification type must be preserved')
|
||||
assert(notification.purchaseToken === 'registered-google-play-token', 'token must be preserved internally')
|
||||
|
||||
payload.packageName = 'com.attacker.app'
|
||||
let error: unknown
|
||||
try {
|
||||
parseGooglePlayRtdn({
|
||||
message: { messageId: 'pubsub-message-2', data: btoa(JSON.stringify(payload)) },
|
||||
})
|
||||
} catch (candidate) {
|
||||
error = candidate
|
||||
}
|
||||
assert(error instanceof GooglePubSubError, 'wrong package must fail closed')
|
||||
})
|
||||
|
||||
Deno.test('Google Play RTDN test notification is acknowledged without a purchase token', () => {
|
||||
const notification = parseGooglePlayRtdn({
|
||||
message: {
|
||||
messageId: 'pubsub-test-message',
|
||||
data: btoa(JSON.stringify({
|
||||
version: '1.0',
|
||||
packageName: 'com.d3ro.voice',
|
||||
eventTimeMillis: '1787241600000',
|
||||
testNotification: { version: '1.0' },
|
||||
})),
|
||||
},
|
||||
})
|
||||
assert(notification.kind === 'test', 'test notification must be recognized')
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue