✨ 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>
107 lines
No EOL
3.1 KiB
TypeScript
107 lines
No EOL
3.1 KiB
TypeScript
import { Response } from 'express';
|
|
import { query } from '../utils/db';
|
|
import { AuthRequest } from '../middleware/auth';
|
|
|
|
export const getIntegrations = async (req: AuthRequest, res: Response) => {
|
|
try {
|
|
const result = await query(
|
|
`SELECT id, provider, account_name, account_email, is_active, created_at, updated_at
|
|
FROM integrations WHERE user_id = $1 ORDER BY provider`,
|
|
[req.user?.id]
|
|
);
|
|
|
|
res.json({
|
|
success: true,
|
|
integrations: result.rows
|
|
});
|
|
} catch (error) {
|
|
console.error('Get integrations error:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: 'Internal server error'
|
|
});
|
|
}
|
|
};
|
|
|
|
export const connectIntegration = async (req: AuthRequest, res: Response) => {
|
|
try {
|
|
const { provider } = req.params;
|
|
const { access_token, refresh_token, account_name, account_email, scopes } = req.body;
|
|
|
|
if (!access_token) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: 'Access token is required'
|
|
});
|
|
}
|
|
|
|
const existing = await query(
|
|
'SELECT id FROM integrations WHERE user_id = $1 AND provider = $2',
|
|
[req.user?.id, provider]
|
|
);
|
|
|
|
if (existing.rows.length > 0) {
|
|
const result = await query(
|
|
`UPDATE integrations SET access_token = $1, refresh_token = $2, account_name = $3,
|
|
account_email = $4, scopes = $5, is_active = true, updated_at = CURRENT_TIMESTAMP
|
|
WHERE user_id = $6 AND provider = $7
|
|
RETURNING id, provider, account_name, account_email, is_active`,
|
|
[access_token, refresh_token, account_name, account_email, scopes, req.user?.id, provider]
|
|
);
|
|
|
|
return res.json({
|
|
success: true,
|
|
message: 'Integration updated successfully',
|
|
integration: result.rows[0]
|
|
});
|
|
}
|
|
|
|
const result = await query(
|
|
`INSERT INTO integrations (user_id, provider, access_token, refresh_token, account_name, account_email, scopes)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
RETURNING id, provider, account_name, account_email, is_active, created_at`,
|
|
[req.user?.id, provider, access_token, refresh_token, account_name, account_email, scopes]
|
|
);
|
|
|
|
res.status(201).json({
|
|
success: true,
|
|
message: 'Integration connected successfully',
|
|
integration: result.rows[0]
|
|
});
|
|
} catch (error) {
|
|
console.error('Connect integration error:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: 'Internal server error'
|
|
});
|
|
}
|
|
};
|
|
|
|
export const disconnectIntegration = async (req: AuthRequest, res: Response) => {
|
|
try {
|
|
const { id } = req.params;
|
|
|
|
const result = await query(
|
|
'DELETE FROM integrations WHERE id = $1 AND user_id = $2 RETURNING id',
|
|
[id, req.user?.id]
|
|
);
|
|
|
|
if (result.rows.length === 0) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: 'Integration not found'
|
|
});
|
|
}
|
|
|
|
res.json({
|
|
success: true,
|
|
message: 'Integration disconnected successfully'
|
|
});
|
|
} catch (error) {
|
|
console.error('Disconnect integration error:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: 'Internal server error'
|
|
});
|
|
}
|
|
}; |