Files
tenderpilot/subscription-middleware.js

81 lines
2.0 KiB
JavaScript
Raw Normal View History

/**
* Middleware to check subscription status for protected routes
*/
export function requireActiveSubscription(req, res, next) {
// Check if user has subscription info attached
if (!req.subscription) {
return res.status(403).json({
error: 'Active subscription required',
code: 'NO_SUBSCRIPTION'
});
}
// Check if subscription is active (not cancelled or past due)
if (req.subscription.status !== 'active' && req.subscription.status !== 'trialing') {
return res.status(403).json({
error: 'Subscription not active',
code: 'SUBSCRIPTION_INACTIVE',
status: req.subscription.status
});
}
// Check if trial has expired (if trialing)
if (req.subscription.status === 'trialing' && req.subscription.trial_end) {
const trialEnd = new Date(req.subscription.trial_end);
if (new Date() > trialEnd) {
return res.status(403).json({
error: 'Trial period expired',
code: 'TRIAL_EXPIRED'
});
}
}
next();
}
/**
* Middleware to attach subscription info to request
* Must be placed after verifyToken middleware
*/
export function attachSubscription(pool) {
return async (req, res, next) => {
if (!req.user) {
return next();
}
try {
const result = await pool.query(
'SELECT * FROM subscriptions WHERE user_id = $1',
[req.user.id]
);
if (result.rows.length > 0) {
req.subscription = result.rows[0];
}
} catch (error) {
console.error('Error fetching subscription:', error);
}
next();
};
}
/**
* Middleware to check if user is on free tier or has active subscription
*/
export function requireFreeOrSubscription(req, res, next) {
// Free tier is always allowed
if (req.user && req.user.tier === 'free') {
return next();
}
// Otherwise, require active subscription
return requireActiveSubscription(req, res, next);
}
export default {
requireActiveSubscription,
attachSubscription,
requireFreeOrSubscription
};