Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
659 changes: 0 additions & 659 deletions BUSINESS_DESIGN_ANALYSIS.md

This file was deleted.

764 changes: 764 additions & 0 deletions BUSINESS_IMPROVEMENT_PLAN.md

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions backend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,15 @@ DATABASE_URL="mysql://ulticode:ulticode@localhost:23306/ulticode"
# Must be at least 32 characters long for cryptographic security
# Generate a secure random string for production
JWT_SECRET="ulticode-super-secret-jwt-key-min-32-chars"

# Stripe API keys for payment processing
# Get these from https://dashboard.stripe.com/apikeys
STRIPE_SECRET_KEY="sk_test_xxx"
STRIPE_WEBHOOK_SECRET="whsec_xxx"
STRIPE_PRICE_PREMIUM_MONTHLY="price_xxx"
STRIPE_PRICE_PREMIUM_YEARLY="price_xxx"

# Docker sandbox configuration
DOCKER_SOCKET="/var/run/docker.sock"
JUDGE_IMAGE="ulti-judge:latest"
SANDBOX_TYPE="docker"
1 change: 1 addition & 0 deletions backend/.eslintcache

Large diffs are not rendered by default.

76 changes: 76 additions & 0 deletions backend/judge/runners/run-rust.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/bin/bash
# Rust code runner for the sandbox
# Compiles and executes Rust code with provided inputs

set -e

TIME_LIMIT_MS="${TIME_LIMIT_MS:-15000}"
INPUT_FILE="${INPUT_FILE:-/sandbox/input/args.json}"
CODE_FILE="${CODE_FILE:-/sandbox/code/solution.rs}"
WORK_DIR="/sandbox/code"
OUTPUT_BIN="${WORK_DIR}/solution"

# Function to output JSON error
output_error() {
local status="$1"
local error="$2"
local time="${3:-0}"
local memory="${4:-0}"
echo "{\"status\": \"${status}\", \"error\": \"${error}\", \"time\": ${time}, \"memory\": ${memory}}"
exit 1
}

cd "$WORK_DIR"

# Compile Rust code with optimizations
COMPILE_START=$(date +%s%3N)
if ! rustc -O -o "$OUTPUT_BIN" "$CODE_FILE" 2>compile_error.txt; then
COMPILE_ERROR=$(cat compile_error.txt | head -20)
output_error "Compile Error" "$COMPILE_ERROR"
fi
COMPILE_TIME=$(($(date +%s%3N) - COMPILE_START))

# Prepare input
if [ -f "$INPUT_FILE" ]; then
STDIN_INPUT=$(cat "$INPUT_FILE" | python3 -c "
import json, sys
data = json.load(sys.stdin)
args = data.get('args', [])
for arg in args:
if isinstance(arg, list):
print(' '.join(map(str, arg)))
else:
print(str(arg))
" 2>/dev/null || echo "")
else
STDIN_INPUT=""
fi

# Execute with timeout
TIMEOUT_SEC=$((TIME_LIMIT_MS / 1000 + 2))
EXEC_START=$(date +%s%3N)

if [ -n "$STDIN_INPUT" ]; then
OUTPUT=$(echo "$STDIN_INPUT" | timeout ${TIMEOUT_SEC}s "$OUTPUT_BIN" 2>&1) || EXEC_STATUS=$?
else
OUTPUT=$(timeout ${TIMEOUT_SEC}s "$OUTPUT_BIN" 2>&1) || EXEC_STATUS=$?
fi

EXEC_TIME=$(($(date +%s%3N) - EXEC_START))
EXEC_STATUS=${EXEC_STATUS:-0}

# Get memory usage
MEMORY_MB=$(ps -o rss= -p $$ 2>/dev/null | awk '{printf "%.2f", $1/1024}' || echo "0")

if [ $EXEC_STATUS -eq 124 ]; then
output_error "Time Limit Exceeded" "Execution timed out" "$TIME_LIMIT_MS" "$MEMORY_MB"
elif [ $EXEC_STATUS -ne 0 ]; then
CLEANED_OUTPUT=$(echo "$OUTPUT" | grep -v "^$" | head -20)
output_error "Runtime Error" "$CLEANED_OUTPUT" "$EXEC_TIME" "$MEMORY_MB"
else
CLEANED_OUTPUT=$(echo "$OUTPUT" | sed 's/"/\\"/g' | tr '\n' '\\n' | sed 's/\\n$//')
printf '{"status": "Success", "output": "%s", "time": %d, "memory": %.2f}\n' \
"$CLEANED_OUTPUT" \
"$EXEC_TIME" \
"$MEMORY_MB"
fi
3 changes: 3 additions & 0 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"@nestjs/platform-express": "^11.0.1",
"@nestjs/platform-socket.io": "^11.0.1",
"@nestjs/schedule": "^6.1.0",
"@nestjs/swagger": "^11.2.5",
"@nestjs/throttler": "^6.5.0",
"@nestjs/websockets": "^11.0.1",
"@prisma/client": "^6.19.0",
Expand All @@ -62,6 +63,7 @@
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.1",
"socket.io": "^4.8.1",
"stripe": "^20.4.0",
"typescript": "^5.7.3",
"uuid": "^11.1.0"
},
Expand All @@ -79,6 +81,7 @@
"@types/jest": "^30.0.0",
"@types/node": "^22.10.7",
"@types/nodemailer": "^7.0.11",
"@types/stripe": "^8.0.417",
"@types/supertest": "^6.0.2",
"@types/uuid": "^10.0.0",
"eslint": "^9.18.0",
Expand Down
122 changes: 110 additions & 12 deletions backend/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,27 @@ datasource db {
}

