feat: visual polish, nav login link, pricing badge fix, cursor fix, button contrast
- 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
This commit is contained in:
80
subscription-middleware.js
Normal file
80
subscription-middleware.js
Normal file
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* 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
|
||||
};
|
||||
Reference in New Issue
Block a user