feat(students,teachers,classes,auth,web): 学生个人账号彻底清理,学生只是名单记录
学生不再有登录能力:User.passwordHash 以空串占位,role=STUDENT 在密码校验之前 一律 403 并提示改用班级登录(否则「密码错 401 / 密码对但已停用 403」的差异会把 学生账号密码变成可离线验证的预言机)。成绩、未交名单、叫人、已读全部按名单记。 配套改动: - 删除 POST /students/:id/reset-password(调用返回 404,e2e 有负断言); - 新建学生不设密码,StudentsView 移除密码输入与「重置密码」入口, 列表标识仍自动生成为学号式(student01…); - class-account.ts / auth.service.ts 收紧班级会话语义; - 经管「修改密码」入口收敛到 Web 端:教师改本人密码走顶栏下拉, 班级密码由管理员在班级管理里维护,教师可用 POST /teachers/:id/reset-password 设初始密码。
This commit is contained in:
1 parent
7ea0e0f7c9
commit
d27f9a4b9e
11 files changed
+121
-104
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import { z } from 'zod';
|
||||
import { CLASSISLAND_NOTIFICATION_CHANNELS } from '@classhelper/shared';
|
||||
import { CLASSISLAND_NOTIFICATION_CHANNELS, MAX_TERM_WEEK } from '@classhelper/shared';
|
||||
import { keywordSchema } from '../../lib/schemas.js';
|
||||
|
||||
export const createClassSchema = z.object({
|
||||
@@ -13,13 +13,19 @@ export const createClassSchema = z.object({
|
||||
.trim()
|
||||
.regex(/^[A-Za-z0-9]{4,16}$/, '班级码需为 4~16 位字母或数字')
|
||||
.optional(),
|
||||
/**
|
||||
* 本学期教学周数。上限与课表周次口径统一取 MAX_TERM_WEEK(30):
|
||||
* 周次选择器与 weekNumberSchema 都只到 30,允许更大的值只会让用户设出一个
|
||||
* 系统兑现不了的学期长度(第 31 周之后永远为空)。
|
||||
*/
|
||||
termWeeks: z.coerce.number().int().min(1).max(MAX_TERM_WEEK).optional(),
|
||||
});
|
||||
|
||||
export const updateClassSchema = z.object({
|
||||
name: z.string().trim().min(1).max(64).optional(),
|
||||
grade: z.string().trim().min(1).max(32).optional(),
|
||||
/** 本学期教学周数(1~40,班主任可调) */
|
||||
termWeeks: z.coerce.number().int().min(1).max(40).optional(),
|
||||
/** 本学期教学周数(1~30,管理员可调) */
|
||||
termWeeks: z.coerce.number().int().min(1).max(MAX_TERM_WEEK).optional(),
|
||||
});
|
||||
|
||||
/** 设置 / 重置班级账号(班级码 + 班级密码):仅管理员 */
|
||||
@@ -43,7 +49,6 @@ export const listClassesQuerySchema = z.object({
|
||||
export const addStudentSchema = z.object({
|
||||
username: z.string().trim().min(3, '用户名至少 3 位').max(32),
|
||||
name: z.string().trim().min(1, '请输入姓名').max(32),
|
||||
password: z.string().min(6, '密码至少 6 位').max(128).optional(),
|
||||
});
|
||||
|
||||
export const assignTeacherSchema = z.object({
|
||||
|
||||
@@ -28,7 +28,6 @@ import {
|
||||
toStudentDto,
|
||||
toTeacherBrief,
|
||||
} from '../../lib/mappers.js';
|
||||
import { hashPassword } from '../../lib/password.js';
|
||||
import { emitToClass } from '../../realtime/bus.js';
|
||||
import { SOCKET_EVENTS } from '@classhelper/shared';
|
||||
import type {
|
||||
@@ -152,6 +151,8 @@ export async function createClass(user: TokenPayload, input: CreateClassInput):
|
||||
teacherId,
|
||||
code: account.code,
|
||||
passwordHash: account.passwordHash,
|
||||
// 新建时就能指定学期周数(之前只有编辑接口支持,Web 端表单里填了也会被丢弃)
|
||||
...(input.termWeeks !== undefined ? { termWeeks: input.termWeeks } : {}),
|
||||
},
|
||||
include: {
|
||||
teacher: { select: { id: true, name: true, username: true } },
|
||||
@@ -228,7 +229,7 @@ export async function updateClass(
|
||||
data: {
|
||||
...(input.name ? { name: input.name } : {}),
|
||||
...(input.grade ? { grade: input.grade } : {}),
|
||||
// 教学周数(班主任可调):课表周次选择与默认 weekEnd 都用它
|
||||
// 教学周数(仅管理员可调,见 assertCanManageClasses):课表周次选择与默认 weekEnd 都用它
|
||||
...(input.termWeeks !== undefined ? { termWeeks: input.termWeeks } : {}),
|
||||
},
|
||||
include: {
|
||||
@@ -260,9 +261,9 @@ export async function listClassStudents(user: TokenPayload, classId: string): Pr
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加学生到班级。
|
||||
* 已存在的学生账号直接转入本班(同时维护 Enrollment,保证"一个学生一个主班级")。
|
||||
* 新账号使用 DEFAULT_STUDENT_PASSWORD 作为初始密码。
|
||||
* 添加学生到班级(名单实体)。
|
||||
* 已存在的学生直接转入本班(同时维护 Enrollment,保证"一个学生一个主班级")。
|
||||
* 学生没有账号属性:不设密码、不能登录,学生端统一用班级码 + 班级密码。
|
||||
*/
|
||||
export async function addStudent(
|
||||
user: TokenPayload,
|
||||
@@ -292,7 +293,8 @@ export async function addStudent(
|
||||
name: input.name,
|
||||
role: 'STUDENT',
|
||||
classId,
|
||||
passwordHash: await hashPassword(input.password ?? env.defaultStudentPassword),
|
||||
// 空串占位:User.passwordHash 必填,但学生的 403 登录判定在密码校验之前,永远用不到
|
||||
passwordHash: '',
|
||||
},
|
||||
});
|
||||
studentId = created.id;
|
||||
|
||||
Reference in new issue
Block a user