GuDingZiChan/backend/src/middleware/__tests__/auth.priority.test.ts

196 lines
5.8 KiB
TypeScript

import test from 'node:test'
import assert from 'node:assert/strict'
import prisma from '../../utils/prisma'
import { keycloak } from '../../utils/keycloak'
import { protect } from '../auth'
const makeUser = (id: number, username: string) => ({
id,
username,
password: 'hidden',
name: username,
email: null,
phone: null,
role: 'admin',
status: 'active',
person_id: null,
person: null
})
const createResponse = () => {
const state = { statusCode: 200, body: null as any, nextCount: 0 }
const res = {
locals: {} as any,
status(code: number) {
state.statusCode = code
return this
},
json(payload: any) {
state.body = payload
return this
}
}
const next = () => {
state.nextCount += 1
}
return { res, next, state }
}
test('Keycloak 模式下真实 Bearer 令牌优先于旧的钉钉 H5 session', async () => {
const originalMode = process.env.AUTH_MODE
const originalProtect = keycloak.protect
const originalFindUnique = prisma.user.findUnique
const lookups: any[] = []
process.env.AUTH_MODE = 'keycloak'
;(keycloak.protect as any) = () => async (req: any, _res: any, next: any) => {
req.kauth = {
grant: {
access_token: {
content: {
preferred_username: 'keycloak-user',
name: 'Keycloak User',
realm_access: { roles: ['ignored-external-role'] }
}
}
}
}
return next()
}
;(prisma.user.findUnique as any) = async (args: any) => {
lookups.push(args.where)
if (args.where.username === 'keycloak-user') return makeUser(22, 'keycloak-user')
if (args.where.id === 11) return makeUser(11, 'old-dingtalk-session')
return null
}
try {
const middleware = protect()
const req = {
headers: { authorization: 'Bearer real-keycloak-token' },
session: { user: { id: 11 } }
}
const { res, next, state } = createResponse()
await middleware(req as any, res as any, next as any)
assert.equal(state.nextCount, 1)
assert.equal(res.locals.user.id, 22)
assert.deepEqual(lookups, [{ username: 'keycloak-user' }])
} finally {
if (originalMode === undefined) delete process.env.AUTH_MODE
else process.env.AUTH_MODE = originalMode
;(keycloak.protect as any) = originalProtect
;(prisma.user.findUnique as any) = originalFindUnique
}
})
test('Keycloak 模式下 Bearer session 占位值仍使用 H5 session', async () => {
const originalMode = process.env.AUTH_MODE
const originalProtect = keycloak.protect
const originalFindUnique = prisma.user.findUnique
let keycloakCalled = 0
process.env.AUTH_MODE = 'keycloak'
;(keycloak.protect as any) = () => async (_req: any, _res: any, next: any) => {
keycloakCalled += 1
return next()
}
;(prisma.user.findUnique as any) = async (args: any) => {
if (args.where.id === 11) return makeUser(11, 'dingtalk-session')
return null
}
try {
const middleware = protect()
const req = {
headers: { authorization: 'Bearer session' },
session: { user: { id: 11 } }
}
const { res, next, state } = createResponse()
await middleware(req as any, res as any, next as any)
assert.equal(state.nextCount, 1)
assert.equal(keycloakCalled, 0)
assert.equal(res.locals.user.id, 11)
} finally {
if (originalMode === undefined) delete process.env.AUTH_MODE
else process.env.AUTH_MODE = originalMode
;(keycloak.protect as any) = originalProtect
;(prisma.user.findUnique as any) = originalFindUnique
}
})
test('local 模式即使带真实 Bearer 也只使用本地 session', async () => {
const originalMode = process.env.AUTH_MODE
const originalFindUnique = prisma.user.findUnique
process.env.AUTH_MODE = 'local'
;(prisma.user.findUnique as any) = async (args: any) => {
if (args.where.id === 31) return makeUser(31, 'local-session')
return null
}
try {
const middleware = protect()
const req = {
headers: { authorization: 'Bearer should-not-win' },
session: { user: { id: 31 } }
}
const { res, next, state } = createResponse()
await middleware(req as any, res as any, next as any)
assert.equal(state.nextCount, 1)
assert.equal(res.locals.user.id, 31)
} finally {
if (originalMode === undefined) delete process.env.AUTH_MODE
else process.env.AUTH_MODE = originalMode
;(prisma.user.findUnique as any) = originalFindUnique
}
})
test('钉钉会话在员工改绑后立即失效且不继续读取系统用户', async () => {
const originalMode = process.env.AUTH_MODE
const originalFindFirst = prisma.user.findFirst
const originalFindUnique = prisma.user.findUnique
let findUniqueCalls = 0
process.env.AUTH_MODE = 'local'
;(prisma.user.findFirst as any) = async (args: any) => {
assert.equal(args.where.id, 41)
assert.equal(args.where.person.is.source_userid, 'ding-user-a')
return null
}
;(prisma.user.findUnique as any) = async () => {
findUniqueCalls += 1
return makeUser(41, 'rebound-user')
}
try {
const middleware = protect()
const req = {
headers: {},
session: {
user: {
id: 41,
auth_source: 'dingtalk',
dingtalk_userid: 'ding-user-a'
}
}
}
const { res, next, state } = createResponse()
await middleware(req as any, res as any, next as any)
assert.equal(state.nextCount, 0)
assert.equal(state.statusCode, 401)
assert.equal(state.body.message, '钉钉绑定已失效,请重新登录或联系管理员')
assert.equal(req.session.user, undefined)
assert.equal(findUniqueCalls, 0)
} finally {
if (originalMode === undefined) delete process.env.AUTH_MODE
else process.env.AUTH_MODE = originalMode
;(prisma.user.findFirst as any) = originalFindFirst
;(prisma.user.findUnique as any) = originalFindUnique
}
})