You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
174 lines
6.4 KiB
174 lines
6.4 KiB
import {
|
|
AUTH_HTTP_METHODS,
|
|
AUTH_ROUTE_PATHS
|
|
} from '$libs/auth/consts';
|
|
import {
|
|
authJson,
|
|
authRouteNotFound,
|
|
protectAuthHandler,
|
|
toAuthRequestLike,
|
|
verifyAuthRequestCsrf,
|
|
type AuthHandlerEngine,
|
|
type AuthRouteRequest
|
|
} from './handler-runtime.ts';
|
|
import type {
|
|
AuthEmailVerificationCompleteInput,
|
|
AuthEmailVerificationRequestInput,
|
|
AuthPasswordResetCompleteInput,
|
|
AuthPasswordResetRequestInput,
|
|
AuthSignInPasswordInput,
|
|
AuthSignUpPasswordInput
|
|
} from '$libs/auth/types';
|
|
|
|
export interface AuthRouteHandlers {
|
|
readonly current: (input: AuthRouteRequest) => Promise<Response>;
|
|
readonly csrf: (input: AuthRouteRequest) => Promise<Response>;
|
|
readonly signUpPassword: (input: AuthRouteRequest) => Promise<Response>;
|
|
readonly signInPassword: (input: AuthRouteRequest) => Promise<Response>;
|
|
readonly signOut: (input: AuthRouteRequest) => Promise<Response>;
|
|
readonly signOutGlobal: (input: AuthRouteRequest) => Promise<Response>;
|
|
readonly requestEmailVerification: (input: AuthRouteRequest) => Promise<Response>;
|
|
readonly completeEmailVerification: (input: AuthRouteRequest) => Promise<Response>;
|
|
readonly requestPasswordReset: (input: AuthRouteRequest) => Promise<Response>;
|
|
readonly completePasswordReset: (input: AuthRouteRequest) => Promise<Response>;
|
|
readonly handle: (input: AuthRouteRequest) => Promise<Response>;
|
|
}
|
|
|
|
export type { AuthRouteRequest } from './handler-runtime.ts';
|
|
|
|
export function createAuthRouteHandlers(engine: AuthHandlerEngine): AuthRouteHandlers {
|
|
async function current(input: AuthRouteRequest): Promise<Response> {
|
|
return protectAuthHandler(async () =>
|
|
authJson(
|
|
await engine.current({ tenantId: input.tenantId, request: toAuthRequestLike(input.request) })
|
|
)
|
|
);
|
|
}
|
|
|
|
async function csrf(input: AuthRouteRequest): Promise<Response> {
|
|
return protectAuthHandler(async () => {
|
|
const result = await engine.issueCsrf({ tenantId: input.tenantId });
|
|
return authJson(
|
|
{ token: result.token, expiresAt: result.expiresAt },
|
|
{ cookies: [result.cookie] }
|
|
);
|
|
});
|
|
}
|
|
|
|
async function signUpPassword(input: AuthRouteRequest): Promise<Response> {
|
|
return protectAuthHandler(async () => {
|
|
await verifyAuthRequestCsrf(engine, input);
|
|
const body = (await input.request.json()) as Omit<AuthSignUpPasswordInput, 'tenantId'>;
|
|
return authJson(await engine.signUpPassword({ ...body, tenantId: input.tenantId }));
|
|
});
|
|
}
|
|
|
|
async function signInPassword(input: AuthRouteRequest): Promise<Response> {
|
|
return protectAuthHandler(async () => {
|
|
await verifyAuthRequestCsrf(engine, input);
|
|
const body = (await input.request.json()) as Omit<AuthSignInPasswordInput, 'tenantId'>;
|
|
return authJson(await engine.signInPassword({ ...body, tenantId: input.tenantId }));
|
|
});
|
|
}
|
|
|
|
async function signOut(input: AuthRouteRequest): Promise<Response> {
|
|
return protectAuthHandler(async () => {
|
|
await verifyAuthRequestCsrf(engine, input);
|
|
return authJson(
|
|
await engine.signOut({ tenantId: input.tenantId, request: toAuthRequestLike(input.request) })
|
|
);
|
|
});
|
|
}
|
|
|
|
async function signOutGlobal(input: AuthRouteRequest): Promise<Response> {
|
|
return protectAuthHandler(async () => {
|
|
await verifyAuthRequestCsrf(engine, input);
|
|
return authJson(
|
|
await engine.signOutGlobal({
|
|
tenantId: input.tenantId,
|
|
request: toAuthRequestLike(input.request)
|
|
})
|
|
);
|
|
});
|
|
}
|
|
|
|
async function requestEmailVerification(input: AuthRouteRequest): Promise<Response> {
|
|
return protectAuthHandler(async () => {
|
|
await verifyAuthRequestCsrf(engine, input);
|
|
const body = (await input.request.json()) as Omit<
|
|
AuthEmailVerificationRequestInput,
|
|
'tenantId'
|
|
>;
|
|
return authJson(await engine.requestEmailVerification({ ...body, tenantId: input.tenantId }));
|
|
});
|
|
}
|
|
|
|
async function completeEmailVerification(input: AuthRouteRequest): Promise<Response> {
|
|
return protectAuthHandler(async () => {
|
|
await verifyAuthRequestCsrf(engine, input);
|
|
const body = (await input.request.json()) as Omit<
|
|
AuthEmailVerificationCompleteInput,
|
|
'tenantId'
|
|
>;
|
|
return authJson(
|
|
await engine.completeEmailVerification({ ...body, tenantId: input.tenantId })
|
|
);
|
|
});
|
|
}
|
|
|
|
async function requestPasswordReset(input: AuthRouteRequest): Promise<Response> {
|
|
return protectAuthHandler(async () => {
|
|
await verifyAuthRequestCsrf(engine, input);
|
|
const body = (await input.request.json()) as Omit<AuthPasswordResetRequestInput, 'tenantId'>;
|
|
return authJson(await engine.requestPasswordReset({ ...body, tenantId: input.tenantId }));
|
|
});
|
|
}
|
|
|
|
async function completePasswordReset(input: AuthRouteRequest): Promise<Response> {
|
|
return protectAuthHandler(async () => {
|
|
await verifyAuthRequestCsrf(engine, input);
|
|
const body = (await input.request.json()) as Omit<AuthPasswordResetCompleteInput, 'tenantId'>;
|
|
return authJson(await engine.completePasswordReset({ ...body, tenantId: input.tenantId }));
|
|
});
|
|
}
|
|
|
|
async function handle(input: AuthRouteRequest): Promise<Response> {
|
|
const pathname = new URL(input.request.url).pathname;
|
|
const method = input.request.method;
|
|
if (pathname === AUTH_ROUTE_PATHS.CURRENT && method === AUTH_HTTP_METHODS.GET)
|
|
return current(input);
|
|
if (pathname === AUTH_ROUTE_PATHS.CSRF && method === AUTH_HTTP_METHODS.GET) return csrf(input);
|
|
if (pathname === AUTH_ROUTE_PATHS.SIGN_UP_PASSWORD && method === AUTH_HTTP_METHODS.POST)
|
|
return signUpPassword(input);
|
|
if (pathname === AUTH_ROUTE_PATHS.SIGN_IN_PASSWORD && method === AUTH_HTTP_METHODS.POST)
|
|
return signInPassword(input);
|
|
if (pathname === AUTH_ROUTE_PATHS.SIGN_OUT && method === AUTH_HTTP_METHODS.POST)
|
|
return signOut(input);
|
|
if (pathname === AUTH_ROUTE_PATHS.SIGN_OUT_GLOBAL && method === AUTH_HTTP_METHODS.POST)
|
|
return signOutGlobal(input);
|
|
if (pathname === AUTH_ROUTE_PATHS.EMAIL_VERIFY_REQUEST && method === AUTH_HTTP_METHODS.POST)
|
|
return requestEmailVerification(input);
|
|
if (pathname === AUTH_ROUTE_PATHS.EMAIL_VERIFY_COMPLETE && method === AUTH_HTTP_METHODS.POST)
|
|
return completeEmailVerification(input);
|
|
if (pathname === AUTH_ROUTE_PATHS.PASSWORD_RESET_REQUEST && method === AUTH_HTTP_METHODS.POST)
|
|
return requestPasswordReset(input);
|
|
if (pathname === AUTH_ROUTE_PATHS.PASSWORD_RESET_COMPLETE && method === AUTH_HTTP_METHODS.POST)
|
|
return completePasswordReset(input);
|
|
return authRouteNotFound();
|
|
}
|
|
|
|
return {
|
|
current,
|
|
csrf,
|
|
signUpPassword,
|
|
signInPassword,
|
|
signOut,
|
|
signOutGlobal,
|
|
requestEmailVerification,
|
|
completeEmailVerification,
|
|
requestPasswordReset,
|
|
completePasswordReset,
|
|
handle
|
|
};
|
|
}
|