Merge pull request #14 from NTumurbars/codex/update-password-reset-endpoint-calls
Update password reset endpoint and add verification script
This commit is contained in:
commit
ff0dfa1021
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
|
// Password reset request
|
||||||
const passwordResetMutation = useMutation({
|
const passwordResetMutation = useMutation({
|
||||||
mutationFn: (data: ForgotPasswordRequest) =>
|
mutationFn: (data: ForgotPasswordRequest) =>
|
||||||
apiClient.POST('/auth/forgot-password', { body: data }),
|
apiClient.POST('/auth/request-password-reset', { body: data }),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Password reset
|
// Password reset
|
||||||
|
|||||||
@ -209,7 +209,7 @@ export const useAuthStore = create<AuthStoreState>()(
|
|||||||
requestPasswordReset: async (data: ForgotPasswordRequest) => {
|
requestPasswordReset: async (data: ForgotPasswordRequest) => {
|
||||||
set({ loading: true, error: null });
|
set({ loading: true, error: null });
|
||||||
try {
|
try {
|
||||||
await apiClient.POST('/auth/forgot-password', { body: data });
|
await apiClient.POST('/auth/request-password-reset', { body: data });
|
||||||
set({ loading: false });
|
set({ loading: false });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const authError = error as AuthError;
|
const authError = error as AuthError;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user