✨ Features: - Modern SaaS automation platform - Next.js 15 + TypeScript frontend - Node.js + Express backend - PostgreSQL database with full schema - Docker Compose setup - Admin panel with analytics - Template marketplace (6 templates) - Integrations hub (10+ services) - Authentication & role-based access - Responsive n8n-style design 🎯 Ready for demo and deployment 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
713 lines
No EOL
23 KiB
TypeScript
713 lines
No EOL
23 KiB
TypeScript
import express from 'express';
|
|
import cors from 'cors';
|
|
import helmet from 'helmet';
|
|
import dotenv from 'dotenv';
|
|
|
|
dotenv.config();
|
|
|
|
const app = express();
|
|
const PORT = process.env.PORT || 3001;
|
|
|
|
app.use(helmet());
|
|
app.use(cors());
|
|
app.use(express.json());
|
|
|
|
app.get('/health', (req, res) => {
|
|
res.json({ status: 'OK', timestamp: new Date().toISOString() });
|
|
});
|
|
|
|
// Simple test route
|
|
app.get('/test', (req, res) => {
|
|
res.json({ message: 'Backend is working!' });
|
|
});
|
|
|
|
// Simple auth endpoints for testing
|
|
app.post('/auth/login', async (req, res) => {
|
|
try {
|
|
const { email, password } = req.body;
|
|
|
|
if (!email || !password) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: 'Email and password are required'
|
|
});
|
|
}
|
|
|
|
// For now, just check against our known admin user
|
|
if (email === 'info@ai-impress.com' && password === 'admin123') {
|
|
const token = 'test-admin-token-123';
|
|
const user = {
|
|
id: 1,
|
|
email: 'info@ai-impress.com',
|
|
first_name: 'Global',
|
|
last_name: 'Admin',
|
|
role: 'admin',
|
|
subscription_plan: 'enterprise',
|
|
subscription_status: 'active',
|
|
is_verified: true,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString()
|
|
};
|
|
|
|
return res.json({
|
|
success: true,
|
|
token,
|
|
user
|
|
});
|
|
}
|
|
|
|
return res.status(401).json({
|
|
success: false,
|
|
message: 'Invalid credentials'
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('Login error:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: 'Internal server error'
|
|
});
|
|
}
|
|
});
|
|
|
|
app.post('/auth/signup', async (req, res) => {
|
|
try {
|
|
const { email, password, first_name, last_name } = req.body;
|
|
|
|
if (!email || !password) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: 'Email and password are required'
|
|
});
|
|
}
|
|
|
|
// Simple mock signup
|
|
const token = 'test-user-token-456';
|
|
const user = {
|
|
id: 2,
|
|
email,
|
|
first_name: first_name || '',
|
|
last_name: last_name || '',
|
|
role: 'free',
|
|
subscription_plan: 'free',
|
|
subscription_status: 'active',
|
|
is_verified: false,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString()
|
|
};
|
|
|
|
res.status(201).json({
|
|
success: true,
|
|
token,
|
|
user
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('Signup error:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: 'Internal server error'
|
|
});
|
|
}
|
|
});
|
|
|
|
// Admin Analytics endpoint
|
|
app.get('/admin/analytics', (req, res) => {
|
|
try {
|
|
// Mock analytics data
|
|
const analytics = {
|
|
userStats: {
|
|
total_users: 156,
|
|
free_users: 120,
|
|
pro_users: 28,
|
|
enterprise_users: 6,
|
|
admin_users: 2,
|
|
verified_users: 134,
|
|
active_last_7_days: 89,
|
|
new_last_30_days: 23
|
|
},
|
|
workflowStats: {
|
|
total_workflows: 342,
|
|
active_workflows: 278,
|
|
new_workflows_30_days: 45,
|
|
activation_rate: 81.2
|
|
},
|
|
executionStats: {
|
|
total_executions: 12847,
|
|
successful_executions: 12234,
|
|
executions_24h: 234,
|
|
executions_7d: 1876
|
|
},
|
|
revenueStats: {
|
|
total_revenue: 18750.00,
|
|
revenue_30_days: 4200.00,
|
|
successful_payments: 34,
|
|
average_order_value: 150.00
|
|
},
|
|
integrationStats: [
|
|
{ provider: 'telegram', count: 45 },
|
|
{ provider: 'slack', count: 38 },
|
|
{ provider: 'gmail', count: 67 },
|
|
{ provider: 'teams', count: 23 }
|
|
],
|
|
recentActivity: [
|
|
{
|
|
action: 'create_workflow',
|
|
resource_type: 'workflow',
|
|
created_at: new Date(Date.now() - 1000 * 60 * 5).toISOString(),
|
|
user_email: 'john@example.com'
|
|
},
|
|
{
|
|
action: 'upgrade_subscription',
|
|
resource_type: 'subscription',
|
|
created_at: new Date(Date.now() - 1000 * 60 * 15).toISOString(),
|
|
user_email: 'sarah@company.com'
|
|
},
|
|
{
|
|
action: 'execute_workflow',
|
|
resource_type: 'workflow',
|
|
created_at: new Date(Date.now() - 1000 * 60 * 8).toISOString(),
|
|
user_email: 'mike@startup.io'
|
|
},
|
|
{
|
|
action: 'create_integration',
|
|
resource_type: 'integration',
|
|
created_at: new Date(Date.now() - 1000 * 60 * 22).toISOString(),
|
|
user_email: 'lisa@agency.com'
|
|
},
|
|
{
|
|
action: 'login',
|
|
resource_type: 'auth',
|
|
created_at: new Date(Date.now() - 1000 * 60 * 3).toISOString(),
|
|
user_email: 'admin@platform.com'
|
|
}
|
|
],
|
|
topUsers: [
|
|
{
|
|
email: 'power.user@company.com',
|
|
first_name: 'Alex',
|
|
last_name: 'Johnson',
|
|
subscription_plan: 'enterprise',
|
|
workflow_count: 24,
|
|
last_login_at: new Date(Date.now() - 1000 * 60 * 30).toISOString()
|
|
},
|
|
{
|
|
email: 'busy.bee@startup.io',
|
|
first_name: 'Maria',
|
|
last_name: 'Garcia',
|
|
subscription_plan: 'pro',
|
|
workflow_count: 18,
|
|
last_login_at: new Date(Date.now() - 1000 * 60 * 120).toISOString()
|
|
},
|
|
{
|
|
email: 'automation.expert@tech.com',
|
|
first_name: 'David',
|
|
last_name: 'Chen',
|
|
subscription_plan: 'pro',
|
|
workflow_count: 15,
|
|
last_login_at: new Date(Date.now() - 1000 * 60 * 45).toISOString()
|
|
},
|
|
{
|
|
email: 'workflow.master@agency.com',
|
|
first_name: 'Emma',
|
|
last_name: 'Wilson',
|
|
subscription_plan: 'enterprise',
|
|
workflow_count: 12,
|
|
last_login_at: new Date(Date.now() - 1000 * 60 * 60).toISOString()
|
|
}
|
|
],
|
|
dailyRegistrations: [
|
|
{ date: '2024-09-21', registrations: 3 },
|
|
{ date: '2024-09-22', registrations: 5 },
|
|
{ date: '2024-09-23', registrations: 2 },
|
|
{ date: '2024-09-24', registrations: 8 },
|
|
{ date: '2024-09-25', registrations: 4 },
|
|
{ date: '2024-09-26', registrations: 6 },
|
|
{ date: '2024-09-27', registrations: 7 },
|
|
{ date: '2024-09-28', registrations: 9 }
|
|
],
|
|
executionTrend: [
|
|
{ date: '2024-09-21', executions: 145, successful: 142 },
|
|
{ date: '2024-09-22', executions: 167, successful: 163 },
|
|
{ date: '2024-09-23', executions: 132, successful: 128 },
|
|
{ date: '2024-09-24', executions: 198, successful: 189 },
|
|
{ date: '2024-09-25', executions: 156, successful: 151 },
|
|
{ date: '2024-09-26', executions: 203, successful: 197 },
|
|
{ date: '2024-09-27', executions: 178, successful: 171 },
|
|
{ date: '2024-09-28', executions: 234, successful: 227 }
|
|
]
|
|
};
|
|
|
|
res.json(analytics);
|
|
} catch (error) {
|
|
console.error('Analytics error:', error);
|
|
res.status(500).json({ error: 'Failed to fetch analytics' });
|
|
}
|
|
});
|
|
|
|
// Templates/Workflows endpoint (with /api prefix)
|
|
app.get('/api/templates', (req, res) => {
|
|
try {
|
|
const templates = [
|
|
{
|
|
id: 1,
|
|
name: "Telegram to Slack Bridge",
|
|
description: "Automatically forward messages from Telegram channels to Slack channels with formatting and filtering options",
|
|
category: "Communication",
|
|
tags: ["telegram", "slack", "messaging", "automation"],
|
|
complexity: "intermediate",
|
|
estimatedTime: "15 minutes",
|
|
useCount: 234,
|
|
rating: 4.8,
|
|
author: "Aimpress Team",
|
|
thumbnail: "/templates/telegram-slack.jpg",
|
|
icon: "🔗",
|
|
gradient: "from-blue-500 to-purple-600",
|
|
workflow: {
|
|
nodes: [
|
|
{ type: "telegram-trigger", name: "Telegram Webhook" },
|
|
{ type: "filter", name: "Message Filter" },
|
|
{ type: "slack", name: "Send to Slack" }
|
|
]
|
|
},
|
|
createdAt: "2024-08-15T10:30:00Z",
|
|
updatedAt: "2024-09-20T14:22:00Z"
|
|
},
|
|
{
|
|
id: 2,
|
|
name: "Gmail to Teams Notifications",
|
|
description: "Send important email notifications from Gmail to Microsoft Teams with smart filtering and priority detection",
|
|
category: "Email & Notifications",
|
|
tags: ["gmail", "teams", "notifications", "email-filter"],
|
|
complexity: "beginner",
|
|
estimatedTime: "10 minutes",
|
|
useCount: 189,
|
|
rating: 4.6,
|
|
author: "Aimpress Team",
|
|
thumbnail: "/templates/gmail-teams.jpg",
|
|
icon: "📧",
|
|
gradient: "from-red-500 to-blue-600",
|
|
workflow: {
|
|
nodes: [
|
|
{ type: "gmail-trigger", name: "Gmail Watch" },
|
|
{ type: "condition", name: "Priority Check" },
|
|
{ type: "teams", name: "Teams Message" }
|
|
]
|
|
},
|
|
createdAt: "2024-07-22T09:15:00Z",
|
|
updatedAt: "2024-09-18T11:45:00Z"
|
|
},
|
|
{
|
|
id: 3,
|
|
name: "Customer Support Automation",
|
|
description: "Comprehensive customer support workflow that routes tickets, sends auto-responses, and escalates urgent issues",
|
|
category: "Customer Service",
|
|
tags: ["support", "automation", "tickets", "escalation"],
|
|
complexity: "advanced",
|
|
estimatedTime: "45 minutes",
|
|
useCount: 156,
|
|
rating: 4.9,
|
|
author: "Aimpress Team",
|
|
thumbnail: "/templates/customer-support.jpg",
|
|
icon: "🎧",
|
|
gradient: "from-green-500 to-teal-600",
|
|
workflow: {
|
|
nodes: [
|
|
{ type: "webhook", name: "Ticket Webhook" },
|
|
{ type: "ai-classifier", name: "Urgency Detection" },
|
|
{ type: "condition", name: "Route Decision" },
|
|
{ type: "email", name: "Auto Response" },
|
|
{ type: "slack", name: "Agent Alert" }
|
|
]
|
|
},
|
|
createdAt: "2024-06-10T16:20:00Z",
|
|
updatedAt: "2024-09-25T13:30:00Z"
|
|
},
|
|
{
|
|
id: 4,
|
|
name: "Social Media Content Sync",
|
|
description: "Automatically sync content across multiple social media platforms with custom formatting for each platform",
|
|
category: "Social Media",
|
|
tags: ["social-media", "content", "automation", "multi-platform"],
|
|
complexity: "intermediate",
|
|
estimatedTime: "30 minutes",
|
|
useCount: 298,
|
|
rating: 4.7,
|
|
author: "Aimpress Team",
|
|
thumbnail: "/templates/social-sync.jpg",
|
|
icon: "📱",
|
|
gradient: "from-pink-500 to-orange-600",
|
|
workflow: {
|
|
nodes: [
|
|
{ type: "rss-feed", name: "Content Source" },
|
|
{ type: "ai-formatter", name: "Platform Formatter" },
|
|
{ type: "twitter", name: "Twitter Post" },
|
|
{ type: "linkedin", name: "LinkedIn Post" },
|
|
{ type: "facebook", name: "Facebook Post" }
|
|
]
|
|
},
|
|
createdAt: "2024-09-01T12:00:00Z",
|
|
updatedAt: "2024-09-27T10:15:00Z"
|
|
},
|
|
{
|
|
id: 5,
|
|
name: "E-commerce Order Processing",
|
|
description: "Complete order processing pipeline with inventory checks, payment verification, and shipping notifications",
|
|
category: "E-commerce",
|
|
tags: ["orders", "inventory", "payments", "shipping"],
|
|
complexity: "advanced",
|
|
estimatedTime: "60 minutes",
|
|
useCount: 87,
|
|
rating: 4.8,
|
|
author: "Aimpress Team",
|
|
thumbnail: "/templates/ecommerce-orders.jpg",
|
|
icon: "🛒",
|
|
gradient: "from-indigo-500 to-purple-600",
|
|
workflow: {
|
|
nodes: [
|
|
{ type: "shopify-trigger", name: "New Order" },
|
|
{ type: "inventory-check", name: "Stock Verification" },
|
|
{ type: "payment-gateway", name: "Payment Check" },
|
|
{ type: "shipping-api", name: "Create Shipment" },
|
|
{ type: "email", name: "Customer Notification" }
|
|
]
|
|
},
|
|
createdAt: "2024-08-05T14:30:00Z",
|
|
updatedAt: "2024-09-22T16:45:00Z"
|
|
},
|
|
{
|
|
id: 6,
|
|
name: "Data Backup & Sync",
|
|
description: "Automated data backup solution that syncs files across multiple cloud storage providers with versioning",
|
|
category: "Data Management",
|
|
tags: ["backup", "sync", "cloud-storage", "versioning"],
|
|
complexity: "intermediate",
|
|
estimatedTime: "25 minutes",
|
|
useCount: 142,
|
|
rating: 4.5,
|
|
author: "Aimpress Team",
|
|
thumbnail: "/templates/data-backup.jpg",
|
|
icon: "☁️",
|
|
gradient: "from-cyan-500 to-blue-600",
|
|
workflow: {
|
|
nodes: [
|
|
{ type: "schedule", name: "Daily Trigger" },
|
|
{ type: "google-drive", name: "Source Files" },
|
|
{ type: "dropbox", name: "Backup to Dropbox" },
|
|
{ type: "aws-s3", name: "Archive to S3" },
|
|
{ type: "slack", name: "Status Report" }
|
|
]
|
|
},
|
|
createdAt: "2024-07-15T11:20:00Z",
|
|
updatedAt: "2024-09-19T09:30:00Z"
|
|
}
|
|
];
|
|
|
|
res.json({
|
|
templates,
|
|
categories: ["Communication", "Email & Notifications", "Customer Service", "Social Media", "E-commerce", "Data Management"],
|
|
totalCount: templates.length
|
|
});
|
|
} catch (error) {
|
|
console.error('Templates error:', error);
|
|
res.status(500).json({ error: 'Failed to fetch templates' });
|
|
}
|
|
});
|
|
|
|
// Templates endpoint (without /api prefix for frontend compatibility)
|
|
app.get('/templates', (req, res) => {
|
|
try {
|
|
const templates = [
|
|
{
|
|
id: 1,
|
|
name: "Telegram to Slack Bridge",
|
|
description: "Automatically forward messages from Telegram channels to Slack channels with formatting and filtering options",
|
|
category: "Communication",
|
|
tags: ["telegram", "slack", "messaging", "automation"],
|
|
complexity: "intermediate",
|
|
estimatedTime: "15 minutes",
|
|
useCount: 234,
|
|
rating: 4.8,
|
|
author: "Aimpress Team",
|
|
thumbnail: "/templates/telegram-slack.jpg",
|
|
icon: "🔗",
|
|
gradient: "from-blue-500 to-purple-600",
|
|
workflow: {
|
|
nodes: [
|
|
{ type: "telegram-trigger", name: "Telegram Webhook" },
|
|
{ type: "filter", name: "Message Filter" },
|
|
{ type: "slack", name: "Send to Slack" }
|
|
]
|
|
},
|
|
createdAt: "2024-08-15T10:30:00Z",
|
|
updatedAt: "2024-09-20T14:22:00Z"
|
|
},
|
|
{
|
|
id: 2,
|
|
name: "Gmail to Teams Notifications",
|
|
description: "Send important email notifications from Gmail to Microsoft Teams with smart filtering and priority detection",
|
|
category: "Email & Notifications",
|
|
tags: ["gmail", "teams", "notifications", "email-filter"],
|
|
complexity: "beginner",
|
|
estimatedTime: "10 minutes",
|
|
useCount: 189,
|
|
rating: 4.6,
|
|
author: "Aimpress Team",
|
|
thumbnail: "/templates/gmail-teams.jpg",
|
|
icon: "📧",
|
|
gradient: "from-red-500 to-blue-600",
|
|
workflow: {
|
|
nodes: [
|
|
{ type: "gmail-trigger", name: "Gmail Watch" },
|
|
{ type: "condition", name: "Priority Check" },
|
|
{ type: "teams", name: "Teams Message" }
|
|
]
|
|
},
|
|
createdAt: "2024-07-22T09:15:00Z",
|
|
updatedAt: "2024-09-18T11:45:00Z"
|
|
},
|
|
{
|
|
id: 3,
|
|
name: "Customer Support Automation",
|
|
description: "Comprehensive customer support workflow that routes tickets, sends auto-responses, and escalates urgent issues",
|
|
category: "Customer Service",
|
|
tags: ["support", "automation", "tickets", "escalation"],
|
|
complexity: "advanced",
|
|
estimatedTime: "45 minutes",
|
|
useCount: 156,
|
|
rating: 4.9,
|
|
author: "Aimpress Team",
|
|
thumbnail: "/templates/customer-support.jpg",
|
|
icon: "🎧",
|
|
gradient: "from-green-500 to-teal-600",
|
|
workflow: {
|
|
nodes: [
|
|
{ type: "webhook", name: "Ticket Webhook" },
|
|
{ type: "ai-classifier", name: "Urgency Detection" },
|
|
{ type: "condition", name: "Route Decision" },
|
|
{ type: "email", name: "Auto Response" },
|
|
{ type: "slack", name: "Agent Alert" }
|
|
]
|
|
},
|
|
createdAt: "2024-06-10T16:20:00Z",
|
|
updatedAt: "2024-09-25T13:30:00Z"
|
|
},
|
|
{
|
|
id: 4,
|
|
name: "Social Media Content Sync",
|
|
description: "Automatically sync content across multiple social media platforms with custom formatting for each platform",
|
|
category: "Social Media",
|
|
tags: ["social-media", "content", "automation", "multi-platform"],
|
|
complexity: "intermediate",
|
|
estimatedTime: "30 minutes",
|
|
useCount: 298,
|
|
rating: 4.7,
|
|
author: "Aimpress Team",
|
|
thumbnail: "/templates/social-sync.jpg",
|
|
icon: "📱",
|
|
gradient: "from-pink-500 to-orange-600",
|
|
workflow: {
|
|
nodes: [
|
|
{ type: "rss-feed", name: "Content Source" },
|
|
{ type: "ai-formatter", name: "Platform Formatter" },
|
|
{ type: "twitter", name: "Twitter Post" },
|
|
{ type: "linkedin", name: "LinkedIn Post" },
|
|
{ type: "facebook", name: "Facebook Post" }
|
|
]
|
|
},
|
|
createdAt: "2024-09-01T12:00:00Z",
|
|
updatedAt: "2024-09-27T10:15:00Z"
|
|
},
|
|
{
|
|
id: 5,
|
|
name: "E-commerce Order Processing",
|
|
description: "Complete order processing pipeline with inventory checks, payment verification, and shipping notifications",
|
|
category: "E-commerce",
|
|
tags: ["orders", "inventory", "payments", "shipping"],
|
|
complexity: "advanced",
|
|
estimatedTime: "60 minutes",
|
|
useCount: 87,
|
|
rating: 4.8,
|
|
author: "Aimpress Team",
|
|
thumbnail: "/templates/ecommerce-orders.jpg",
|
|
icon: "🛒",
|
|
gradient: "from-indigo-500 to-purple-600",
|
|
workflow: {
|
|
nodes: [
|
|
{ type: "shopify-trigger", name: "New Order" },
|
|
{ type: "inventory-check", name: "Stock Verification" },
|
|
{ type: "payment-gateway", name: "Payment Check" },
|
|
{ type: "shipping-api", name: "Create Shipment" },
|
|
{ type: "email", name: "Customer Notification" }
|
|
]
|
|
},
|
|
createdAt: "2024-08-05T14:30:00Z",
|
|
updatedAt: "2024-09-22T16:45:00Z"
|
|
},
|
|
{
|
|
id: 6,
|
|
name: "Data Backup & Sync",
|
|
description: "Automated data backup solution that syncs files across multiple cloud storage providers with versioning",
|
|
category: "Data Management",
|
|
tags: ["backup", "sync", "cloud-storage", "versioning"],
|
|
complexity: "intermediate",
|
|
estimatedTime: "25 minutes",
|
|
useCount: 142,
|
|
rating: 4.5,
|
|
author: "Aimpress Team",
|
|
thumbnail: "/templates/data-backup.jpg",
|
|
icon: "☁️",
|
|
gradient: "from-cyan-500 to-blue-600",
|
|
workflow: {
|
|
nodes: [
|
|
{ type: "schedule", name: "Daily Trigger" },
|
|
{ type: "google-drive", name: "Source Files" },
|
|
{ type: "dropbox", name: "Backup to Dropbox" },
|
|
{ type: "aws-s3", name: "Archive to S3" },
|
|
{ type: "slack", name: "Status Report" }
|
|
]
|
|
},
|
|
createdAt: "2024-07-15T11:20:00Z",
|
|
updatedAt: "2024-09-19T09:30:00Z"
|
|
}
|
|
];
|
|
|
|
res.json({
|
|
templates,
|
|
categories: ["Communication", "Email & Notifications", "Customer Service", "Social Media", "E-commerce", "Data Management"],
|
|
totalCount: templates.length
|
|
});
|
|
} catch (error) {
|
|
console.error('Templates error:', error);
|
|
res.status(500).json({ error: 'Failed to fetch templates' });
|
|
}
|
|
});
|
|
|
|
// Template installation endpoint
|
|
app.post('/templates/:templateId/install', (req, res) => {
|
|
try {
|
|
const { templateId } = req.params;
|
|
const { workflow_name } = req.body;
|
|
|
|
console.log(`Installing template ${templateId} with name: ${workflow_name}`);
|
|
|
|
// Mock successful installation
|
|
res.json({
|
|
success: true,
|
|
message: 'Template installed successfully',
|
|
workflow: {
|
|
id: `workflow_${Date.now()}`,
|
|
name: workflow_name,
|
|
template_id: templateId,
|
|
status: 'active',
|
|
created_at: new Date().toISOString()
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.error('Template installation error:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
error: 'Failed to install template'
|
|
});
|
|
}
|
|
});
|
|
|
|
// Admin Users endpoint
|
|
app.get('/admin/users', (req, res) => {
|
|
try {
|
|
const mockUsers = [
|
|
{
|
|
id: '1',
|
|
email: 'info@ai-impress.com',
|
|
first_name: 'Global',
|
|
last_name: 'Admin',
|
|
role: 'admin',
|
|
subscription_plan: 'enterprise',
|
|
subscription_status: 'active',
|
|
is_verified: true,
|
|
last_login_at: new Date(Date.now() - 1000 * 60 * 10).toISOString(),
|
|
created_at: new Date('2024-01-01').toISOString(),
|
|
workflow_count: 5
|
|
},
|
|
{
|
|
id: '2',
|
|
email: 'john.doe@example.com',
|
|
first_name: 'John',
|
|
last_name: 'Doe',
|
|
role: 'pro',
|
|
subscription_plan: 'pro',
|
|
subscription_status: 'active',
|
|
is_verified: true,
|
|
last_login_at: new Date(Date.now() - 1000 * 60 * 60).toISOString(),
|
|
created_at: new Date('2024-02-15').toISOString(),
|
|
workflow_count: 8
|
|
},
|
|
{
|
|
id: '3',
|
|
email: 'jane.smith@company.com',
|
|
first_name: 'Jane',
|
|
last_name: 'Smith',
|
|
role: 'free',
|
|
subscription_plan: 'free',
|
|
subscription_status: 'active',
|
|
is_verified: true,
|
|
last_login_at: new Date(Date.now() - 1000 * 60 * 30).toISOString(),
|
|
created_at: new Date('2024-03-10').toISOString(),
|
|
workflow_count: 3
|
|
},
|
|
{
|
|
id: '4',
|
|
email: 'enterprise@bigcorp.com',
|
|
first_name: 'Robert',
|
|
last_name: 'Johnson',
|
|
role: 'enterprise',
|
|
subscription_plan: 'enterprise',
|
|
subscription_status: 'active',
|
|
is_verified: true,
|
|
last_login_at: new Date(Date.now() - 1000 * 60 * 120).toISOString(),
|
|
created_at: new Date('2024-01-20').toISOString(),
|
|
workflow_count: 25
|
|
}
|
|
];
|
|
|
|
res.json({
|
|
users: mockUsers,
|
|
pagination: {
|
|
currentPage: 1,
|
|
totalPages: 1,
|
|
totalUsers: mockUsers.length,
|
|
limit: 20
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.error('Users error:', error);
|
|
res.status(500).json({ error: 'Failed to fetch users' });
|
|
}
|
|
});
|
|
|
|
// Update user role endpoint
|
|
app.patch('/admin/users/:userId/role', (req, res) => {
|
|
try {
|
|
const { userId } = req.params;
|
|
const { role, subscription_plan } = req.body;
|
|
|
|
console.log(`Updating user ${userId}: role=${role}, plan=${subscription_plan}`);
|
|
|
|
// Mock successful update
|
|
res.json({
|
|
id: userId,
|
|
email: 'user@example.com',
|
|
role,
|
|
subscription_plan
|
|
});
|
|
} catch (error) {
|
|
console.error('Update user role error:', error);
|
|
res.status(500).json({ error: 'Failed to update user role' });
|
|
}
|
|
});
|
|
|
|
app.listen(PORT, () => {
|
|
console.log(`Server running on port ${PORT}`);
|
|
});
|
|
|
|
export default app; |