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
|
|
@ -0,0 +1,121 @@
|
|||
-- ============================================================================
|
||||
-- Mobile monetization hardening
|
||||
-- Atomically revoke Google Play linked purchase tokens before applying a new
|
||||
-- verified purchase. This prevents upgrade/downgrade and resubscribe chains
|
||||
-- from retaining two entitlements.
|
||||
-- ============================================================================
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE OR REPLACE FUNCTION public.apply_verified_google_play_purchase(
|
||||
p_user_id uuid,
|
||||
p_platform text,
|
||||
p_product_id text,
|
||||
p_store_transaction_id text,
|
||||
p_token_hash text,
|
||||
p_linked_token_hash text,
|
||||
p_purchase_token text,
|
||||
p_purchase_state text,
|
||||
p_purchase_at timestamptz,
|
||||
p_expires_at timestamptz,
|
||||
p_auto_renewing boolean,
|
||||
p_acknowledged boolean,
|
||||
p_tier text,
|
||||
p_entitled boolean,
|
||||
p_verification jsonb
|
||||
) RETURNS jsonb
|
||||
LANGUAGE plpgsql
|
||||
SECURITY DEFINER
|
||||
SET search_path = public, pg_temp
|
||||
AS $$
|
||||
DECLARE
|
||||
v_linked_purchase_id uuid;
|
||||
v_linked_user_id uuid;
|
||||
v_linked_revoked boolean := false;
|
||||
v_result jsonb;
|
||||
BEGIN
|
||||
IF p_platform <> 'google_play' THEN
|
||||
RAISE EXCEPTION 'invalid_platform';
|
||||
END IF;
|
||||
|
||||
IF p_linked_token_hash IS NOT NULL THEN
|
||||
IF p_linked_token_hash !~ '^[0-9a-f]{64}$' OR p_linked_token_hash = p_token_hash THEN
|
||||
RAISE EXCEPTION 'invalid_linked_purchase_token';
|
||||
END IF;
|
||||
|
||||
SELECT id, user_id
|
||||
INTO v_linked_purchase_id, v_linked_user_id
|
||||
FROM public.iap_purchases
|
||||
WHERE platform = 'google_play'
|
||||
AND token_hash = p_linked_token_hash
|
||||
FOR UPDATE;
|
||||
|
||||
IF v_linked_user_id IS NOT NULL AND v_linked_user_id <> p_user_id THEN
|
||||
RAISE EXCEPTION 'linked_purchase_owned_by_other_user';
|
||||
END IF;
|
||||
|
||||
IF v_linked_purchase_id IS NOT NULL THEN
|
||||
UPDATE public.iap_purchases
|
||||
SET purchase_state = 'expired',
|
||||
expires_at = least(coalesce(expires_at, now()), now()),
|
||||
auto_renewing = false,
|
||||
verified_at = now(),
|
||||
updated_at = now()
|
||||
WHERE id = v_linked_purchase_id;
|
||||
|
||||
UPDATE public.subscriptions
|
||||
SET tier = 'free',
|
||||
status = 'expired',
|
||||
current_period_end = now(),
|
||||
cancel_at = now(),
|
||||
provider = 'none',
|
||||
payment_provider = 'none',
|
||||
store_product_id = NULL,
|
||||
store_purchase_id = NULL,
|
||||
auto_renewing = false,
|
||||
updated_at = now()
|
||||
WHERE user_id = p_user_id
|
||||
AND store_purchase_id = v_linked_purchase_id;
|
||||
|
||||
IF FOUND THEN
|
||||
UPDATE public.profiles
|
||||
SET tier = 'free',
|
||||
updated_at = now()
|
||||
WHERE id = p_user_id;
|
||||
END IF;
|
||||
v_linked_revoked := true;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
v_result := public.apply_verified_store_purchase(
|
||||
p_user_id,
|
||||
p_platform,
|
||||
p_product_id,
|
||||
p_store_transaction_id,
|
||||
p_token_hash,
|
||||
p_purchase_token,
|
||||
p_purchase_state,
|
||||
p_purchase_at,
|
||||
p_expires_at,
|
||||
p_auto_renewing,
|
||||
p_acknowledged,
|
||||
p_tier,
|
||||
p_entitled,
|
||||
p_verification
|
||||
);
|
||||
|
||||
RETURN v_result || jsonb_build_object('linked_purchase_revoked', v_linked_revoked);
|
||||
END;
|
||||
$$;
|
||||
|
||||
REVOKE ALL ON FUNCTION public.apply_verified_google_play_purchase(
|
||||
uuid, text, text, text, text, text, text, text, timestamptz, timestamptz,
|
||||
boolean, boolean, text, boolean, jsonb
|
||||
) FROM PUBLIC, anon, authenticated;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION public.apply_verified_google_play_purchase(
|
||||
uuid, text, text, text, text, text, text, text, timestamptz, timestamptz,
|
||||
boolean, boolean, text, boolean, jsonb
|
||||
) TO service_role;
|
||||
|
||||
COMMIT;
|
||||
Loading…
Add table
Add a link
Reference in a new issue