coldown fix
This commit is contained in:
142
server/routes.ts
142
server/routes.ts
@@ -6,6 +6,17 @@ import { insertPixelSchema, insertUserCooldownSchema, type WSMessage } from "@sh
|
||||
import { CanvasExporter } from "./export";
|
||||
import { config } from "./config";
|
||||
|
||||
// Admin authentication middleware
|
||||
function requireAdmin(req: Request, res: Response, next: NextFunction) {
|
||||
const adminKey = req.headers['x-admin-key'] || req.body.adminKey;
|
||||
|
||||
if (!adminKey || adminKey !== config.adminKey) {
|
||||
return res.status(401).json({ message: "Admin access required" });
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
// Authentication middleware
|
||||
function requireAuth(req: Request, res: Response, next: NextFunction) {
|
||||
if (!config.enableKeycloak) {
|
||||
@@ -99,6 +110,48 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
||||
}
|
||||
});
|
||||
|
||||
// Canvas-Erweiterungs-Endpoint
|
||||
app.post("/api/config/expand", async (req, res) => {
|
||||
try {
|
||||
const { canvasWidth, canvasHeight } = req.body;
|
||||
|
||||
if (!canvasWidth || !canvasHeight || canvasWidth < 1 || canvasHeight < 1) {
|
||||
return res.status(400).json({ message: "Invalid canvas dimensions" });
|
||||
}
|
||||
|
||||
const currentConfig = await storage.getCanvasConfig();
|
||||
|
||||
// Erlaube nur Erweiterung, nicht Verkleinerung
|
||||
if (canvasWidth < currentConfig.canvasWidth || canvasHeight < currentConfig.canvasHeight) {
|
||||
return res.status(400).json({
|
||||
message: "Canvas kann nur erweitert werden, nicht verkleinert",
|
||||
current: { width: currentConfig.canvasWidth, height: currentConfig.canvasHeight }
|
||||
});
|
||||
}
|
||||
|
||||
// Für SQLite Storage: Verwende spezielle expandCanvas Methode
|
||||
if ('expandCanvas' in storage && typeof storage.expandCanvas === 'function') {
|
||||
await (storage as any).expandCanvas(canvasWidth, canvasHeight);
|
||||
} else {
|
||||
// Fallback für Memory Storage
|
||||
await storage.updateCanvasConfig({
|
||||
canvasWidth,
|
||||
canvasHeight,
|
||||
defaultCooldown: currentConfig.defaultCooldown,
|
||||
enableAutomaticEvents: currentConfig.enableAutomaticEvents,
|
||||
eventDuration: currentConfig.eventDuration,
|
||||
eventInterval: currentConfig.eventInterval
|
||||
});
|
||||
}
|
||||
|
||||
const updatedConfig = await storage.getCanvasConfig();
|
||||
res.json(updatedConfig);
|
||||
} catch (error) {
|
||||
console.error("Failed to expand canvas:", error);
|
||||
res.status(500).json({ message: "Failed to expand canvas" });
|
||||
}
|
||||
});
|
||||
|
||||
// Config is now read-only from file
|
||||
// Remove the POST endpoint for config updates
|
||||
|
||||
@@ -121,11 +174,17 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
||||
// Check cooldown unless events are enabled
|
||||
if (!config.enableAutomaticEvents) {
|
||||
const cooldown = await storage.getUserCooldown(userInfo.userId);
|
||||
if (cooldown && cooldown.cooldownEnds > new Date()) {
|
||||
return res.status(429).json({ message: "Cooldown active" });
|
||||
const now = new Date();
|
||||
|
||||
if (cooldown && cooldown.cooldownEnds > now) {
|
||||
const remaining = Math.ceil((cooldown.cooldownEnds.getTime() - now.getTime()) / 1000);
|
||||
return res.status(429).json({
|
||||
message: "Cooldown active",
|
||||
remainingSeconds: remaining
|
||||
});
|
||||
}
|
||||
|
||||
// Set new cooldown
|
||||
// Set new cooldown - immer setzen, auch wenn kein vorheriger existierte
|
||||
const cooldownEnd = new Date(Date.now() + (config.defaultCooldown * 1000));
|
||||
await storage.setUserCooldown({
|
||||
userId: userInfo.userId,
|
||||
@@ -226,6 +285,83 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
||||
});
|
||||
});
|
||||
|
||||
// Admin Routes
|
||||
app.post("/api/admin/auth", (req, res) => {
|
||||
const { adminKey } = req.body;
|
||||
|
||||
if (adminKey === config.adminKey) {
|
||||
res.json({ success: true });
|
||||
} else {
|
||||
res.status(401).json({ message: "Invalid admin key" });
|
||||
}
|
||||
});
|
||||
|
||||
app.get("/api/admin/stats", requireAdmin, async (req, res) => {
|
||||
try {
|
||||
const pixels = await storage.getAllPixels();
|
||||
const uniqueUsers = new Set(pixels.map(p => p.userId)).size;
|
||||
|
||||
res.json({
|
||||
totalPixels: pixels.length,
|
||||
uniqueUsers,
|
||||
lastActivity: pixels.length > 0 ? pixels[pixels.length - 1].createdAt : null
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ message: "Failed to fetch admin stats" });
|
||||
}
|
||||
});
|
||||
|
||||
app.delete("/api/admin/pixels/:id", requireAdmin, async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
|
||||
if ('deletePixel' in storage && typeof storage.deletePixel === 'function') {
|
||||
await (storage as any).deletePixel(id);
|
||||
|
||||
// Broadcast pixel deletion
|
||||
broadcast({
|
||||
type: "pixel_deleted",
|
||||
data: { pixelId: id },
|
||||
});
|
||||
|
||||
res.json({ success: true });
|
||||
} else {
|
||||
res.status(501).json({ message: "Pixel deletion not supported by current storage" });
|
||||
}
|
||||
} catch (error) {
|
||||
res.status(500).json({ message: "Failed to delete pixel" });
|
||||
}
|
||||
});
|
||||
|
||||
app.delete("/api/admin/canvas", requireAdmin, async (req, res) => {
|
||||
try {
|
||||
if ('clearCanvas' in storage && typeof storage.clearCanvas === 'function') {
|
||||
await (storage as any).clearCanvas();
|
||||
|
||||
// Broadcast canvas clear
|
||||
broadcast({
|
||||
type: "canvas_cleared",
|
||||
data: {},
|
||||
});
|
||||
|
||||
res.json({ success: true });
|
||||
} else {
|
||||
res.status(501).json({ message: "Canvas clearing not supported by current storage" });
|
||||
}
|
||||
} catch (error) {
|
||||
res.status(500).json({ message: "Failed to clear canvas" });
|
||||
}
|
||||
});
|
||||
|
||||
app.post("/api/admin/export", requireAdmin, async (req, res) => {
|
||||
try {
|
||||
const filename = await exporter.exportCanvas();
|
||||
res.json({ filename, success: true });
|
||||
} catch (error) {
|
||||
res.status(500).json({ message: "Failed to export canvas" });
|
||||
}
|
||||
});
|
||||
|
||||
// Keep connections alive with ping/pong
|
||||
const pingInterval = setInterval(() => {
|
||||
connectedUsers.forEach(ws => {
|
||||
|
||||
Reference in New Issue
Block a user