- Hero mockup: enhanced 3D perspective and shadow - Testimonials: illustrated SVG avatars - Growth pricing card: visual prominence (scale, gradient, badge) - Most Popular badge: repositioned to avoid overlapping heading - Nav: added Log In link next to Start Free Trial - Fixed btn-primary text colour on anchor tags (white on blue) - Fixed cursor: default on all non-interactive elements - Disabled user-select on non-form content to prevent text caret
81 lines
2.0 KiB
JavaScript
81 lines
2.0 KiB
JavaScript
/**
|
|
* 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
|
|
};
|