From 1a180ea07bd7644f2b090b3ee72de03a6aa370bf Mon Sep 17 00:00:00 2001 From: Guoguo Date: Wed, 20 May 2026 02:25:51 -0700 Subject: [PATCH] fix: prevent trial reset on device rebind MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit confirmBind and mockBind now check trial history before granting trial. Previously only checked for active subscriptions — if trial expired, rebinding would create a new 7-day trial, allowing infinite free usage. Now checks if user ever had a trial (any status), skips if so. --- server/src/dao/binding.dao.js | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/server/src/dao/binding.dao.js b/server/src/dao/binding.dao.js index edf6827..b99e56a 100644 --- a/server/src/dao/binding.dao.js +++ b/server/src/dao/binding.dao.js @@ -95,16 +95,22 @@ async function confirmBind(userId, deviceId, bindToken) { 'UPDATE bindings SET bind_status = 1, bind_time = NOW() WHERE binding_id = ?', [rows[0].binding_id] ) - // Ensure trial subscription - const [subs] = await conn.execute( + // Grant trial only if user has never had one before + const [activeSubs] = await conn.execute( 'SELECT subscription_id FROM subscriptions WHERE user_id = ? AND status = 1 AND expire_time > NOW() LIMIT 1', [userId] ) - if (subs.length === 0) { - await conn.execute( - "INSERT INTO subscriptions (user_id, plan, status, amount, start_time, expire_time) VALUES (?, 'trial', 1, 0, NOW(), DATE_ADD(NOW(), INTERVAL 7 DAY))", + if (activeSubs.length === 0) { + const [trialHistory] = await conn.execute( + "SELECT subscription_id FROM subscriptions WHERE user_id = ? AND plan = 'trial' LIMIT 1", [userId] ) + if (trialHistory.length === 0) { + await conn.execute( + "INSERT INTO subscriptions (user_id, plan, status, amount, start_time, expire_time) VALUES (?, 'trial', 1, 0, NOW(), DATE_ADD(NOW(), INTERVAL 7 DAY))", + [userId] + ) + } } return true }) @@ -136,16 +142,22 @@ async function mockBind(userId, deviceId) { "INSERT INTO bindings (user_id, device_id, bind_token, bind_expires, bind_status, bind_time) VALUES (?, ?, 'mock', NOW(), 1, NOW())", [userId, deviceId] ) - // Ensure trial - const [subs] = await conn.execute( + // Grant trial only if user has never had one before + const [activeSubs] = await conn.execute( 'SELECT subscription_id FROM subscriptions WHERE user_id = ? AND status = 1 AND expire_time > NOW() LIMIT 1', [userId] ) - if (subs.length === 0) { - await conn.execute( - "INSERT INTO subscriptions (user_id, plan, status, amount, start_time, expire_time) VALUES (?, 'trial', 1, 0, NOW(), DATE_ADD(NOW(), INTERVAL 7 DAY))", + if (activeSubs.length === 0) { + const [trialHistory] = await conn.execute( + "SELECT subscription_id FROM subscriptions WHERE user_id = ? AND plan = 'trial' LIMIT 1", [userId] ) + if (trialHistory.length === 0) { + await conn.execute( + "INSERT INTO subscriptions (user_id, plan, status, amount, start_time, expire_time) VALUES (?, 'trial', 1, 0, NOW(), DATE_ADD(NOW(), INTERVAL 7 DAY))", + [userId] + ) + } } return { success: true } })