model Subscription {
id String @id @default(uuid()) @db.VarChar(40)
user_id String @db.VarChar(40)
plan SubscriptionPlan @default(FREE)
status SubscriptionStatus @default(ACTIVE)
started_at DateTime @default(now())
expires_at DateTime?
cancelled_at DateTime?
created_at DateTime @default(now())
updated_at DateTime @updatedAt
id String @id @default(uuid()) @db.VarChar(40)
user_id String @db.VarChar(40)
plan SubscriptionPlan @default(FREE)
status SubscriptionStatus @default(ACTIVE)
started_at DateTime @default(now())
expires_at DateTime?
cancelled_at DateTime?
// Stripe payment integration fields
stripe_customer_id String? @db.VarChar(255)
stripe_subscription_id String? @db.VarChar(255)
stripe_price_id String? @db.VarChar(255)
stripe_current_period_end DateTime?
created_at DateTime @default(now())
updated_at DateTime @updatedAt

user User @relation(fields: [user_id], references: [id], onDelete: Cascade)

@@index([user_id])
@@index([status])
@@index([stripe_customer_id])
@@index([stripe_subscription_id])
@@map("subscriptions")
}

Expand Down Expand Up @@ -104,6 +111,9 @@ model Problem {
flag_reviewed_by String? @db.VarChar(40)
flag_reviewed_at DateTime?
flag_notes String? @db.Text
created_at DateTime @default(now())
updated_at DateTime @default(now()) @updatedAt
version Int @default(1)
contestProblems ContestProblem[]
detail ProblemDetail?
examples ProblemExample[]
Expand All @@ -114,6 +124,7 @@ model Problem {
solutions Solution[]
submissions Submission[]
testCases TestCase[]
versions ProblemVersion[]

@@index([difficulty])
@@index([slug])
Expand All @@ -122,9 +133,39 @@ model Problem {
@@index([is_flagged, is_deleted])
@@index([difficulty, is_published, is_deleted])
@@index([created_at])
@@index([version])
@@map("problems")
}

model ProblemVersion {
id String @id @default(cuid())
problem_id BigInt
version_number Int
title String @db.VarChar(255)
slug String @db.VarChar(120)
difficulty Difficulty
is_premium Boolean @default(false)
is_published Boolean @default(false)
summary String? @db.Text
content String? @db.Text
constraints Json?
hints Json?
examples Json?
languages Json?
tags Json?
change_summary String? @db.VarChar(500)
change_type String @default("update") @db.VarChar(20) // create, update, rollback
created_at DateTime @default(now())
created_by String? @db.VarChar(40)

problem Problem @relation(fields: [problem_id], references: [id], onDelete: Cascade)

@@unique([problem_id, version_number])
@@index([problem_id])
@@index([created_at])
@@map("problem_versions")
}

model ProblemDetail {
id String @id @db.VarChar(40)
problem_id BigInt @unique
Expand Down Expand Up @@ -865,9 +906,10 @@ model Submission {
test_details Json?
memoryDistBinsMb Json?
runtimeDistBinsMs Json?
contestSubmissions ContestSubmission[]
problem Problem @relation(fields: [problem_id], references: [id], onDelete: Cascade)
user User @relation(fields: [user_id], references: [id], onDelete: Cascade)
contestSubmissions ContestSubmission[]
executionLogs SandboxExecutionLog[]
problem Problem @relation(fields: [problem_id], references: [id], onDelete: Cascade)
user User @relation(fields: [user_id], references: [id], onDelete: Cascade)

@@index([problem_id, user_id])
@@index([created_at])
Expand Down Expand Up @@ -1306,3 +1348,59 @@ enum EmailStatus {
SENT
FAILED
}

// Sandbox Execution Monitoring
model SandboxExecutionLog {
id String @id @default(uuid()) @db.VarChar(40)
execution_id String @unique @db.VarChar(40)
submission_id String? @db.VarChar(40)
language String @db.VarChar(20)
status ExecutionStatus @default(RUNNING)
time_ms Int?
memory_bytes Int?
exit_code Int?
error_message String? @db.Text
container_id String? @db.VarChar(64)
started_at DateTime @default(now())
completed_at DateTime?
created_at DateTime @default(now())

submission Submission? @relation(fields: [submission_id], references: [id])

@@index([status])
@@index([language])
@@index([started_at])
@@index([submission_id])
@@map("sandbox_execution_logs")
}

model SandboxMetrics {
id String @id @default(uuid()) @db.VarChar(40)
date DateTime @db.Date
total_executions Int @default(0)
successful Int @default(0)
timeouts Int @default(0)
memory_exceeded Int @default(0)
runtime_errors Int @default(0)
compile_errors Int @default(0)
system_errors Int @default(0)
avg_time_ms Float?
max_time_ms Int?
avg_memory_bytes Float?
max_memory_bytes Int?
created_at DateTime @default(now())
updated_at DateTime @updatedAt

@@unique([date])
@@map("sandbox_metrics")
}

enum ExecutionStatus {
RUNNING
COMPLETED
TIMEOUT
MEMORY_EXCEEDED
RUNTIME_ERROR
COMPILE_ERROR
SYSTEM_ERROR
}
Loading
Loading