All checks were successful
Build Frontend / Build Frontend (push) Successful in 9s
- Added websocket.url to backend config - Updated /api/config/public endpoint to return WebSocket URL - Frontend now fetches WS URL from backend config API - Falls back to environment variable or auto-generated URL - Add WS_URL to backend .env: wss://api.turbotrades.dev/ws
225 lines
6.6 KiB
JavaScript
225 lines
6.6 KiB
JavaScript
import SiteConfig from "../models/SiteConfig.js";
|
|
import { config as appConfig } from "../config/index.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,
|
|
},
|
|
|
|
// WebSocket URL
|
|
websocket: {
|
|
url: appConfig.websocket.url,
|
|
},
|
|
|
|
// 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,
|
|
});
|
|
}
|
|
});
|
|
}
|