File size: 5,319 Bytes
5fc01f3
1a0f9f0
 
d8d4e36
6c62800
 
 
 
6b3ee8d
d8d4e36
 
 
1a0f9f0
 
6a9c565
6b3ee8d
828bf6e
6c62800
 
 
 
df1fe51
6c62800
 
 
 
828bf6e
 
 
 
 
 
 
 
f4e209c
bbfb6eb
828bf6e
 
 
 
1a0f9f0
380d805
 
 
 
8f0180b
380d805
4b38102
6b3ee8d
6c62800
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6a9c565
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6c62800
1a0f9f0
 
6b3ee8d
 
1a0f9f0
828bf6e
 
6b3ee8d
 
8f0180b
828bf6e
8f0180b
1a0f9f0
 
380d805
8f0180b
1a0f9f0
 
 
 
 
 
828bf6e
6b3ee8d
1a0f9f0
 
828bf6e
1a0f9f0
6b3ee8d
 
1a0f9f0
828bf6e
 
1a0f9f0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import os
import psycopg
from psycopg.rows import dict_row
from supabase import create_client, Client
import asyncio

conn = None
conn_lock = asyncio.Lock()

SUPABASE_URL = os.getenv("SUPABASE_URL")
SUPABASE_KEY = os.getenv("SUPABASE_SERVICE_ROLE_KEY")
supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY)
POSTGRE_SECRET = os.getenv("POSTGRE_SECRET")

conn = psycopg.connect(POSTGRE_SECRET, row_factory=dict_row, sslmode="verify-full", sslrootcert="prod-ca-2021.crt")


async def get_conn():
    global conn

    if conn is None or conn.closed:
        conn = psycopg.connect(POSTGRE_SECRET, row_factory=dict_row, sslmode="verify-full", sslrootcert="prod-ca-2021.crt")

    return conn


def normalize_plan_key(plan_name: str | None) -> str:
    if not plan_name:
        return "free"
    normalized = "".join(ch for ch in str(plan_name).lower() if ch.isalpha())
    if "professional" in normalized:
        return "professional"
    if "creator" in normalized:
        return "creator"
    if "core" in normalized:
        return "core"
    if "light" in normalized:
        return "light"
    return "free"


async def fetch_subscription(jwt: str):
    auth_res = supabase.auth.get_user(jwt)
    if auth_res.user is None:
        return {"error": "Invalid or expired session"}

    user = auth_res.user
    email = user.email

    async with conn_lock:
        connection = await get_conn()

        try:
            with connection.cursor() as cur:
                cur.execute("""
                    with cust as (
                        select id 
                        from stripe.customers 
                        where email = %s
                    ),
                    subs as (
                        select
                            s.id as subscription_id,
                            s.status,
                            s.current_period_end,
                            s.items->'data'->0->'price'->>'id' as price_id
                        from stripe.subscriptions s
                        join cust on s.customer = cust.id
                        where s.status in ('active', 'trialing', 'past_due')
                    )
                    select
                        subs.subscription_id,
                        subs.status,
                        subs.current_period_end,
                        subs.price_id,
                        prices.nickname,
                        prices.product as product_id,
                        products.name as product_name
                    from subs
                    left join stripe.prices prices
                      on prices.id = subs.price_id
                    left join stripe.products products
                      on prices.product = products.id;
                """, (email,))
                rows = cur.fetchall()

        except psycopg.OperationalError:
            connection = psycopg.connect(POSTGRE_SECRET, row_factory=dict_row)
            with connection.cursor() as cur:
                cur.execute("""
                    with cust as (
                        select id 
                        from stripe.customers 
                        where email = %s
                    ),
                    subs as (
                        select
                            s.id as subscription_id,
                            s.status,
                            s.current_period_end,
                            s.items->'data'->0->'price'->>'id' as price_id
                        from stripe.subscriptions s
                        join cust on s.customer = cust.id
                        where s.status in ('active', 'trialing', 'past_due')
                    )
                    select
                        subs.subscription_id,
                        subs.status,
                        subs.current_period_end,
                        subs.price_id,
                        prices.nickname,
                        prices.product as product_id,
                        products.name as product_name
                    from subs
                    left join stripe.prices prices
                      on prices.id = subs.price_id
                    left join stripe.products products
                      on prices.product = products.id;
                """, (email,))
                rows = cur.fetchall()

    if not rows:
        return {
            "email": email,
            "signed_up": user.created_at.isoformat(),
            "subscription": None,
            "plan_key": "free",
        }

    subscriptions = []
    preferred_plan_key = "free"

    for row in rows:
        plan_key = normalize_plan_key(row["product_name"] or row["nickname"])

        subscriptions.append({
            "subscription_id": row["subscription_id"],
            "status": row["status"],
            "current_period_end": row["current_period_end"],
            "price_id": row["price_id"],
            "product_name": row["product_name"],
            "nickname": row["nickname"],
            "plan_key": plan_key,
        })

        if row["status"] in ("active", "trialing"):
            preferred_plan_key = plan_key

    return {
        "email": email,
        "signed_up": user.created_at.isoformat(),
        "subscription": subscriptions,
        "plan_key": preferred_plan_key,
    }