Initial commit: MOPC platform with Docker deployment setup

Full Next.js 15 platform with tRPC, Prisma, PostgreSQL, NextAuth.
Includes production Dockerfile (multi-stage, port 7600), docker-compose
with registry-based image pull, Gitea Actions CI workflow, nginx config
for portal.monaco-opc.com, deployment scripts, and DEPLOYMENT.md guide.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-30 13:41:32 +01:00
commit a606292aaa
290 changed files with 70691 additions and 0 deletions

59
src/lib/rate-limit.ts Normal file
View File

@@ -0,0 +1,59 @@
/**
* Simple in-memory rate limiter using fixed window approach.
* Tracks request counts per key (typically IP) within time windows.
*
* For production with multiple instances, replace with Redis-based solution.
*/
type RateLimitEntry = {
count: number
resetAt: number
}
const store = new Map<string, RateLimitEntry>()
export type RateLimitResult = {
success: boolean
remaining: number
resetAt: number
}
/**
* Check rate limit for a given key.
* @param key - Identifier (e.g., IP address)
* @param limit - Max requests per window
* @param windowMs - Window size in milliseconds
*/
export function checkRateLimit(
key: string,
limit: number,
windowMs: number
): RateLimitResult {
const now = Date.now()
const entry = store.get(key)
if (!entry || now > entry.resetAt) {
const resetAt = now + windowMs
store.set(key, { count: 1, resetAt })
return { success: true, remaining: limit - 1, resetAt }
}
if (entry.count >= limit) {
return { success: false, remaining: 0, resetAt: entry.resetAt }
}
entry.count++
return { success: true, remaining: limit - entry.count, resetAt: entry.resetAt }
}
// Clean up stale entries every 5 minutes to prevent memory leaks
if (typeof setInterval !== 'undefined') {
setInterval(() => {
const now = Date.now()
for (const [key, entry] of store) {
if (now > entry.resetAt) {
store.delete(key)
}
}
}, 5 * 60 * 1000).unref?.()
}