backend changes
This commit is contained in:
parent
aaf7065431
commit
9c453bfe07
1
Jenkinsfile
vendored
1
Jenkinsfile
vendored
@ -196,6 +196,7 @@ pipeline {
|
||||
docker compose ps
|
||||
'
|
||||
"""
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ services:
|
||||
container_name: pipeline_postgres
|
||||
environment:
|
||||
POSTGRES_USER: pipeline_admin
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
POSTGRES_PASSWORD: secure_pipeline_2024
|
||||
POSTGRES_DB: dev_pipeline
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
@ -26,7 +26,7 @@ services:
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: pipeline_redis
|
||||
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
|
||||
command: redis-server --appendonly yes --requirepass redis_secure_2024
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
ports:
|
||||
@ -45,8 +45,8 @@ services:
|
||||
image: mongo:7
|
||||
container_name: pipeline_mongodb
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: pipeline_user
|
||||
MONGO_INITDB_ROOT_PASSWORD: ${MONGODB_PASSWORD}
|
||||
MONGO_INITDB_ROOT_USERNAME: pipeline_admin
|
||||
MONGO_INITDB_ROOT_PASSWORD: mongo_secure_2024
|
||||
volumes:
|
||||
- mongodb_data:/data/db
|
||||
ports:
|
||||
@ -62,7 +62,7 @@ services:
|
||||
container_name: pipeline_rabbitmq
|
||||
environment:
|
||||
RABBITMQ_DEFAULT_USER: pipeline_admin
|
||||
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD}
|
||||
RABBITMQ_DEFAULT_PASS: rabbit_secure_2024
|
||||
volumes:
|
||||
- rabbitmq_data:/var/lib/rabbitmq
|
||||
- rabbitmq_logs:/var/log/rabbitmq
|
||||
@ -93,12 +93,12 @@ services:
|
||||
- POSTGRES_PORT=5432
|
||||
- POSTGRES_DB=dev_pipeline
|
||||
- POSTGRES_USER=pipeline_admin
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- POSTGRES_PASSWORD=secure_pipeline_2024
|
||||
- REDIS_HOST=redis
|
||||
- REDIS_PORT=6379
|
||||
- REDIS_PASSWORD=${REDIS_PASSWORD}
|
||||
- REDIS_PASSWORD=redis_secure_2024
|
||||
- NODE_ENV=development
|
||||
- DATABASE_URL=postgresql://pipeline_admin:${POSTGRES_PASSWORD}@postgres:5432/dev_pipeline
|
||||
- DATABASE_URL=postgresql://pipeline_admin:secure_pipeline_2024@postgres:5432/dev_pipeline
|
||||
entrypoint: ["/bin/sh", "-c", "chmod +x ./scripts/migrate-all.sh && ./scripts/migrate-all.sh"]
|
||||
depends_on:
|
||||
postgres:
|
||||
@ -240,20 +240,20 @@ services:
|
||||
- POSTGRES_PORT=5432
|
||||
- POSTGRES_DB=dev_pipeline
|
||||
- POSTGRES_USER=pipeline_admin
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- POSTGRES_PASSWORD=secure_pipeline_2024
|
||||
# Cache and message queue
|
||||
- REDIS_HOST=redis
|
||||
- REDIS_PORT=6379
|
||||
- REDIS_PASSWORD=${REDIS_PASSWORD}
|
||||
- REDIS_PASSWORD=redis_secure_2024
|
||||
- RABBITMQ_HOST=rabbitmq
|
||||
- RABBITMQ_PORT=5672
|
||||
- RABBITMQ_USER=pipeline_admin
|
||||
- RABBITMQ_PASSWORD=${RABBITMQ_PASSWORD}
|
||||
- RABBITMQ_PASSWORD=rabbit_secure_2024
|
||||
# JWT configuration
|
||||
- JWT_ACCESS_SECRET=access-secret-key-2024-tech4biz-secure_pipeline_2024
|
||||
- JWT_SECRET=access-secret-key-2024-tech4biz-secure_pipeline_2024
|
||||
# - JWT_ACCESS_SECRET=access-secret-key-2024-tech4biz-${POSTGRES_PASSWORD}
|
||||
# - JWT_REFRESH_SECRET=refresh-secret-key-2024-tech4biz-${POSTGRES_PASSWORD}
|
||||
- JWT_SECRET=ultra_secure_jwt_secret_2024
|
||||
# - JWT_ACCESS_SECRET=access-secret-key-2024-tech4biz-secure_pipeline_2024
|
||||
# - JWT_REFRESH_SECRET=refresh-secret-key-2024-tech4biz-secure_pipeline_2024
|
||||
# Service URLs
|
||||
- USER_AUTH_URL=http://user-auth:8011
|
||||
- TEMPLATE_MANAGER_URL=http://template-manager:8009
|
||||
@ -299,10 +299,10 @@ services:
|
||||
- POSTGRES_PORT=5432
|
||||
- POSTGRES_DB=dev_pipeline
|
||||
- POSTGRES_USER=pipeline_admin
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- POSTGRES_PASSWORD=secure_pipeline_2024
|
||||
- REDIS_HOST=redis
|
||||
- REDIS_PORT=6379
|
||||
- REDIS_PASSWORD=${REDIS_PASSWORD}
|
||||
- REDIS_PASSWORD=redis_secure_2024
|
||||
- MONGODB_HOST=mongodb
|
||||
- MONGODB_PORT=27017
|
||||
- NEO4J_URI=bolt://neo4j:7687
|
||||
@ -310,7 +310,7 @@ services:
|
||||
- NEO4J_PASSWORD=password
|
||||
- CHROMA_HOST=chromadb
|
||||
- CHROMA_PORT=8000
|
||||
- REDIS_URL=redis://redis:6379
|
||||
- REDIS_URL=redis://:redis_secure_2024@redis:6379
|
||||
networks:
|
||||
- pipeline_network
|
||||
depends_on:
|
||||
@ -333,10 +333,10 @@ services:
|
||||
- POSTGRES_PORT=5432
|
||||
- POSTGRES_DB=dev_pipeline
|
||||
- POSTGRES_USER=pipeline_admin
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- POSTGRES_PASSWORD=secure_pipeline_2024
|
||||
- REDIS_HOST=redis
|
||||
- REDIS_PORT=6379
|
||||
- REDIS_PASSWORD=${REDIS_PASSWORD}
|
||||
- REDIS_PASSWORD=redis_secure_2024
|
||||
networks:
|
||||
- pipeline_network
|
||||
depends_on:
|
||||
@ -355,13 +355,13 @@ services:
|
||||
environment:
|
||||
- PORT=8003
|
||||
- HOST=0.0.0.0
|
||||
- CLAUDE_API_KEY=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
|
||||
- ANTHROPIC_API_KEY=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
|
||||
- CLAUDE_API_KEY=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
|
||||
- ANTHROPIC_API_KEY=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
|
||||
- POSTGRES_HOST=postgres
|
||||
- POSTGRES_PORT=5432
|
||||
- POSTGRES_DB=dev_pipeline
|
||||
- POSTGRES_USER=pipeline_admin
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- POSTGRES_PASSWORD=secure_pipeline_2024
|
||||
- MONGODB_HOST=mongodb
|
||||
- MONGODB_PORT=27017
|
||||
networks:
|
||||
@ -391,13 +391,13 @@ services:
|
||||
- POSTGRES_PORT=5432
|
||||
- POSTGRES_DB=dev_pipeline
|
||||
- POSTGRES_USER=pipeline_admin
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- POSTGRES_PASSWORD=secure_pipeline_2024
|
||||
- MONGODB_HOST=mongodb
|
||||
- MONGODB_PORT=27017
|
||||
- REDIS_HOST=redis
|
||||
- REDIS_PORT=6379
|
||||
- REDIS_PASSWORD=${REDIS_PASSWORD}
|
||||
- CLAUDE_API_KEY=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
|
||||
- REDIS_PASSWORD=redis_secure_2024
|
||||
- CLAUDE_API_KEY=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
|
||||
- OPENAI_API_KEY=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
|
||||
# - NEO4J_URI=bolt://neo4j:7687
|
||||
# - NEO4J_USER=neo4j
|
||||
@ -440,10 +440,10 @@ services:
|
||||
- POSTGRES_PORT=5432
|
||||
- POSTGRES_DB=dev_pipeline
|
||||
- POSTGRES_USER=pipeline_admin
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- POSTGRES_PASSWORD=secure_pipeline_2024
|
||||
- REDIS_HOST=redis
|
||||
- REDIS_PORT=6379
|
||||
- REDIS_PASSWORD=${REDIS_PASSWORD}
|
||||
- REDIS_PASSWORD=redis_secure_2024
|
||||
networks:
|
||||
- pipeline_network
|
||||
depends_on:
|
||||
@ -464,13 +464,13 @@ services:
|
||||
- POSTGRES_PORT=5432
|
||||
- POSTGRES_DB=dev_pipeline
|
||||
- POSTGRES_USER=pipeline_admin
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- POSTGRES_PASSWORD=secure_pipeline_2024
|
||||
- MONGODB_HOST=mongodb
|
||||
- MONGODB_PORT=27017
|
||||
- RABBITMQ_HOST=rabbitmq
|
||||
- RABBITMQ_PORT=5672
|
||||
- RABBITMQ_USER=pipeline_admin
|
||||
- RABBITMQ_PASSWORD=${RABBITMQ_PASSWORD}
|
||||
- RABBITMQ_PASSWORD=rabbit_secure_2024
|
||||
networks:
|
||||
- pipeline_network
|
||||
depends_on:
|
||||
@ -496,25 +496,25 @@ services:
|
||||
- POSTGRES_PORT=5432
|
||||
- POSTGRES_DB=dev_pipeline
|
||||
- POSTGRES_USER=pipeline_admin
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- POSTGRES_PASSWORD=secure_pipeline_2024
|
||||
- REDIS_HOST=redis
|
||||
- REDIS_PORT=6379
|
||||
- REDIS_PASSWORD=${REDIS_PASSWORD}
|
||||
- REDIS_PASSWORD=redis_secure_2024
|
||||
- JWT_ACCESS_SECRET=access-secret-key-2024-tech4biz-secure_pipeline_2024
|
||||
- JWT_REFRESH_SECRET=refresh-secret-key-2024-tech4biz-${POSTGRES_PASSWORD}
|
||||
- JWT_REFRESH_SECRET=refresh-secret-key-2024-tech4biz-secure_pipeline_2024
|
||||
- JWT_ACCESS_EXPIRY=24h
|
||||
- JWT_ADMIN_ACCESS_EXPIRY=7d
|
||||
- JWT_REFRESH_EXPIRY=7d
|
||||
- FRONTEND_URL=*
|
||||
# Email Configuration
|
||||
- SMTP_HOST=${SMTP_HOST:-smtp.gmail.com}
|
||||
- SMTP_PORT=${SMTP_PORT:-587}
|
||||
- SMTP_SECURE=${SMTP_SECURE:-false}
|
||||
- SMTP_USER=${SMTP_USER:-frontendtechbiz@gmail.com}
|
||||
- SMTP_PASS=${SMTP_PASS:-oidhhjeasgzbqptq}
|
||||
- SMTP_FROM=${SMTP_FROM:-frontendtechbiz@gmail.com}
|
||||
- GMAIL_USER=${GMAIL_USER:-frontendtechbiz@gmail.com}
|
||||
- GMAIL_APP_PASSWORD=${GMAIL_APP_PASSWORD:-oidhhjeasgzbqptq}
|
||||
- SMTP_HOST=smtp.gmail.com
|
||||
- SMTP_PORT=587
|
||||
- SMTP_SECURE=false
|
||||
- SMTP_USER=frontendtechbiz@gmail.com
|
||||
- SMTP_PASS=oidhhjeasgzbqptq
|
||||
- SMTP_FROM=frontendtechbiz@gmail.com
|
||||
- GMAIL_USER=frontendtechbiz@gmail.com
|
||||
- GMAIL_APP_PASSWORD=oidhhjeasgzbqptq
|
||||
- AUTH_PUBLIC_URL=*
|
||||
- TEMPLATE_MANAGER_URL=http://template-manager:8009
|
||||
networks:
|
||||
@ -551,10 +551,10 @@ services:
|
||||
- POSTGRES_PORT=5432
|
||||
- POSTGRES_DB=dev_pipeline
|
||||
- POSTGRES_USER=pipeline_admin
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- POSTGRES_PASSWORD=secure_pipeline_2024
|
||||
- REDIS_HOST=redis
|
||||
- REDIS_PORT=6379
|
||||
- REDIS_PASSWORD=${REDIS_PASSWORD}
|
||||
- REDIS_PASSWORD=redis_secure_2024
|
||||
- NODE_ENV=development
|
||||
- JWT_ACCESS_SECRET=access-secret-key-2024-tech4biz-secure_pipeline_2024
|
||||
networks:
|
||||
@ -584,16 +584,16 @@ services:
|
||||
environment:
|
||||
- PORT=8021
|
||||
- HOST=0.0.0.0
|
||||
- CLAUDE_API_KEY=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
|
||||
- CLAUDE_API_KEY=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
|
||||
- POSTGRES_HOST=postgres
|
||||
- POSTGRES_PORT=5432
|
||||
- POSTGRES_DB=dev_pipeline
|
||||
- POSTGRES_USER=pipeline_admin
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- POSTGRES_PASSWORD=secure_pipeline_2024
|
||||
- REDIS_HOST=redis
|
||||
- REDIS_PORT=6379
|
||||
- REDIS_PASSWORD=${REDIS_PASSWORD}
|
||||
- JWT_ACCESS_SECRET=access-secret-key-2024-tech4biz-${POSTGRES_PASSWORD}
|
||||
- REDIS_PASSWORD=redis_secure_2024
|
||||
- JWT_ACCESS_SECRET=access-secret-key-2024-tech4biz-secure_pipeline_2024
|
||||
- USER_AUTH_SERVICE_URL=http://user-auth:8011
|
||||
- FLASK_ENV=development
|
||||
networks:
|
||||
@ -622,10 +622,10 @@ services:
|
||||
- POSTGRES_PORT=5432
|
||||
- POSTGRES_DB=dev_pipeline
|
||||
- POSTGRES_USER=pipeline_admin
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- POSTGRES_PASSWORD=secure_pipeline_2024
|
||||
- REDIS_HOST=redis
|
||||
- REDIS_PORT=6379
|
||||
- REDIS_PASSWORD=${REDIS_PASSWORD}
|
||||
- REDIS_PASSWORD=redis_secure_2024
|
||||
- NODE_ENV=development
|
||||
- GITHUB_REDIRECT_URI=*
|
||||
- ATTACHED_REPOS_DIR=/tmp/attached-repos
|
||||
@ -657,9 +657,9 @@ services:
|
||||
environment:
|
||||
- PORT=8007
|
||||
- HOST=0.0.0.0
|
||||
- DATABASE_URL=postgresql://pipeline_admin:${POSTGRES_PASSWORD}@postgres:5432/dev_pipeline
|
||||
- CLAUDE_API_KEY=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
|
||||
- REDIS_URL=redis://pipeline_redis:6379
|
||||
- DATABASE_URL=postgresql://pipeline_admin:secure_pipeline_2024@postgres:5432/dev_pipeline
|
||||
- CLAUDE_API_KEY=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
|
||||
- REDIS_URL=redis://:redis_secure_2024@pipeline_redis:6379
|
||||
- SERVICE_PORT=8007
|
||||
- LOG_LEVEL=INFO
|
||||
- DEFAULT_TARGET_QUALITY=0.85
|
||||
@ -697,8 +697,8 @@ services:
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- PORT=8008
|
||||
- DATABASE_URL=postgresql://pipeline_admin:${POSTGRES_PASSWORD}@postgres:5432/dev_pipeline
|
||||
- REDIS_URL=redis://pipeline_redis:6379
|
||||
- DATABASE_URL=postgresql://pipeline_admin:secure_pipeline_2024@postgres:5432/dev_pipeline
|
||||
- REDIS_URL=redis://:redis_secure_2024@pipeline_redis:6379
|
||||
- API_GATEWAY_URL=http://pipeline_api_gateway:8000
|
||||
- CODE_GENERATOR_URL=http://pipeline_code_generator:8004
|
||||
- SELF_IMPROVING_URL=http://pipeline_self_improving_generator:8007
|
||||
@ -738,8 +738,8 @@ services:
|
||||
- "5678:5678"
|
||||
environment:
|
||||
- N8N_BASIC_AUTH_ACTIVE=true
|
||||
- N8N_BASIC_AUTH_USER=pipeline_admin
|
||||
- N8N_BASIC_AUTH_PASSWORD=pipeline_n8n_2024
|
||||
- N8N_BASIC_AUTH_USER=admin
|
||||
- N8N_BASIC_AUTH_PASSWORD=admin_n8n_2024
|
||||
- N8N_HOST=localhost
|
||||
- N8N_PORT=5678
|
||||
- N8N_PROTOCOL=http
|
||||
@ -750,7 +750,7 @@ services:
|
||||
- DB_POSTGRESDB_PORT=5432
|
||||
- DB_POSTGRESDB_DATABASE=n8n
|
||||
- DB_POSTGRESDB_USER=pipeline_admin
|
||||
- DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- DB_POSTGRESDB_PASSWORD=secure_pipeline_2024
|
||||
volumes:
|
||||
- n8n_data:/home/node/.n8n
|
||||
- ./orchestration/n8n/workflows:/home/node/.n8n/workflows
|
||||
|
||||
@ -230,8 +230,17 @@ class CustomFeature {
|
||||
const updated = await CustomFeature.update(id, updates);
|
||||
|
||||
// If approved, ensure a mirrored entry exists/updates in template_features
|
||||
// Only mirror if the template_id exists in the main templates table
|
||||
if (updated && status === 'approved') {
|
||||
try {
|
||||
// Check if template_id exists in main templates table
|
||||
const templateCheck = await database.query(
|
||||
'SELECT id FROM templates WHERE id = $1 AND is_active = true',
|
||||
[updated.template_id]
|
||||
);
|
||||
|
||||
if (templateCheck.rows.length > 0) {
|
||||
// Template exists in main templates table, safe to mirror
|
||||
const Feature = require('./feature');
|
||||
const featureId = `custom_${updated.id}`;
|
||||
const existingMirror = await Feature.getByFeatureId(updated.template_id, featureId);
|
||||
@ -243,6 +252,7 @@ class CustomFeature {
|
||||
feature_type: 'custom',
|
||||
is_default: false
|
||||
});
|
||||
console.log('✅ Updated mirrored feature in template_features for approved custom feature');
|
||||
} else {
|
||||
await Feature.create({
|
||||
template_id: updated.template_id,
|
||||
@ -255,6 +265,11 @@ class CustomFeature {
|
||||
is_default: false,
|
||||
created_by_user: true
|
||||
});
|
||||
console.log('✅ Created mirrored feature in template_features for approved custom feature');
|
||||
}
|
||||
} else {
|
||||
// Template is likely a custom template, don't mirror to template_features
|
||||
console.log('ℹ️ Custom feature approved but template_id references custom template, skipping mirror to template_features');
|
||||
}
|
||||
} catch (mirrorErr) {
|
||||
console.error('⚠️ Failed to mirror approved custom feature into template_features:', mirrorErr.message);
|
||||
|
||||
@ -48,6 +48,206 @@ const requireAdmin = (req, res, next) => {
|
||||
// Apply admin middleware to all routes
|
||||
router.use(requireAdmin);
|
||||
|
||||
// GET /api/admin/custom-features - Proxy to existing custom features functionality
|
||||
router.get('/custom-features', async (req, res) => {
|
||||
try {
|
||||
const limit = parseInt(req.query.limit) || 50;
|
||||
const offset = parseInt(req.query.offset) || 0;
|
||||
const status = req.query.status;
|
||||
|
||||
console.log(`Admin: Fetching custom features (status: ${status || 'all'}, limit: ${limit}, offset: ${offset})`);
|
||||
|
||||
let features;
|
||||
if (status) {
|
||||
features = await CustomFeature.getFeaturesByStatus(status, limit, offset);
|
||||
} else {
|
||||
features = await CustomFeature.getAllFeatures(limit, offset);
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: features,
|
||||
count: features.length,
|
||||
message: `Found ${features.length} custom features`
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error fetching custom features:', error.message);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: 'Failed to fetch custom features',
|
||||
message: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// POST /api/admin/custom-features/:id/review - Review custom feature
|
||||
router.post('/custom-features/:id/review', async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const { status, admin_notes, admin_reviewed_by } = req.body;
|
||||
|
||||
const validStatuses = ['approved', 'rejected', 'duplicate'];
|
||||
if (!validStatuses.includes(status)) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: 'Invalid status',
|
||||
message: `Status must be one of: ${validStatuses.join(', ')}`
|
||||
});
|
||||
}
|
||||
|
||||
console.log(`🔍 Admin: Reviewing custom feature ${id} with status: ${status}`);
|
||||
|
||||
const feature = await CustomFeature.getById(id);
|
||||
if (!feature) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
error: 'Feature not found',
|
||||
message: 'The specified feature does not exist'
|
||||
});
|
||||
}
|
||||
|
||||
const reviewData = {
|
||||
status,
|
||||
admin_notes,
|
||||
admin_reviewed_by: admin_reviewed_by || req.user.id
|
||||
};
|
||||
|
||||
const updatedFeature = await CustomFeature.reviewFeature(id, reviewData);
|
||||
|
||||
try {
|
||||
await AdminNotification.notifyFeatureReviewed(id, feature.name, status);
|
||||
} catch (notifError) {
|
||||
console.warn('⚠️ Failed to create notification:', notifError.message);
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: updatedFeature,
|
||||
message: `Feature "${feature.name}" has been ${status}`
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('❌ Error reviewing custom feature:', error.message);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: 'Failed to review custom feature',
|
||||
message: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/admin/custom-templates - Get custom templates
|
||||
router.get('/custom-templates', async (req, res) => {
|
||||
try {
|
||||
const limit = parseInt(req.query.limit) || 50;
|
||||
const offset = parseInt(req.query.offset) || 0;
|
||||
const status = req.query.status;
|
||||
|
||||
console.log(`Admin: Fetching custom templates (status: ${status || 'all'}, limit: ${limit}, offset: ${offset})`);
|
||||
|
||||
let templates;
|
||||
if (status) {
|
||||
templates = await CustomTemplate.getTemplatesByStatus(status, limit, offset);
|
||||
} else {
|
||||
templates = await CustomTemplate.getAllTemplates(limit, offset);
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: templates,
|
||||
count: templates.length,
|
||||
message: `Found ${templates.length} custom templates`
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error fetching custom templates:', error.message);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: 'Failed to fetch custom templates',
|
||||
message: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// POST /api/admin/custom-templates/:id/review - Review custom template
|
||||
router.post('/custom-templates/:id/review', async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const { status, admin_notes, admin_reviewed_by } = req.body;
|
||||
|
||||
const validStatuses = ['approved', 'rejected', 'duplicate'];
|
||||
if (!validStatuses.includes(status)) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: 'Invalid status',
|
||||
message: `Status must be one of: ${validStatuses.join(', ')}`
|
||||
});
|
||||
}
|
||||
|
||||
console.log(`🔍 Admin: Reviewing custom template ${id} with status: ${status}`);
|
||||
|
||||
const template = await CustomTemplate.getById(id);
|
||||
if (!template) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
error: 'Template not found',
|
||||
message: 'The specified template does not exist'
|
||||
});
|
||||
}
|
||||
|
||||
const reviewData = {
|
||||
status,
|
||||
admin_notes,
|
||||
admin_reviewed_by: admin_reviewed_by || req.user.id
|
||||
};
|
||||
|
||||
const updatedTemplate = await CustomTemplate.reviewTemplate(id, reviewData);
|
||||
|
||||
try {
|
||||
await AdminNotification.notifyTemplateReviewed(id, template.title, status);
|
||||
} catch (notifError) {
|
||||
console.warn('⚠️ Failed to create notification:', notifError.message);
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: updatedTemplate,
|
||||
message: `Template "${template.title}" has been ${status}`
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('❌ Error reviewing custom template:', error.message);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: 'Failed to review custom template',
|
||||
message: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/admin/templates/stats - Get template statistics
|
||||
router.get('/templates/stats', async (req, res) => {
|
||||
try {
|
||||
console.log('📊 Admin: Fetching template statistics...');
|
||||
|
||||
const stats = await CustomTemplate.getTemplateStats();
|
||||
const notificationCounts = await AdminNotification.getCounts();
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
templates: stats,
|
||||
notifications: notificationCounts
|
||||
},
|
||||
message: 'Template statistics retrieved successfully'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('❌ Error fetching template stats:', error.message);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: 'Failed to fetch template statistics',
|
||||
message: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/admin/features/pending - Get pending features for review
|
||||
router.get('/features/pending', async (req, res) => {
|
||||
try {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user