Files
TurboTrades/routes/config.js
iDefineHD 63c578b0ae feat: Complete admin panel implementation
- Add user management system with all CRUD operations
- Add promotion statistics dashboard with export
- Simplify Trading & Market settings UI
- Fix promotion schema (dates now optional)
- Add missing API endpoints and PATCH support
- Add comprehensive documentation
- Fix critical bugs (deletePromotion, duplicate endpoints)

All features tested and production-ready.
2026-01-10 21:57:55 +00:00

219 lines
6.5 KiB
JavaScript

import SiteConfig from "../models/SiteConfig.js";
/**
* Public configuration routes
* These endpoints are accessible without authentication
* @param {FastifyInstance} fastify
* @param {Object} options
*/
export default async function configRoutes(fastify, options) {
// GET /config/public - Get public site configuration
fastify.get("/public", async (request, reply) => {
try {
const config = await SiteConfig.getConfig();
return reply.send({
success: true,
config: {
// Site status
maintenance: {
enabled: config.isMaintenanceActive(),
message: config.maintenance.message,
scheduledEnd: config.maintenance.scheduledEnd,
},
// Features
features: {
twoFactorAuth: config.features.twoFactorAuth,
emailVerification: config.features.emailVerification,
giveaways: config.features.giveaways,
affiliateProgram: config.features.affiliateProgram,
},
// Trading settings (public info only)
trading: {
enabled: config.trading.enabled,
depositEnabled: config.trading.depositEnabled,
withdrawEnabled: config.trading.withdrawEnabled,
minDeposit: config.trading.minDeposit,
minWithdraw: config.trading.minWithdraw,
withdrawFee: config.trading.withdrawFee,
},
// Market settings (public info only)
market: {
enabled: config.market.enabled,
commission: config.market.commission,
minListingPrice: config.market.minListingPrice,
maxListingPrice: config.market.maxListingPrice,
},
// Social links
social: config.social,
// Support
support: {
email: config.support.email,
liveChatEnabled: config.support.liveChatEnabled,
ticketSystemEnabled: config.support.ticketSystemEnabled,
},
// SEO
seo: config.seo,
},
});
} catch (error) {
console.error("❌ Failed to get public config:", error);
return reply.status(500).send({
success: false,
message: "Failed to retrieve configuration",
error: error.message,
});
}
});
// GET /config/announcements - Get active announcements
fastify.get("/announcements", async (request, reply) => {
try {
const config = await SiteConfig.getConfig();
const announcements = config.getActiveAnnouncements();
return reply.send({
success: true,
announcements: announcements.map((announcement) => ({
id: announcement.id,
type: announcement.type,
message: announcement.message,
dismissible: announcement.dismissible,
createdAt: announcement.createdAt,
})),
});
} catch (error) {
console.error("❌ Failed to get announcements:", error);
return reply.status(500).send({
success: false,
message: "Failed to retrieve announcements",
error: error.message,
});
}
});
// GET /config/promotions - Get active promotions
fastify.get("/promotions", async (request, reply) => {
try {
const config = await SiteConfig.getConfig();
const promotions = config.getActivePromotions();
// Return public promo info (hide some sensitive details)
const publicPromos = promotions.map((promo) => ({
id: promo.id,
name: promo.name,
description: promo.description,
type: promo.type,
startDate: promo.startDate,
endDate: promo.endDate,
bonusPercentage: promo.bonusPercentage,
minDeposit: promo.minDeposit,
maxBonus: promo.maxBonus,
discountPercentage: promo.discountPercentage,
newUsersOnly: promo.newUsersOnly,
requiresCode: !!promo.code,
bannerImage: promo.bannerImage,
}));
return reply.send({
success: true,
promotions: publicPromos,
});
} catch (error) {
console.error("❌ Failed to get promotions:", error);
return reply.status(500).send({
success: false,
message: "Failed to retrieve promotions",
error: error.message,
});
}
});
// POST /config/validate-promo - Validate a promo code
fastify.post(
"/validate-promo",
{
schema: {
body: {
type: "object",
required: ["code"],
properties: {
code: { type: "string", minLength: 1 },
},
},
},
},
async (request, reply) => {
try {
const { code } = request.body;
const config = await SiteConfig.getConfig();
const promo = config.validatePromoCode(code);
if (!promo) {
return reply.status(404).send({
success: false,
message: "Invalid or expired promo code",
});
}
return reply.send({
success: true,
valid: true,
promotion: {
id: promo.id,
name: promo.name,
description: promo.description,
type: promo.type,
bonusPercentage: promo.bonusPercentage,
minDeposit: promo.minDeposit,
maxBonus: promo.maxBonus,
discountPercentage: promo.discountPercentage,
endDate: promo.endDate,
},
});
} catch (error) {
console.error("❌ Failed to validate promo code:", error);
return reply.status(500).send({
success: false,
message: "Failed to validate promo code",
error: error.message,
});
}
}
);
// GET /config/status - Get current site status (simple health check with maintenance info)
fastify.get("/status", async (request, reply) => {
try {
const config = await SiteConfig.getConfig();
return reply.send({
success: true,
status: "operational",
maintenance: config.isMaintenanceActive(),
services: {
trading: config.trading.enabled,
deposit: config.trading.depositEnabled,
withdraw: config.trading.withdrawEnabled,
market: config.market.enabled,
},
timestamp: new Date().toISOString(),
});
} catch (error) {
console.error("❌ Failed to get status:", error);
return reply.status(500).send({
success: false,
message: "Failed to retrieve status",
error: error.message,
});
}
});
}