169 lines
4.9 KiB
JavaScript
169 lines
4.9 KiB
JavaScript
/**
|
|
* WalkGuide — JWT Token Management Helper
|
|
* Mengelola login, penyimpanan token, dan auto-refresh untuk k6 VUs.
|
|
*/
|
|
import { check, sleep } from "k6";
|
|
import * as api from "./api-client.js";
|
|
import { testData } from "./test-data.js";
|
|
|
|
// ── Shared token cache (per VU, tidak cross-VU karena k6 isolasi per VU) ────
|
|
let _cachedTokens = null; // { accessToken, refreshToken, role, userId, uniqueUserId }
|
|
|
|
/**
|
|
* Login dan simpan token di memory VU ini.
|
|
* Return { accessToken, refreshToken, role, userId }
|
|
*/
|
|
export function loginAndStore(email, password) {
|
|
const res = api.login(email, password);
|
|
check(res, { "auth-helper: login 200": (r) => r.status === 200 });
|
|
|
|
if (res.status !== 200) {
|
|
console.error(
|
|
`[auth-helper] Login failed for ${email}: ${res.status} ${res.body}`,
|
|
);
|
|
return null;
|
|
}
|
|
|
|
const body = api.parseBody(res);
|
|
if (!body || !body.data || !body.data.accessToken) {
|
|
console.error(`[auth-helper] Unexpected login response: ${res.body}`);
|
|
return null;
|
|
}
|
|
|
|
_cachedTokens = {
|
|
accessToken: body.data.accessToken,
|
|
refreshToken: body.data.refreshToken,
|
|
role: body.data.role,
|
|
userId: body.data.userId,
|
|
uniqueUserId: body.data.uniqueUserId || null,
|
|
};
|
|
return _cachedTokens;
|
|
}
|
|
|
|
/**
|
|
* Register user baru, lalu login. Return token set.
|
|
*/
|
|
export function registerAndLogin(payload) {
|
|
const regRes = api.register(payload);
|
|
check(regRes, {
|
|
"auth-helper: register 2xx": (r) => r.status >= 200 && r.status < 300,
|
|
});
|
|
|
|
if (regRes.status !== 200 && regRes.status !== 201) {
|
|
// Mungkin email sudah ada — coba login saja
|
|
console.warn(
|
|
`[auth-helper] Register failed (${regRes.status}), attempting login.`,
|
|
);
|
|
}
|
|
|
|
const body = api.parseBody(regRes);
|
|
// Kalau register langsung return token (sesuai AuthService):
|
|
if (body && body.data && body.data.accessToken) {
|
|
_cachedTokens = {
|
|
accessToken: body.data.accessToken,
|
|
refreshToken: body.data.refreshToken,
|
|
role: body.data.role,
|
|
userId: body.data.userId,
|
|
uniqueUserId: body.data.uniqueUserId || null,
|
|
};
|
|
return _cachedTokens;
|
|
}
|
|
|
|
// Fallback: login manual
|
|
return loginAndStore(payload.email, payload.password);
|
|
}
|
|
|
|
/**
|
|
* Ambil access token dari cache. Kalau null, throw agar test gagal eksplisit.
|
|
*/
|
|
export function getAccessToken() {
|
|
if (!_cachedTokens || !_cachedTokens.accessToken) {
|
|
throw new Error(
|
|
"[auth-helper] No access token in cache. Call loginAndStore() first.",
|
|
);
|
|
}
|
|
return _cachedTokens.accessToken;
|
|
}
|
|
|
|
export function getRefreshToken() {
|
|
if (!_cachedTokens || !_cachedTokens.refreshToken) {
|
|
throw new Error("[auth-helper] No refresh token in cache.");
|
|
}
|
|
return _cachedTokens.refreshToken;
|
|
}
|
|
|
|
export function getCachedTokens() {
|
|
return _cachedTokens;
|
|
}
|
|
|
|
export function getCachedUniqueUserId() {
|
|
return _cachedTokens ? _cachedTokens.uniqueUserId : null;
|
|
}
|
|
|
|
/**
|
|
* Refresh access token menggunakan refresh token yang tersimpan.
|
|
* Update cache dengan access token baru.
|
|
*/
|
|
export function doRefreshToken() {
|
|
const rt = getRefreshToken();
|
|
const res = api.refreshToken(rt);
|
|
check(res, { "auth-helper: refresh 200": (r) => r.status === 200 });
|
|
|
|
if (res.status !== 200) {
|
|
console.error(`[auth-helper] Refresh token failed: ${res.status}`);
|
|
return null;
|
|
}
|
|
|
|
const body = api.parseBody(res);
|
|
if (body && body.data && body.data.accessToken) {
|
|
_cachedTokens.accessToken = body.data.accessToken;
|
|
}
|
|
return _cachedTokens.accessToken;
|
|
}
|
|
|
|
/**
|
|
* Clear semua cached token (simulasi logout).
|
|
*/
|
|
export function clearTokens() {
|
|
_cachedTokens = null;
|
|
}
|
|
|
|
// ── Pre-built credential sets untuk smoke/load test ──────────────────────────
|
|
// Test users yang sudah ada di DB kampus (V2__seed_users.sql)
|
|
// Jika tidak ada, gunakan dynamic register.
|
|
|
|
export const PREBUILT_GUARDIAN = {
|
|
email: __ENV.GUARDIAN_EMAIL || "guardian@walkguide.test",
|
|
password: __ENV.GUARDIAN_PASSWORD || "Guardian123!",
|
|
};
|
|
|
|
export const PREBUILT_USER = {
|
|
email: __ENV.USER_EMAIL || "user@walkguide.test",
|
|
password: __ENV.USER_PASSWORD || "User123!",
|
|
};
|
|
|
|
/**
|
|
* Setup pair: register guardian + user, lalu pairing.
|
|
* Return { guardianTokens, userTokens }
|
|
*/
|
|
export function setupPairedSession() {
|
|
const suffix = `${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;
|
|
|
|
// Register guardian
|
|
const gPayload = testData.guardianRegisterPayload(suffix);
|
|
const gTokens = registerAndLogin(gPayload);
|
|
if (!gTokens) return null;
|
|
|
|
// Register user
|
|
const uPayload = testData.userRegisterPayload(suffix);
|
|
const uTokens = registerAndLogin(uPayload);
|
|
if (!uTokens) return null;
|
|
|
|
return {
|
|
guardianTokens: gTokens,
|
|
userTokens: uTokens,
|
|
guardianPayload: gPayload,
|
|
userPayload: uPayload,
|
|
};
|
|
}
|