feat: add basic auth to distribute credits cron jobs

This commit is contained in:
javayhu 2025-08-10 11:48:53 +08:00
parent f50f60443a
commit 78f76f35b9
3 changed files with 55 additions and 2 deletions

View File

@ -167,6 +167,12 @@ TURNSTILE_SECRET_KEY=""
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
NEXT_PUBLIC_CRISP_WEBSITE_ID="" NEXT_PUBLIC_CRISP_WEBSITE_ID=""
# -----------------------------------------------------------------------------
# Cron Jobs
# -----------------------------------------------------------------------------
CRON_JOBS_USERNAME=""
CRON_JOBS_PASSWORD=""
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# AI # AI
# https://mksaas.com/docs/ai # https://mksaas.com/docs/ai
@ -179,6 +185,13 @@ GOOGLE_GENERATIVE_AI_API_KEY=""
DEEPSEEK_API_KEY="" DEEPSEEK_API_KEY=""
OPENROUTER_API_KEY="" OPENROUTER_API_KEY=""
# -----------------------------------------------------------------------------
# Basic Authentication
# Used for protecting sensitive API endpoints like distribute-credits
# -----------------------------------------------------------------------------
BASIC_AUTH_USERNAME="admin"
BASIC_AUTH_PASSWORD=""
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Web Content Analyzer (Firecrawl) # Web Content Analyzer (Firecrawl)
# https://firecrawl.dev/ # https://firecrawl.dev/

View File

@ -1,10 +1,50 @@
import { distributeCreditsToAllUsers } from '@/credits/credits'; import { distributeCreditsToAllUsers } from '@/credits/credits';
import { NextResponse } from 'next/server'; import { NextResponse } from 'next/server';
// Basic authentication middleware
function validateBasicAuth(request: Request): boolean {
const authHeader = request.headers.get('authorization');
if (!authHeader || !authHeader.startsWith('Basic ')) {
return false;
}
// Extract credentials from Authorization header
const base64Credentials = authHeader.split(' ')[1];
const credentials = Buffer.from(base64Credentials, 'base64').toString(
'utf-8'
);
const [username, password] = credentials.split(':');
// Validate against environment variables
const expectedUsername = process.env.CRON_JOBS_USERNAME;
const expectedPassword = process.env.CRON_JOBS_PASSWORD;
if (!expectedUsername || !expectedPassword) {
console.error(
'Basic auth credentials not configured in environment variables'
);
return false;
}
return username === expectedUsername && password === expectedPassword;
}
/** /**
* distribute credits to all users daily * distribute credits to all users daily
*/ */
export async function GET() { export async function GET(request: Request) {
// Validate basic authentication
if (!validateBasicAuth(request)) {
console.error('distribute credits unauthorized');
return new NextResponse('Unauthorized', {
status: 401,
headers: {
'WWW-Authenticate': 'Basic realm="Secure Area"',
},
});
}
console.log('distribute credits start'); console.log('distribute credits start');
const { processedCount, errorCount } = await distributeCreditsToAllUsers(); const { processedCount, errorCount } = await distributeCreditsToAllUsers();
console.log( console.log(

View File

@ -571,7 +571,7 @@ export async function distributeCreditsToAllUsers() {
name: user.name, name: user.name,
}) })
.from(user) .from(user)
.where(eq(user.banned, false)); // Only active users .where(not(eq(user.banned, true))); // Only active users, banned is null by default
console.log('distribute credits, users count:', users.length); console.log('distribute credits, users count:', users.length);
let processedCount = 0; let processedCount = 0;