Skip to content

API Reference

dxx114514-stack edited this page Oct 17, 2026 · 5 revisions

API 文档

NoldOJ 后端提供 REST API,统一前缀 /api/v1,共 36 个路由文件、23 个挂载前缀、179 个端点。

完整接口文档(含每个端点的请求/响应示例与错误码):

本页为模块级总览。

认证方式

  • 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 探针)

试卷 API(/exams)

方法与路径 说明
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 节。

用户组 API(/groups)

组的管理操作(建组、改名/描述、删除、增减成员)仅 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 状态却谁都看不到。

POST /groups/:id/import — Excel 批量导入成员

前端解析 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 中返回。

实体可见性 API(/:id/visibility)

题目 / 比赛 / 试卷 / 题单四类实体共用一套可见性语义: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 末尾「前端页面」表。

相关文档

Clone this wiki locally