Update password reset endpoint and add verification script
This commit is contained in:
parent
143aad11d8
commit
4ef8a6057d
16
apps/portal/scripts/stubs/core-api.ts
Normal file
16
apps/portal/scripts/stubs/core-api.ts
Normal file
@ -0,0 +1,16 @@
|
||||
export type PostCall = [path: string, options?: unknown];
|
||||
|
||||
export const postCalls: PostCall[] = [];
|
||||
|
||||
export const apiClient = {
|
||||
POST: async (path: string, options?: unknown) => {
|
||||
postCalls.push([path, options]);
|
||||
return { data: null } as const;
|
||||
},
|
||||
GET: async () => ({ data: null } as const),
|
||||
PUT: async () => ({ data: null } as const),
|
||||
PATCH: async () => ({ data: null } as const),
|
||||
DELETE: async () => ({ data: null } as const),
|
||||
};
|
||||
|
||||
export const configureApiClientAuth = () => undefined;
|
||||
119
apps/portal/scripts/test-request-password-reset.cjs
Executable file
119
apps/portal/scripts/test-request-password-reset.cjs
Executable file
@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fs = require("node:fs");
|
||||
const path = require("node:path");
|
||||
const Module = require("node:module");
|
||||
const ts = require("typescript");
|
||||
|
||||
const srcRoot = path.join(path.resolve(__dirname, ".."), "src");
|
||||
|
||||
const registerTsCompiler = extension => {
|
||||
require.extensions[extension] = (module, filename) => {
|
||||
const source = fs.readFileSync(filename, "utf8");
|
||||
const { outputText } = ts.transpileModule(source, {
|
||||
compilerOptions: {
|
||||
module: ts.ModuleKind.CommonJS,
|
||||
target: ts.ScriptTarget.ES2020,
|
||||
jsx: ts.JsxEmit.ReactJSX,
|
||||
esModuleInterop: true,
|
||||
moduleResolution: ts.ModuleResolutionKind.NodeNext,
|
||||
resolveJsonModule: true,
|
||||
skipLibCheck: true,
|
||||
},
|
||||
fileName: filename,
|
||||
});
|
||||
|
||||
module._compile(outputText, filename);
|
||||
};
|
||||
};
|
||||
|
||||
registerTsCompiler(".ts");
|
||||
registerTsCompiler(".tsx");
|
||||
|
||||
const originalResolveFilename = Module._resolveFilename;
|
||||
Module._resolveFilename = function resolve(request, parent, isMain, options) {
|
||||
if (request === "@/core/api") {
|
||||
const stubPath = path.resolve(__dirname, "stubs/core-api.ts");
|
||||
return originalResolveFilename.call(this, stubPath, parent, isMain, options);
|
||||
}
|
||||
|
||||
if (request.startsWith("@/")) {
|
||||
const resolved = path.resolve(srcRoot, request.slice(2));
|
||||
return originalResolveFilename.call(this, resolved, parent, isMain, options);
|
||||
}
|
||||
|
||||
return originalResolveFilename.call(this, request, parent, isMain, options);
|
||||
};
|
||||
|
||||
class LocalStorageMock {
|
||||
constructor() {
|
||||
this._store = new Map();
|
||||
}
|
||||
|
||||
clear() {
|
||||
this._store.clear();
|
||||
}
|
||||
|
||||
getItem(key) {
|
||||
return this._store.has(key) ? this._store.get(key) : null;
|
||||
}
|
||||
|
||||
key(index) {
|
||||
return Array.from(this._store.keys())[index] ?? null;
|
||||
}
|
||||
|
||||
removeItem(key) {
|
||||
this._store.delete(key);
|
||||
}
|
||||
|
||||
setItem(key, value) {
|
||||
this._store.set(key, String(value));
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this._store.size;
|
||||
}
|
||||
}
|
||||
|
||||
global.localStorage = new LocalStorageMock();
|
||||
|
||||
const coreApiStub = require("./stubs/core-api.ts");
|
||||
coreApiStub.postCalls.length = 0;
|
||||
|
||||
const { useAuthStore } = require("../src/features/auth/services/auth.store.ts");
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
const payload = { email: "tester@example.com" };
|
||||
await useAuthStore.getState().requestPasswordReset(payload);
|
||||
|
||||
if (coreApiStub.postCalls.length !== 1) {
|
||||
throw new Error(`Expected 1 POST call, received ${coreApiStub.postCalls.length}`);
|
||||
}
|
||||
|
||||
const [endpoint, options] = coreApiStub.postCalls[0];
|
||||
if (endpoint !== "/auth/request-password-reset") {
|
||||
throw new Error(`Expected endpoint \"/auth/request-password-reset\" but received \"${endpoint}\"`);
|
||||
}
|
||||
|
||||
if (!options || typeof options !== "object") {
|
||||
throw new Error("Password reset request did not include options payload");
|
||||
}
|
||||
|
||||
const body = options.body;
|
||||
if (!body || typeof body !== "object") {
|
||||
throw new Error("Password reset request did not include a body");
|
||||
}
|
||||
|
||||
if (body.email !== payload.email) {
|
||||
throw new Error(
|
||||
`Expected request body email to be \"${payload.email}\" but received \"${body.email}\"`
|
||||
);
|
||||
}
|
||||
|
||||
console.log("Password reset request forwarded correctly:", { endpoint, body });
|
||||
} catch (error) {
|
||||
console.error("Password reset request verification failed:", error);
|
||||
process.exitCode = 1;
|
||||
}
|
||||
})();
|
||||
@ -53,8 +53,8 @@ export function useAuth() {
|
||||
|
||||
// Password reset request
|
||||
const passwordResetMutation = useMutation({
|
||||
mutationFn: (data: ForgotPasswordRequest) =>
|
||||
apiClient.POST('/auth/forgot-password', { body: data }),
|
||||
mutationFn: (data: ForgotPasswordRequest) =>
|
||||
apiClient.POST('/auth/request-password-reset', { body: data }),
|
||||
});
|
||||
|
||||
// Password reset
|
||||
|
||||
@ -208,7 +208,7 @@ export const useAuthStore = create<AuthStoreState>()(
|
||||
requestPasswordReset: async (data: ForgotPasswordRequest) => {
|
||||
set({ loading: true, error: null });
|
||||
try {
|
||||
await apiClient.POST('/auth/forgot-password', { body: data });
|
||||
await apiClient.POST('/auth/request-password-reset', { body: data });
|
||||
set({ loading: false });
|
||||
} catch (error) {
|
||||
const authError = error as AuthError;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user