完善半自动履约凭证与客户重新授权流程
统一虎牙和微博账号级 CK 保存与导出;CK 失效后回到客户重新登录,后台支持重发授权;客户授权页改为统一深色布局并收敛开发迁移配置。
This commit is contained in:
@@ -15,13 +15,18 @@ test(
|
||||
async () => {
|
||||
process.env.DATABASE_URL = TEST_DATABASE_URL
|
||||
const { closeDb, query } = await import('../../db/client.js')
|
||||
const { ensureSemiAutoTasksForOrder, listAdminSemiAutoTasks, listPublicSemiAutoTasks } =
|
||||
await import('./semi-auto-task-service.js')
|
||||
const {
|
||||
ensureSemiAutoTasksForOrder,
|
||||
listAdminSemiAutoTasks,
|
||||
listPublicSemiAutoTasks,
|
||||
requestAdminSemiAutoCustomerReauth,
|
||||
} = await import('./semi-auto-task-service.js')
|
||||
const suffix = `${Date.now()}_${Math.floor(Math.random() * 1_000_000)}`
|
||||
const orderNo = `IT-SEMI-AUTO-${suffix}`
|
||||
const skuKey = `半自动测试-${suffix}`
|
||||
let orderId = 0
|
||||
let configId = 0
|
||||
let credentialId = 0
|
||||
try {
|
||||
const order = await query<{ id: number }>(
|
||||
`
|
||||
@@ -102,8 +107,61 @@ test(
|
||||
assert.equal(tasks[0]?.orderNo, orderNo)
|
||||
assert.equal(tasks[0]?.quantity, 1)
|
||||
assert.equal(tasks[0]?.semiAutoConfig.pageTitle, '虎牙授权测试')
|
||||
|
||||
const taskId = Number(tasks[0]?.id || 0)
|
||||
const credential = await query<{ id: number }>(
|
||||
`
|
||||
INSERT INTO semi_auto_credentials (
|
||||
platform, platform_uid, platform_nickname, credential_payload_json,
|
||||
credential_source, credential_status, credential_updated_at,
|
||||
last_checked_at, last_check_error, created_at, updated_at
|
||||
) VALUES (
|
||||
'huya', $1, '集成测试虎牙', '{"cookies":[]}',
|
||||
'qr', 'invalid', NOW(), NOW(), 'CK 已失效', NOW(), NOW()
|
||||
) RETURNING id
|
||||
`,
|
||||
[`it-huya-${suffix}`],
|
||||
)
|
||||
credentialId = Number(credential.rows[0]?.id || 0)
|
||||
await query(
|
||||
`
|
||||
UPDATE semi_auto_tasks
|
||||
SET credential_id = $2,
|
||||
connector_session_id = $3,
|
||||
login_status = 'authenticated',
|
||||
binding_status = 'confirmed',
|
||||
execution_status = 'waiting_operator',
|
||||
customer_link_opened_at = NOW(),
|
||||
authenticated_at = NOW(),
|
||||
bound_at = NOW(),
|
||||
updated_at = NOW()
|
||||
WHERE id = $1
|
||||
`,
|
||||
[taskId, credentialId, `it-huya-session-${suffix}`],
|
||||
)
|
||||
|
||||
const reauthorized = await requestAdminSemiAutoCustomerReauth(taskId, {
|
||||
userId: 1,
|
||||
role: 'support',
|
||||
displayName: '集成测试客服',
|
||||
} as never)
|
||||
assert.equal(reauthorized.task.loginStatus, 'waiting_login')
|
||||
assert.equal(reauthorized.task.bindingStatus, 'not_started')
|
||||
assert.equal(reauthorized.task.executionStatus, 'waiting_customer')
|
||||
assert.equal(reauthorized.task.customerLinkOpenedAt, null)
|
||||
const retainedCredential = await query<{ credential_id: number }>(
|
||||
'SELECT credential_id FROM semi_auto_tasks WHERE id = $1',
|
||||
[taskId],
|
||||
)
|
||||
assert.equal(Number(retainedCredential.rows[0]?.credential_id), credentialId)
|
||||
assert.ok(
|
||||
reauthorized.events.some((event) => event.eventType === 'customer_reauth_requested'),
|
||||
)
|
||||
} finally {
|
||||
if (orderId > 0) await query('DELETE FROM orders WHERE id = $1', [orderId])
|
||||
if (credentialId > 0) {
|
||||
await query('DELETE FROM semi_auto_credentials WHERE id = $1', [credentialId])
|
||||
}
|
||||
if (configId > 0) {
|
||||
await query('DELETE FROM manual_fulfillment_configs WHERE id = $1', [configId])
|
||||
}
|
||||
@@ -341,12 +399,10 @@ test(
|
||||
)
|
||||
|
||||
test(
|
||||
'微博账号 CK 以账号级密文保存并可解密加载',
|
||||
'微博账号 CK 以账号级 Cookie JSON 保存并可加载',
|
||||
{ skip: !TEST_DATABASE_URL ? '未设置 SEMI_AUTO_TASK_TEST_DATABASE_URL' : false },
|
||||
async () => {
|
||||
process.env.DATABASE_URL = TEST_DATABASE_URL
|
||||
process.env.SEMI_AUTO_CREDENTIAL_ENCRYPTION_KEY =
|
||||
'integration-test-semi-auto-credential-key-123456'
|
||||
const { closeDb, query, withTransaction } = await import('../../db/client.js')
|
||||
const { loadSemiAutoCredential, upsertSemiAutoCredentialWithClient } =
|
||||
await import('./semi-auto-credential-service.js')
|
||||
@@ -374,18 +430,17 @@ test(
|
||||
}),
|
||||
)
|
||||
const raw = await query<{
|
||||
credential_ciphertext: string
|
||||
credential_payload_json: string
|
||||
credential_source: string
|
||||
credential_status: string
|
||||
}>(
|
||||
`SELECT credential_ciphertext, credential_source, credential_status
|
||||
`SELECT credential_payload_json, credential_source, credential_status
|
||||
FROM semi_auto_credentials WHERE id = $1`,
|
||||
[credentialId],
|
||||
)
|
||||
assert.equal(raw.rows[0]?.credential_source, 'sms')
|
||||
assert.equal(raw.rows[0]?.credential_status, 'valid')
|
||||
assert.ok(raw.rows[0]?.credential_ciphertext.startsWith('enc:v1:'))
|
||||
assert.equal(raw.rows[0]?.credential_ciphertext.includes(`secret-sub-${suffix}`), false)
|
||||
assert.match(raw.rows[0]?.credential_payload_json || '', /"cookies"/)
|
||||
|
||||
const credential = await loadSemiAutoCredential(credentialId)
|
||||
assert.equal(credential?.platformUid, `it-weibo-${suffix}`)
|
||||
@@ -394,7 +449,6 @@ test(
|
||||
if (credentialId > 0) {
|
||||
await query('DELETE FROM semi_auto_credentials WHERE id = $1', [credentialId])
|
||||
}
|
||||
delete process.env.SEMI_AUTO_CREDENTIAL_ENCRYPTION_KEY
|
||||
await closeDb()
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user