feat: 冻结/拒绝的打手账号禁止登录
- loginWorker 仅允许 active 状态登录,rejected(冻结)/pending_review/disabled 均拦截并返回对应错误码 - verifyWorkerSessionToken 对非 active 状态直接失效会话,冻结后已登录会话立即退出 - 补充 assertWorkerLoginAllowed 四种状态的单元测试
This commit is contained in:
@@ -1,8 +1,71 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import test from 'node:test'
|
||||
|
||||
import type { WorkOrderRow } from '../../repositories/worker-platform/index.js'
|
||||
import { resolveCollectSubmitTargetWorkOrder } from './index.js'
|
||||
import type { WorkOrderRow, WorkerUserRow } from '../../repositories/worker-platform/index.js'
|
||||
import { assertWorkerLoginAllowed, resolveCollectSubmitTargetWorkOrder } from './index.js'
|
||||
|
||||
function buildWorkerUserRow(overrides: Partial<WorkerUserRow> = {}): WorkerUserRow {
|
||||
return {
|
||||
id: 1,
|
||||
username: 'jd01',
|
||||
password_hash: 'scrypt$salt$hash',
|
||||
display_name: '测试打手',
|
||||
phone: '',
|
||||
level_id: 1,
|
||||
status: 'active',
|
||||
review_note: '',
|
||||
session_version: 1,
|
||||
created_at: '2026-07-28T00:00:00.000Z',
|
||||
updated_at: '2026-07-28T00:00:00.000Z',
|
||||
reviewed_at: null,
|
||||
inviter_id: null,
|
||||
invite_code: 'TEST0001',
|
||||
...overrides,
|
||||
}
|
||||
}
|
||||
|
||||
test('assertWorkerLoginAllowed allows active workers', () => {
|
||||
assert.doesNotThrow(() => assertWorkerLoginAllowed(buildWorkerUserRow()))
|
||||
})
|
||||
|
||||
test('assertWorkerLoginAllowed blocks rejected (frozen) workers with worker_rejected', () => {
|
||||
assert.throws(
|
||||
() => assertWorkerLoginAllowed(buildWorkerUserRow({ status: 'rejected' })),
|
||||
(error: unknown) =>
|
||||
Boolean(
|
||||
error &&
|
||||
typeof error === 'object' &&
|
||||
(error as { statusCode?: number }).statusCode === 403 &&
|
||||
(error as { errorCode?: string }).errorCode === 'worker_rejected',
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
test('assertWorkerLoginAllowed blocks pending review workers with worker_pending_review', () => {
|
||||
assert.throws(
|
||||
() => assertWorkerLoginAllowed(buildWorkerUserRow({ status: 'pending_review' })),
|
||||
(error: unknown) =>
|
||||
Boolean(
|
||||
error &&
|
||||
typeof error === 'object' &&
|
||||
(error as { statusCode?: number }).statusCode === 403 &&
|
||||
(error as { errorCode?: string }).errorCode === 'worker_pending_review',
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
test('assertWorkerLoginAllowed blocks disabled workers with worker_disabled', () => {
|
||||
assert.throws(
|
||||
() => assertWorkerLoginAllowed(buildWorkerUserRow({ status: 'disabled' })),
|
||||
(error: unknown) =>
|
||||
Boolean(
|
||||
error &&
|
||||
typeof error === 'object' &&
|
||||
(error as { statusCode?: number }).statusCode === 403 &&
|
||||
(error as { errorCode?: string }).errorCode === 'worker_disabled',
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
function buildWorkOrderRow(
|
||||
overrides: Partial<WorkOrderRow> = {},
|
||||
|
||||
@@ -335,14 +335,34 @@ export async function loginWorker(username: unknown, password: unknown) {
|
||||
})
|
||||
}
|
||||
|
||||
if (worker.status === 'disabled') {
|
||||
throw createHttpError('接单账号已停用', {
|
||||
assertWorkerLoginAllowed(worker)
|
||||
|
||||
return createWorkerSession(worker)
|
||||
}
|
||||
|
||||
export function assertWorkerLoginAllowed(worker: WorkerUserRow) {
|
||||
if (worker.status === 'active') {
|
||||
return
|
||||
}
|
||||
|
||||
if (worker.status === 'rejected') {
|
||||
throw createHttpError('接单账号已被冻结,无法登录', {
|
||||
statusCode: 403,
|
||||
errorCode: 'worker_disabled',
|
||||
errorCode: 'worker_rejected',
|
||||
})
|
||||
}
|
||||
|
||||
return createWorkerSession(worker)
|
||||
if (worker.status === 'pending_review') {
|
||||
throw createHttpError('接单账号待审核,暂无法登录', {
|
||||
statusCode: 403,
|
||||
errorCode: 'worker_pending_review',
|
||||
})
|
||||
}
|
||||
|
||||
throw createHttpError('接单账号已停用', {
|
||||
statusCode: 403,
|
||||
errorCode: 'worker_disabled',
|
||||
})
|
||||
}
|
||||
|
||||
export async function logoutWorkerSession(token: unknown) {
|
||||
@@ -411,7 +431,7 @@ export async function verifyWorkerSessionToken(token: unknown): Promise<WorkerSe
|
||||
|
||||
const workerId = Number(payload.uid || 0)
|
||||
const worker = await getWorkerUserById(workerId)
|
||||
if (!worker || worker.status === 'disabled') {
|
||||
if (!worker || worker.status !== 'active') {
|
||||
throw createHttpError('接单账号已不可用,请重新登录', {
|
||||
statusCode: 401,
|
||||
errorCode: 'worker_auth_user_invalid',
|
||||
|
||||
Reference in New Issue
Block a user