- R176 成绩公示表引擎(lib/publicitySheet.js + lib/assets/publicity-template.xlsx 官方模板基底) 与指导教师回填(lib/teacherBackfill.js);赛项名称/编号改为配置项 - R177 新闻「发布 ↔ 撤回」互斥:撤回只置 is_draft=1,不删除数据 - R178 C 层 RBAC:lib/adminPermissions.js(13 权限点 / 70 条路由规则,唯一 SoT) + middleware/auth.js 三段判定(默认拒绝 · is_super 单点 · token_version) + controller/service/adminUser.js + lib/auditLog.js + model/adminAuditLog.js - R178 B1 交卷冻结:service.exam.assertNotSubmitted(bizCode 4006 单一判据源) - R178 B④ 提交口径拆分:formalSubmitted / submitted / answeredCount 三字段 - R178 成绩总览补小组编号:resolveTeamLabels(与选手管理同源,含兜底与三态) - R181 生产迁移配套:admins +7 列、admin_audit_logs(scripts/migrate_r178_admin_rbac.py)
119 lines
3.9 KiB
JavaScript
119 lines
3.9 KiB
JavaScript
'use strict';
|
||
|
||
/**
|
||
* 管理员账号管理控制器(R178 · C 层)
|
||
*
|
||
* 统一错误约定(与项目其它控制器一致):
|
||
* - 业务错误 = HTTP 200 + `code !== 0`(helper.error 不改 HTTP 状态)
|
||
* - service 通过 `bizCode` 表达期望错误码,这里原样翻译
|
||
* ⛔ 不要把业务错误包成 500(前端会当成系统故障,用户看到「服务器错误」)
|
||
*/
|
||
|
||
const Controller = require('egg').Controller;
|
||
const adminPermissions = require('../lib/adminPermissions');
|
||
|
||
class AdminUserController extends Controller {
|
||
/** 把 service 抛出的 bizCode 翻译成业务响应;非业务异常交给上层 catch */
|
||
_fail(err, fallbackMessage) {
|
||
const { ctx } = this;
|
||
if (err && err.bizCode) {
|
||
ctx.body = ctx.helper.error(err.bizCode, err.bizMessage || err.message);
|
||
return;
|
||
}
|
||
ctx.logger.error(`${fallbackMessage}:`, err);
|
||
ctx.body = ctx.helper.error(500, fallbackMessage);
|
||
}
|
||
|
||
/**
|
||
* 当前登录管理员的权限信息(自助,无需业务权限)
|
||
* GET /api/admin/me
|
||
*
|
||
* 前端用途:① 渲染侧边菜单;② 权限被他人改动后,下次进页面能感知并提示。
|
||
* 顺带返回权限点目录(catalog),避免前端硬编码一份权限清单(那是第二真相源)。
|
||
*/
|
||
async me() {
|
||
const { ctx } = this;
|
||
const admin = ctx.state.currentAdmin;
|
||
if (!admin) {
|
||
ctx.body = ctx.helper.error(401, '未登录或登录状态已失效');
|
||
return;
|
||
}
|
||
ctx.body = ctx.helper.success({
|
||
id: admin.id,
|
||
username: admin.username,
|
||
isSuper: Number(admin.is_super) === 1,
|
||
permissions: admin.permissions || [],
|
||
catalog: adminPermissions.PERMISSIONS,
|
||
}, '获取当前管理员信息成功');
|
||
}
|
||
|
||
/** GET /api/admin/admin-users */
|
||
async list() {
|
||
const { ctx, service } = this;
|
||
try {
|
||
const list = await service.adminUser.list();
|
||
ctx.body = ctx.helper.success({ list, total: list.length }, '获取管理员列表成功');
|
||
} catch (err) {
|
||
this._fail(err, '获取管理员列表失败');
|
||
}
|
||
}
|
||
|
||
/** POST /api/admin/admin-users */
|
||
async create() {
|
||
const { ctx, service } = this;
|
||
try {
|
||
const result = await service.adminUser.create(ctx.request.body || {});
|
||
ctx.body = ctx.helper.success(result, '管理员账号已创建');
|
||
} catch (err) {
|
||
this._fail(err, '创建管理员失败');
|
||
}
|
||
}
|
||
|
||
/** PUT /api/admin/admin-users/:id/permissions */
|
||
async updatePermissions() {
|
||
const { ctx, service } = this;
|
||
try {
|
||
const result = await service.adminUser.updatePermissions(ctx.params.id, ctx.request.body || {});
|
||
ctx.body = ctx.helper.success(result, '权限已更新');
|
||
} catch (err) {
|
||
this._fail(err, '更新权限失败');
|
||
}
|
||
}
|
||
|
||
/** PUT /api/admin/admin-users/:id/password */
|
||
async resetPassword() {
|
||
const { ctx, service } = this;
|
||
try {
|
||
const result = await service.adminUser.resetPassword(ctx.params.id, ctx.request.body || {});
|
||
ctx.body = ctx.helper.success(result, '口令已重置,该账号需重新登录');
|
||
} catch (err) {
|
||
this._fail(err, '重置口令失败');
|
||
}
|
||
}
|
||
|
||
/** PUT /api/admin/admin-users/:id/status */
|
||
async setStatus() {
|
||
const { ctx, service } = this;
|
||
try {
|
||
const result = await service.adminUser.setStatus(ctx.params.id, ctx.request.body || {});
|
||
const msg = Number(result.status) === 1 ? '账号已启用' : '账号已禁用,其在线会话已失效';
|
||
ctx.body = ctx.helper.success(result, msg);
|
||
} catch (err) {
|
||
this._fail(err, '修改账号状态失败');
|
||
}
|
||
}
|
||
|
||
/** DELETE /api/admin/admin-users/:id */
|
||
async remove() {
|
||
const { ctx, service } = this;
|
||
try {
|
||
const result = await service.adminUser.remove(ctx.params.id);
|
||
ctx.body = ctx.helper.success(result, '管理员账号已删除');
|
||
} catch (err) {
|
||
this._fail(err, '删除管理员失败');
|
||
}
|
||
}
|
||
}
|
||
|
||
module.exports = AdminUserController;
|