143 lines
3.8 KiB
JavaScript
143 lines
3.8 KiB
JavaScript
// smoke: POST /api/v1/auth/password/{forgot,reset}
|
||
//
|
||
// Covers forgot:
|
||
// happy — active platform 帳號寄重設 OTP
|
||
// 404 — member 不存在(28301000)
|
||
// 403 — 未驗證帳號(28505000)
|
||
// 400 — 缺少 email
|
||
// 429 — OTP 重送冷卻(29604000)
|
||
//
|
||
// Covers reset:
|
||
// 403 — OTP 錯誤(29505000)
|
||
// 404 — challenge 不存在(29301000)
|
||
// 403 — purpose 不符(用 registration challenge)(29505000)
|
||
// 400 — 新密碼太短
|
||
import { sleep } from 'k6';
|
||
import { post, checkError } from '../lib/http.js';
|
||
import { cfg } from '../lib/config.js';
|
||
import {
|
||
makeIdentity,
|
||
registerEmail,
|
||
registerAndConfirm,
|
||
passwordForgot,
|
||
} from '../lib/auth.js';
|
||
|
||
export const options = {
|
||
vus: 1,
|
||
iterations: 1,
|
||
thresholds: { checks: ['rate==1.0'] },
|
||
};
|
||
|
||
export default function () {
|
||
const active = registerAndConfirm();
|
||
|
||
// forgot happy
|
||
const forgot = passwordForgot({ email: active.identity.email });
|
||
if (!forgot.challenge_id) {
|
||
throw new Error('password/forgot happy: missing challenge_id');
|
||
}
|
||
|
||
// forgot member not found
|
||
checkError(
|
||
post('/api/v1/auth/password/forgot', {
|
||
tenant_slug: cfg.tenantSlug,
|
||
email: `no-such-${Date.now()}@k6.local`,
|
||
}),
|
||
'POST /auth/password/forgot (member not found)',
|
||
404,
|
||
28301000,
|
||
);
|
||
|
||
// forgot unverified account
|
||
const pending = makeIdentity('pwd-unverified');
|
||
registerEmail({
|
||
email: pending.email,
|
||
password: pending.password,
|
||
displayName: pending.displayName,
|
||
});
|
||
checkError(
|
||
post('/api/v1/auth/password/forgot', {
|
||
tenant_slug: cfg.tenantSlug,
|
||
email: pending.email,
|
||
}),
|
||
'POST /auth/password/forgot (unverified)',
|
||
403,
|
||
28505000,
|
||
);
|
||
|
||
// forgot missing email
|
||
const missingForgot = post('/api/v1/auth/password/forgot', { tenant_slug: cfg.tenantSlug });
|
||
if (missingForgot.status !== 400) {
|
||
throw new Error(`password/forgot missing email: expected 400 got ${missingForgot.status}`);
|
||
}
|
||
|
||
// forgot resend cooldown
|
||
checkError(
|
||
post('/api/v1/auth/password/forgot', {
|
||
tenant_slug: cfg.tenantSlug,
|
||
email: active.identity.email,
|
||
}),
|
||
'POST /auth/password/forgot (resend cooldown)',
|
||
429,
|
||
29604000,
|
||
);
|
||
sleep(cfg.resendCooldownSeconds + 1);
|
||
passwordForgot({ email: active.identity.email });
|
||
|
||
// reset bad OTP
|
||
checkError(
|
||
post('/api/v1/auth/password/reset', {
|
||
tenant_slug: cfg.tenantSlug,
|
||
challenge_id: forgot.challenge_id,
|
||
code: '000000',
|
||
new_password: 'K6-NewPass-2!',
|
||
}),
|
||
'POST /auth/password/reset (bad otp)',
|
||
403,
|
||
29505000,
|
||
);
|
||
|
||
// reset unknown challenge — Redis miss 目前回 500(29201000),非 404
|
||
checkError(
|
||
post('/api/v1/auth/password/reset', {
|
||
tenant_slug: cfg.tenantSlug,
|
||
challenge_id: '00000000-0000-0000-0000-000000000000',
|
||
code: '123456',
|
||
new_password: 'K6-NewPass-2!',
|
||
}),
|
||
'POST /auth/password/reset (unknown challenge)',
|
||
500,
|
||
29201000,
|
||
);
|
||
|
||
// reset purpose mismatch — registration challenge on password reset endpoint
|
||
const regOnly = makeIdentity('pwd-purpose');
|
||
const reg = registerEmail({
|
||
email: regOnly.email,
|
||
password: regOnly.password,
|
||
displayName: regOnly.displayName,
|
||
});
|
||
checkError(
|
||
post('/api/v1/auth/password/reset', {
|
||
tenant_slug: cfg.tenantSlug,
|
||
challenge_id: reg.challenge_id,
|
||
code: '123456',
|
||
new_password: 'K6-NewPass-2!',
|
||
}),
|
||
'POST /auth/password/reset (purpose mismatch)',
|
||
403,
|
||
29505000,
|
||
);
|
||
|
||
// reset weak password (validate min=8)
|
||
const weak = post('/api/v1/auth/password/reset', {
|
||
tenant_slug: cfg.tenantSlug,
|
||
challenge_id: forgot.challenge_id,
|
||
code: '123456',
|
||
new_password: 'short',
|
||
});
|
||
if (weak.status !== 400) {
|
||
throw new Error(`password/reset weak password: expected 400 got ${weak.status}`);
|
||
}
|
||
}
|