Repository navigation
API Reference
NoldOJ 后端提供 REST API,统一前缀 /api/v1,共 36 个路由文件、23 个挂载前缀、179 个端点。
完整接口文档(含每个端点的请求/响应示例与错误码):
docs/api/APIuse.mddocs/api/openapi.yaml(OpenAPI 3.0)本页为模块级总览。
-
JWT 双令牌:登录后获得 Access Token(
15m)与 Refresh Token(7d)。 - 请求头:
Authorization: Bearer <access_token>。 - 过期后调用
POST /auth/refresh换新;登出、封禁、强制登出(force_logout_at)都会使令牌失效。 - 登录/注册需先取图形验证码:
GET /auth/captcha→ 提交captcha_id+captcha_code(见 使用指南)。
su(超级管理员)> admin(管理员)> teacher(教师)> user(用户)
{
"code": 5,
"reason": "ERR_UNAUTHORIZED",
"message": "Invalid username or password."
}code 为业务错误码:1 参数错误(ERR_INVALID_ARGUMENT)、2 状态错误、3 未找到、4 限流/超限(ERR_RATE_LIMITED、ERR_SUBMIT_LIMIT_EXCEEDED、ERR_FILE_TOO_LARGE)、5 未授权(ERR_UNAUTHORIZED)、6 禁止(ERR_FORBIDDEN);reason 为稳定机读原因,message 为面向用户的说明。
helmet(CSP 等安全响应头)、CORS 白名单、IP+账号限流、上传伪装检测、提交锁——对应黑盒测试覆盖项见 测试与 CI。
| 模块 | 前缀 | 主要端点 |
|---|---|---|
| 认证 | /auth |
captcha、send-code、verify-code、login、register、refresh、logout、change-password、forgot-password、reset-password、email-enabled |
| 题目 | /problems |
列表/详情 CRUD、测试点增删改、ZIP/文件测试数据、AI 生成测试数据、测试分组、计分脚本、题解、讨论、查重、AI 提示(POST /:id/hint) |
| 标签 | /tags |
标签 CRUD、题目标签设置 |
| 提交 | /submissions |
列表、详情、提交代码、detail(含每点时间/内存/分组)、diff、rejudge、删除 |
| 在线编程 | /ide |
languages、run(队列)、run 状态、review(AI 审查) |
| 用户 | /users |
资料、列表、角色、封禁/解封、强制登出、重置密码、Rating、图床限额、sudo-login、创建/删除、注册开关 |
| 用户组 | /groups |
组列表/创建、改名/删组(?force=1)、成员增删、我的组、Excel 批量导入成员(POST /:id/import,仅 su);另见「实体可见性 API」 |
| 语言 | /languages |
语言 CRUD(仅超管) |
| 比赛 | /contests |
CRUD、题目、邀请/加入、参赛者、排行榜、解封榜、公告、虚拟参赛、一键查重、讨论 |
| 试卷 | /exams |
列表/详情/创建/编辑/删除、交卷、考生答卷、提交列表、手动批改、AI 批改、排行榜(时间窗/封榜) |
| 文章 | /articles |
文章 CRUD |
| 文件 | /uploads |
上传/访问/删除(仅教师及以上) |
| 分类 | /categories |
分类 CRUD、题目归类 |
| 公告 | /announcements |
公告 CRUD |
| 题单 | /problem-sets |
题单 CRUD、进度、标记 AC |
| 虚拟比赛 | /virtual-contests |
详情、本人排名 |
| 查重 | /plagiarism |
任务进度、查重对详情 |
| 成就 | /achievements |
成就列表与进度 |
| 数据看板 | /statistics |
个人统计数据 |
| 收藏 | /favorites |
收藏列表/状态/增删 |
| 讨论 | /discussions |
讨论/回复 CRUD、置顶、锁定、官方题解 |
| 系统状态 | /system |
GET /system/status(管理员系统状态仪表盘) |
| 系统 | (server.js 直接定义) |
GET /api/v1/health、GET /api/v1/stats、GET /api/v1/jobs 与 GET /api/v1/jobs/:id(301 到 /submissions)、GET /output.txt(404 探针) |
| 方法与路径 | 说明 |
|---|---|
GET /exams |
试卷列表 |
POST /exams |
创建试卷(教师+;题型/题目、时间窗 start_time/end_time、freeze_minutes、排行榜开关) |
GET /exams/:id |
试卷详情(开考前对考生 403) |
PUT /exams/:id |
编辑试卷(教师+;含封榜控制 manual_frozen/unfrozen) |
DELETE /exams/:id |
删除试卷(教师+) |
POST /exams/:id/submit |
交卷(须在时间窗内) |
GET /exams/:id/submission/:sid |
考生答卷详情(成绩页) |
GET /exams/:id/submissions |
提交列表(教师+) |
POST /exams/:id/grade/:sid |
手动批改主观题(教师+) |
POST /exams/:id/ai-grade/:sid |
AI 批改(教师+) |
GET /exams/:id/leaderboard |
排行榜(完成门槛、封榜快照、?limit 默认 100 上限 200、返回 my 名次) |
另有 GET /system/status(/system,admin+ 系统状态仪表盘)。完整字段见 docs/api/APIuse.md 11.5/11.6 节。
组的管理操作(建组、改名/描述、删除、增减成员)仅 admin/su 可用;任何登录用户都可读 GET /groups/mine。注册时系统自动为每个账号建「个人」组(kind=personal,显示名=用户名)并加入全局唯一的「所有用户」组(kind=all_users),这两个系统组不可改名/删除、成员不可自助变更(403 ERR_FORBIDDEN)。
| 方法与路径 | 说明 |
|---|---|
GET /groups |
用户组列表(含系统组、成员数与已绑定实体数;仅 admin/su) |
POST /groups |
创建自定义组(仅 admin/su;name 必填,kind 固定 custom,owner_id 取当前管理员) |
GET /groups/mine |
我加入的组(任意登录用户;含两个系统组,只含最小字段,不含他人组信息) |
PUT /groups/:id |
改名 / 改描述(仅 admin/su;name 与 description 至少传一个,系统组 403) |
DELETE /groups/:id |
删除组(仅 admin/su;?force=1 先把受影响实体回退为 public 再删,系统组 403) |
GET /groups/:id/members |
组成员分页(仅 admin/su;page/limit 须为正整数,limit 默认 20、上限 100) |
POST /groups/:id/members |
添加成员(仅 admin/su;user_id 必填,全体组成员不可手工变更 → 403) |
DELETE /groups/:id/members/:userId |
移出成员(仅 admin/su;系统组成员一律 403) |
POST /groups/:id/import |
Excel 批量导入成员(仅 su);请求体 users 数组 + default_password,单次上限 500 行 |
删组时若该组仍绑定实体且未带 force,返回 409 { code: 2, reason: "ERR_INVALID_STATE" },message 列出受影响的实体类型与数量;带 ?force=1 时先解绑,并把「因本组消失而再无任何可见组」的实体回退为 public,避免实体停留在 groups 状态却谁都看不到。
前端解析 xlsx/xls 的第一个 sheet 后提交:列 用户名(必填)与 昵称(选填),支持 username/账号、nickname/姓名 别名,其余列忽略;首行未被识别为表头时按固定列序「用户名|昵称」读取;文件内重复用户名已去重。站内示例文件见 /group-sample.xlsx。
请求体(ImportUsersPayload):
{
"users": [
{ "username": "student01", "nickname": "张三" },
{ "username": "student02" }
],
"default_password": "Noldoj@2026"
}-
users最多 500 条(去重后),username必填,nickname可省略。 -
default_password字段选填,但只要users里含有尚未注册的账号就必填,缺失即整单 400。该密码是本批次全部新注册账号的初始口令(不回显、不落盘),要求 ≥8 位且含字母与数字或符号(与管理员建号强度一致),不合规则整单 400。
响应(ImportResult):
{
"total": 42,
"added": 38,
"registered": 12,
"skipped": 4,
"failed": [{ "username": "student_09", "reason": "原因说明(服务端返回的可读文案)" }]
}界面按「共 42 行:新增成员 38 人(其中自动注册 12 人),已在组内 4 人」展示,failed 逐条列成「用户名: 原因」。
导入的三条硬约束:
-
仅超级管理员(su):比其它用户组接口更严,admin 及以下调用一律 403(
ERR_FORBIDDEN);管理面板里按钮同步禁用并提示「含未注册用户自动注册,需超级管理员」。 -
仅自定义组可导入:个人组(
kind=personal)与「所有用户」系统组(kind=all_users)一律 403。 -
自动注册固定为普通用户:不解析文件里的角色,无法通过 Excel 提权,新注册账号一律
role=user。
失败分两级:整单级错误(行数超限、存在未注册账号但缺 default_password、默认密码不合规)整个请求被拒 400 且不写入任何数据;行级失败只影响该行,其它行照常成功,失败明细在 failed 中返回。
题目 / 比赛 / 试卷 / 题单四类实体共用一套可见性语义:visibility 取 public(默认,所有人可见,匿名访客也算)或 groups(仅绑定组成员 + teacher/admin/su 可见)。
| 方法与路径 | 说明 |
|---|---|
GET /problems/:id/visibility |
读题目可见性(任意登录用户) |
PUT /problems/:id/visibility |
写题目可见性(仅 admin/su) |
GET /contests/:id/visibility |
读比赛可见性(任意登录用户) |
PUT /contests/:id/visibility |
写比赛可见性(仅 admin/su) |
GET /exams/:id/visibility |
读试卷可见性(任意登录用户) |
PUT /exams/:id/visibility |
写试卷可见性(仅 admin/su) |
GET /problem-sets/:id/visibility |
读题单可见性(任意登录用户) |
PUT /problem-sets/:id/visibility |
写题单可见性(仅 admin/su) |
写入体(VisibilityPayload):
{
"visibility": "groups",
"group_ids": [3, 5]
}visibility=groups 时 group_ids 必填且至少一个(组不存在返回 400 ERR_INVALID_ARGUMENT,不静默丢弃);visibility=public 时可省略 group_ids(传入则清空绑定)。读取与写入均返回 VisibilityInfo:
{
"visibility": "groups",
"groups": [{ "id": 3, "name": "集训队", "kind": "custom" }]
}可见性判定对列表与详情同时生效:列表静默过滤不可见实体(不报错、不暴露存在性),详情与直连 URL 一律返回 403 { code: 6, reason: "ERR_FORBIDDEN" },message 形如 You do not have permission to view this problem.;提交、题解、讨论、AI 提示、收藏、词云、榜单等旁路同步生效。teacher 及以下调用写接口同样返回 403。
| 场景 | 方法与路径 |
|---|---|
| 登录 | POST /api/v1/auth/login |
| 题目列表 | GET /api/v1/problems |
| 提交代码 | POST /api/v1/submissions |
| 提交详情(每点耗时/内存) | GET /api/v1/submissions/:id/detail |
| 重测 | POST /api/v1/submissions/:id/rejudge |
| IDE 运行 |
POST /api/v1/ide/run → GET /api/v1/ide/run/:id
|
| 健康检查 | GET /api/v1/health |
语法、常量、传入/需定义变量与示例见 判题与沙箱。
页面路径见 frontend/pages/(42 个页面,全中文):题库 problems.html、题目 problem.html?id=X、提交 submit.html、提交详情 submission.html?id=X、IDE ide.html、比赛 contest.html?id=X、试卷 exam.html?id=X、管理面板 admin.html 等,完整清单见 APIuse.md 末尾「前端页面」表。
NoldOJ · Windows 在线评测系统 · MIT License