# oj_Platform-Based_on-vibecoding **Repository Path**: bacht/oj_-platform-based_on-vibecoding ## Basic Information - **Project Name**: oj_Platform-Based_on-vibecoding - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-21 - **Last Updated**: 2026-08-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # OJ Platform:基于 C++17 的在线判题平台 一个面向个人学习与作品集展示的仿 LeetCode 在线判题系统,完整覆盖“注册登录 → 浏览题目 → 编写 C++ → 异步提交 → 自动判题 → 查看结果”的端到端流程。 项目采用 C++17 编写 HTTP 服务和判题核心,使用 MySQL 持久化业务数据,前端为无框架的原生 HTML/CSS/JavaScript 多页应用。 > **安全提示:当前用户代码直接在宿主机子进程中运行,仅设置 CPU 和内存资源限制,不具备容器、namespace、seccomp、文件系统或网络隔离。项目适合本地学习、内网演示和受信任用户环境,请勿未经安全加固直接向不可信公网用户开放提交功能。** ## 功能特性 ### 用户与权限 - 用户注册、登录、注销和当前用户查询; - 密码使用每用户随机 Salt + SHA-256 存储; - 基于 MySQL Session 和 `OJ_SESSION` Cookie 的身份认证; - `user`、`admin` 两级角色与管理员 RBAC 鉴权; - 普通用户越权访问他人提交时返回 404,避免泄漏记录存在性。 ### 题目系统 - 题目列表与分页; - 按 `Easy`、`Medium`、`Hard` 难度筛选; - 按标签筛选; - 题目描述、样例输入输出、时间限制和内存限制; - 公开接口不返回隐藏测试用例; - 管理员可创建、编辑、删除题目和测试用例。 ### 在线编辑与判题 - 本地集成 Ace Editor,支持 C++ 高亮、行号和括号匹配; - Ace 加载失败时回退到普通文本框; - 按题目在浏览器 `localStorage` 中保存代码草稿; - 支持 `Ctrl/Cmd + Enter` 快捷提交; - 提交后立即返回 ID,前端异步轮询结果; - 默认 4 个进程内判题工作线程; - 使用 `g++ -O2 -std=c++17 -DONLINE_JUDGE` 编译; - 使用 `fork`、`execve`、`setrlimit`、`wait4` 和 `getrusage` 运行并统计用户程序; - 支持 `Pending`、`Judging`、`AC`、`WA`、`TLE`、`RE`、`CE`、`SE` 状态; - WA 展示首个失败用例的 Expected/Got 摘要; - CE 展示编译器诊断,RE 展示退出码或信号; - 提供个人提交列表和提交详情。 ### Web 页面 | 路径 | 页面 | 权限 | |---|---|---| | `/` | 首页 | 公开 | | `/login` | 登录 | 公开 | | `/register` | 注册 | 公开 | | `/problems` | 题目列表 | 公开 | | `/problems/:id` | 题目详情与代码编辑器 | 公开浏览,登录后提交 | | `/submissions` | 我的提交 | 登录用户 | | `/submissions/:id` | 提交详情 | 提交所有者或管理员 | | `/admin/problems` | 管理员题目列表 | 管理员 | | `/admin/problems/new` | 新建题目 | 管理员 | | `/admin/problems/:id/edit` | 编辑题目 | 管理员 | 项目使用真实 URL 的多页应用(MPA),没有客户端 Hash Router。 ## 技术栈 | 模块 | 技术 | |---|---| | 后端 | C++17 | | HTTP | cpp-httplib v0.18.1 | | JSON | jsoncpp | | 数据库 | MySQL 5.7+ / 8.x、libmysqlclient | | 加密与随机数 | OpenSSL Crypto | | 并发 | `std::thread`、互斥锁、条件变量、FIFO 队列 | | 判题运行 | Linux `fork`、`execve`、`setrlimit`、`wait4` | | 前端 | 原生 HTML、CSS、JavaScript,多页应用 | | 编辑器 | Ace Editor | | 代码展示 | highlight.js | | 构建 | CMake 3.16+ | | C++ 测试 | GoogleTest、CTest | | HTTP 测试 | Python、pytest、requests | ## 系统架构 ```text Browser(原生 MPA) ├── HTML / CSS / JavaScript / Ace └── fetch /api/* + OJ_SESSION Cookie │ ▼ cpp-httplib Server ├── HTML 与静态资源路由 ├── REST API Handler ├── Session 中间件 └── RBAC 中间件 │ ▼ Service 层 ├── AuthService / SessionService ├── ProblemService └── SubmissionService │ ▼ Repository 层 + MySQL 连接池 └── users / sessions / problems / test_cases / submissions 提交请求 └── 内存 FIFO 队列 └── JudgePool 工作线程 ├── g++ 编译子进程 ├── 用户代码运行子进程 └── 输出比较与结果落库 ``` HTTP 服务、业务 API、静态前端和判题线程池运行在同一个 `oj_server` 进程中。 ## 项目结构 ```text . ├── README.md # 项目介绍与快速开始 ├── DEPLOY.md # 部署与运维说明 ├── SPEC.md # 项目需求与实现规格 ├── API.md # HTTP API 文档 ├── oj-server/ │ ├── CMakeLists.txt # CMake 构建配置 │ ├── config.json # 默认服务配置 │ ├── db/ │ │ └── init.sql # 数据库全量初始化脚本 │ ├── scripts/ │ │ ├── build.sh # 构建脚本 │ │ └── run.sh # 启动脚本 │ ├── src/ │ │ ├── main.cpp # 程序入口与模块装配 │ │ ├── server/ # HTTP、HTML、静态资源与中间件 │ │ ├── service/ # 业务服务层 │ │ ├── repo/ # MySQL Repository 与连接池 │ │ ├── model/ # 数据模型 │ │ ├── judge/ # 队列、编译、运行、比较与真实判题 │ │ ├── util/ # 配置、加密、Cookie、日志等工具 │ │ └── tools/ # 数据重置与测试数据工具 │ ├── web/ # 原生 MPA 前端 │ │ ├── admin/ │ │ └── static/ │ │ ├── css/ │ │ ├── js/ │ │ └── vendor/ │ └── data/runs/ # 默认判题临时目录 └── tests/ ├── phase_1/ ... phase_5/ # C++ GoogleTest └── python/ # HTTP 集成测试 ``` ## 快速开始 以下命令均在仓库根目录执行。 ### 1. 安装依赖 项目要求 Linux、CMake 3.16+、C++17 编译器、MySQL、OpenSSL、jsoncpp 和 libmysqlclient。Debian/Ubuntu 可参考: ```bash sudo apt update sudo apt install -y \ build-essential cmake pkg-config \ libssl-dev libjsoncpp-dev default-libmysqlclient-dev \ mysql-server g++ curl ``` 若系统未安装 `httplib.h`,首次运行 CMake 时会通过 FetchContent 获取 cpp-httplib v0.18.1,因此需要网络访问。 ### 2. 初始化数据库 > **警告:下面的脚本会删除并重建 `oj` 数据库中的业务表,只能用于新数据库或允许清空数据的开发环境。** ```bash mysql -u root -p < oj-server/db/init.sql ``` 初始化脚本会创建 `oj` 数据库和默认管理员: ```text 用户名:admin 密码:admin123 ``` 脚本不会创建默认配置中的 MySQL 用户 `ubuntu`,请自行创建应用用户并授予其访问 `oj` 数据库的权限,或修改配置中的 `db.user`。 ### 3. 配置数据库密码 默认配置位于 `oj-server/config.json`,连接参数为: ```text host: 127.0.0.1 port: 3306 user: ubuntu database: oj ``` 推荐通过环境变量注入密码: ```bash export ubuntu_password='<你的 MySQL 密码>' ``` 当 `ubuntu_password` 非空时,会覆盖 `config.json` 中的 `db.password`。仓库不会自动加载 `.env` 文件。 ### 4. 构建 ```bash ./oj-server/scripts/build.sh ``` 默认使用 Release 模式,产物为 `build/oj_server`。其他构建方式: ```bash BUILD_TYPE=Debug ./oj-server/scripts/build.sh CLEAN=1 ./oj-server/scripts/build.sh ``` ### 5. 启动 ```bash export ubuntu_password='<你的 MySQL 密码>' ./oj-server/scripts/run.sh ``` 指定端口或配置文件: ```bash PORT=9090 ./oj-server/scripts/run.sh CONFIG=/absolute/path/to/config.json ./oj-server/scripts/run.sh ``` 默认访问地址: ```text http://127.0.0.1:8080/ ``` ### 6. 检查服务 ```bash curl -fsS http://127.0.0.1:8080/api/health ``` 预期响应包含: ```json { "status": "ok", "service": "oj_server" } ``` 健康接口仅检查 HTTP 进程是否存活,不检查 MySQL 和判题器是否可用。 ## 配置说明 默认配置: ```json { "port": 8080, "db": { "host": "127.0.0.1", "port": 3306, "user": "ubuntu", "password": "", "name": "oj" }, "judge": { "worker_count": 4, "work_dir": "./data/runs", "compiler": "g++", "compile_flags": "-O2 -std=c++17 -DONLINE_JUDGE" }, "session": { "ttl_seconds": 86400, "cookie_name": "OJ_SESSION" } } ``` | 配置项 | 默认值 | 说明 | |---|---:|---| | `port` | `8080` | HTTP 端口 | | `db.host` | `127.0.0.1` | MySQL 地址 | | `db.port` | `3306` | MySQL 端口 | | `db.user` | `ubuntu` | MySQL 用户 | | `db.password` | 空 | MySQL 密码,可由 `ubuntu_password` 覆盖 | | `db.name` | `oj` | 数据库名 | | `judge.worker_count` | `4` | 判题工作线程数 | | `judge.work_dir` | `./data/runs` | 判题临时目录 | | `judge.compiler` | `g++` | 判题编译器 | | `judge.compile_flags` | `-O2 -std=c++17 -DONLINE_JUDGE` | 编译参数 | | `session.ttl_seconds` | `86400` | Session 有效期,单位为秒 | | `session.cookie_name` | `OJ_SESSION` | Cookie 名称 | | `web_root` | `./web` | 可选,前端资源目录的代码默认值 | `CONFIG`、`PORT` 是 `run.sh` 使用的环境变量;`BUILD_TYPE`、`CLEAN` 是 `build.sh` 使用的环境变量。配置中的相对路径按进程工作目录解析,推荐使用仓库启动脚本。 ## API 概览 ### 认证 | Method | Path | 说明 | |---|---|---| | `POST` | `/api/auth/register` | 注册 | | `POST` | `/api/auth/login` | 登录并设置 Cookie | | `POST` | `/api/auth/logout` | 注销并撤销 Session | | `GET` | `/api/auth/me` | 当前用户 | ### 题目 | Method | Path | 说明 | |---|---|---| | `GET` | `/api/problems` | 题目列表、分页和筛选 | | `GET` | `/api/problems/:id` | 题目详情,不返回隐藏用例 | | `GET` | `/api/admin/problems/:id/full` | 管理员读取完整题目和用例 | | `POST` | `/api/admin/problems` | 管理员创建题目 | | `PUT` | `/api/admin/problems/:id` | 管理员更新题目 | | `DELETE` | `/api/admin/problems/:id` | 管理员删除题目 | ### 提交 | Method | Path | 说明 | |---|---|---| | `POST` | `/api/submissions` | 创建提交并进入判题队列 | | `GET` | `/api/submissions` | 当前用户的提交列表 | | `GET` | `/api/submissions/:id` | 提交详情与判题结果 | | `DELETE` | `/api/submissions/:id` | 所有者或管理员删除提交 | 完整接口说明见 [API.md](API.md)。其中部分阶段说明可能落后于当前实现,遇到差异时应以 `oj-server/src/server/` 中的实际路由代码为准。 ## 判题流程 ```text 1. 创建 submissions 记录,状态为 Pending 2. 将 submission_id 放入进程内 FIFO 队列 3. worker 获取任务并写入 Judging 4. 创建 data/runs// 5. 写入 main.cpp 并调用 g++ 编译 6. 编译失败:写入 CE 和编译诊断 7. 逐个测试用例 fork 子进程运行 8. 使用 RLIMIT_CPU、RLIMIT_AS 限制资源 9. 收集 CPU 时间与峰值 RSS 10. 标准化并比较实际输出和期望输出 11. 写入 AC / WA / TLE / RE / SE 12. 清理提交临时目录 ``` 当前只支持语言标识 `cpp`,单次代码最大 4 MiB;不支持特殊判题器、按题目配置浮点误差或多语言判题。 ## 测试 ### C++ 单元与集成测试 安装 GoogleTest 后重新构建: ```bash sudo apt install -y libgtest-dev ./oj-server/scripts/build.sh ``` 运行: ```bash export ubuntu_password='<测试数据库密码>' ctest --test-dir build --output-on-failure ``` 注意: - 若 CMake 未找到 GoogleTest,会提示警告并禁用测试目标; - 未设置 `ubuntu_password` 时,多个数据库测试会被跳过; - 数据库测试会写入数据,不要连接正式数据库。 ### HTTP 集成测试 先启动服务并准备数据库,再执行: ```bash python3 -m pip install -r tests/python/requirements.txt python3 tests/python/run_all.py ``` 指定其他服务地址: ```bash OJ_BASE_URL=http://127.0.0.1:9090 python3 tests/python/run_all.py ``` 仓库当前没有独立的 lint、format 或 typecheck 脚本;C++ 编译默认启用 `-Wall -Wextra -Wpedantic`。 ## 开发与测试工具 ### 重置管理员 ```bash cd oj-server ../build/reset_admin ``` > **破坏性操作:该工具会删除全部用户,并级联删除相关 Session 和提交,然后重新创建 `admin / admin123`。** ### 重建测试数据 ```bash cd oj-server ../build/seed_test_data --yes ``` > **破坏性操作:该工具会清空业务数据,并重建测试账号、题目和提交记录。不得在正式数据库运行。** ## 已知限制 - **无强沙箱**:用户代码可接触宿主文件系统和网络; - **仅支持 C++**:当前语言标识仅允许 `cpp`; - **队列不持久化**:服务重启后不会自动恢复待判题提交; - **部署能力有限**:未提供 Docker、Compose、systemd、反向代理和 TLS 配置; - **数据库无迁移机制**:只有会删表的全量初始化脚本; - **默认管理员凭据弱**:固定为 `admin / admin123`,且无修改密码 API; - **Session 无定时清理**:过期 Session 查询时失效,但没有后台清理任务; - **健康检查有限**:不检查 MySQL、`g++`、worker 和临时目录; - **无 SPJ**:当前真实判题使用标准化后的精确比较; - **无监控指标**:没有队列深度、Prometheus 指标和自动告警。 更完整的安全、运维、备份、升级与故障排查说明见 [DEPLOY.md](DEPLOY.md)。 ## 相关文档 - [SPEC.md](SPEC.md):需求、设计和开发阶段记录 - [API.md](API.md):HTTP API 接口说明 - [DEPLOY.md](DEPLOY.md):部署、升级、备份和故障排查 - [tests/python/README.md](tests/python/README.md):Python HTTP 测试说明