mirror of
https://github.com/LukeHagar/better-auth.git
synced 2025-12-09 12:27:43 +00:00
chore: move session to api
This commit is contained in:
@@ -39,11 +39,10 @@ export const auth = betterAuth({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
rateLimiter({
|
// rateLimiter({
|
||||||
enabled: true,
|
// enabled: true,
|
||||||
|
// max: 1000,
|
||||||
max: 1000,
|
// }),
|
||||||
}),
|
|
||||||
organization({
|
organization({
|
||||||
async sendInvitationEmail(data) {
|
async sendInvitationEmail(data) {
|
||||||
const res = await resend.emails.send({
|
const res = await resend.emails.send({
|
||||||
|
|||||||
@@ -81,7 +81,7 @@
|
|||||||
"@simplewebauthn/browser": "^10.0.0",
|
"@simplewebauthn/browser": "^10.0.0",
|
||||||
"@simplewebauthn/server": "^10.0.1",
|
"@simplewebauthn/server": "^10.0.1",
|
||||||
"arctic": "2.0.0-next.9",
|
"arctic": "2.0.0-next.9",
|
||||||
"better-call": "0.2.3-beta.3",
|
"better-call": "0.2.3-beta.8",
|
||||||
"better-sqlite3": "^11.1.2",
|
"better-sqlite3": "^11.1.2",
|
||||||
"c12": "^1.11.2",
|
"c12": "^1.11.2",
|
||||||
"chalk": "^5.3.0",
|
"chalk": "^5.3.0",
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ export const createAuthMiddleware = createMiddlewareCreator({
|
|||||||
use: [
|
use: [
|
||||||
optionsMiddleware,
|
optionsMiddleware,
|
||||||
/**
|
/**
|
||||||
* This of for hooks. to tell ts there will a
|
* Only use for post hooks
|
||||||
* return response object
|
|
||||||
*/
|
*/
|
||||||
createMiddleware(async () => {
|
createMiddleware(async () => {
|
||||||
return {} as {
|
return {} as {
|
||||||
|
|||||||
@@ -105,25 +105,29 @@ export function getEndpoints<
|
|||||||
let api: Record<string, any> = {};
|
let api: Record<string, any> = {};
|
||||||
for (const [key, value] of Object.entries(endpoints)) {
|
for (const [key, value] of Object.entries(endpoints)) {
|
||||||
api[key] = async (context: any) => {
|
api[key] = async (context: any) => {
|
||||||
for (const plugin of ctx.options.plugins || []) {
|
// for (const plugin of ctx.options.plugins || []) {
|
||||||
if (plugin.hooks?.before) {
|
// if (plugin.hooks?.before) {
|
||||||
for (const hook of plugin.hooks.before) {
|
// for (const hook of plugin.hooks.before) {
|
||||||
const match = hook.matcher({
|
// const match = hook.matcher({
|
||||||
...context,
|
// ...context,
|
||||||
...value,
|
// ...value,
|
||||||
});
|
// });
|
||||||
if (match) {
|
// if (match) {
|
||||||
const hookRes = await hook.handler(context);
|
// const hookRes = await hook.handler(context);
|
||||||
if (hookRes && "context" in hookRes) {
|
// if (hookRes && "context" in hookRes) {
|
||||||
context = {
|
// context = {
|
||||||
...context,
|
// ...context,
|
||||||
...hookRes.context,
|
// ...hookRes.context,
|
||||||
...value,
|
// ...value,
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
if (context.path === "/user/update") {
|
||||||
|
const res = await api[key].options.use[1](context);
|
||||||
|
console.log(res);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* TODO: move this to respond a json response
|
* TODO: move this to respond a json response
|
||||||
@@ -187,7 +191,6 @@ export const router = <C extends AuthContext, Option extends BetterAuthOptions>(
|
|||||||
},
|
},
|
||||||
...middlewares,
|
...middlewares,
|
||||||
],
|
],
|
||||||
|
|
||||||
onError(e) {
|
onError(e) {
|
||||||
if (options.disableLog !== true) {
|
if (options.disableLog !== true) {
|
||||||
if (e instanceof APIError) {
|
if (e instanceof APIError) {
|
||||||
@@ -196,7 +199,7 @@ export const router = <C extends AuthContext, Option extends BetterAuthOptions>(
|
|||||||
if (typeof e === "object" && e !== null && "message" in e) {
|
if (typeof e === "object" && e !== null && "message" in e) {
|
||||||
const errorMessage = e.message as string;
|
const errorMessage = e.message as string;
|
||||||
if (!errorMessage || typeof errorMessage !== "string") {
|
if (!errorMessage || typeof errorMessage !== "string") {
|
||||||
logger.warn(e);
|
logger.error(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (errorMessage.includes("no such table")) {
|
if (errorMessage.includes("no such table")) {
|
||||||
@@ -224,10 +227,10 @@ export const router = <C extends AuthContext, Option extends BetterAuthOptions>(
|
|||||||
)} to create the tables. There are missing tables in your MySQL database.`,
|
)} to create the tables. There are missing tables in your MySQL database.`,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
logger.warn(e);
|
logger.error(e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.warn(e);
|
logger.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
export * from "./csrf";
|
export * from "./csrf";
|
||||||
export * from "./session";
|
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
import { APIError } from "better-call";
|
|
||||||
import { createAuthMiddleware } from "../call";
|
|
||||||
import { getSessionFromCtx } from "../routes";
|
|
||||||
|
|
||||||
export const sessionMiddleware = createAuthMiddleware(async (ctx) => {
|
|
||||||
const session = await getSessionFromCtx(ctx);
|
|
||||||
if (!session?.session) {
|
|
||||||
throw new APIError("UNAUTHORIZED");
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
session,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
import type { Context, InferUse } from "better-call";
|
import { APIError, type Context, type InferUse } from "better-call";
|
||||||
import { createAuthEndpoint } from "../call";
|
import { createAuthEndpoint, createAuthMiddleware } from "../call";
|
||||||
import { getDate } from "../../utils/date";
|
import { getDate } from "../../utils/date";
|
||||||
import { deleteSessionCookie, setSessionCookie } from "../../utils/cookies";
|
import { deleteSessionCookie, setSessionCookie } from "../../utils/cookies";
|
||||||
import { sessionMiddleware } from "../middlewares/session";
|
|
||||||
import type { Session, User } from "../../adapters/schema";
|
import type { Session, User } from "../../adapters/schema";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { getIp } from "../../utils/get-request-ip";
|
import { getIp } from "../../utils/get-request-ip";
|
||||||
@@ -67,14 +66,18 @@ export const getSession = <Option extends BetterAuthOptions>() =>
|
|||||||
const cachedSession = sessionCache.get(key);
|
const cachedSession = sessionCache.get(key);
|
||||||
if (cachedSession) {
|
if (cachedSession) {
|
||||||
if (cachedSession.expiresAt > Date.now()) {
|
if (cachedSession.expiresAt > Date.now()) {
|
||||||
return ctx.json(cachedSession.data);
|
return ctx.json(
|
||||||
|
cachedSession.data as unknown as {
|
||||||
|
session: Prettify<InferSession<Option>>;
|
||||||
|
user: Prettify<InferUser<Option>>;
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
sessionCache.delete(key);
|
sessionCache.delete(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
const session =
|
const session =
|
||||||
await ctx.context.internalAdapter.findSession(sessionCookieToken);
|
await ctx.context.internalAdapter.findSession(sessionCookieToken);
|
||||||
|
|
||||||
if (!session || session.session.expiresAt < new Date()) {
|
if (!session || session.session.expiresAt < new Date()) {
|
||||||
deleteSessionCookie(ctx);
|
deleteSessionCookie(ctx);
|
||||||
if (session) {
|
if (session) {
|
||||||
@@ -95,10 +98,15 @@ export const getSession = <Option extends BetterAuthOptions>() =>
|
|||||||
* We don't need to update the session if the user doesn't want to be remembered
|
* We don't need to update the session if the user doesn't want to be remembered
|
||||||
*/
|
*/
|
||||||
if (dontRememberMe) {
|
if (dontRememberMe) {
|
||||||
return ctx.json(session);
|
return ctx.json(
|
||||||
|
session as unknown as {
|
||||||
|
session: Prettify<InferSession<Option>>;
|
||||||
|
user: Prettify<InferUser<Option>>;
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
const expiresIn = ctx.context.session.expiresIn;
|
const expiresIn = ctx.context.sessionConfig.expiresIn;
|
||||||
const updateAge = ctx.context.session.updateAge;
|
const updateAge = ctx.context.sessionConfig.updateAge;
|
||||||
/**
|
/**
|
||||||
* Calculate last updated date to throttle write updates to database
|
* Calculate last updated date to throttle write updates to database
|
||||||
* Formula: ({expiry date} - sessionMaxAge) + sessionUpdateAge
|
* Formula: ({expiry date} - sessionMaxAge) + sessionUpdateAge
|
||||||
@@ -119,7 +127,7 @@ export const getSession = <Option extends BetterAuthOptions>() =>
|
|||||||
await ctx.context.internalAdapter.updateSession(
|
await ctx.context.internalAdapter.updateSession(
|
||||||
session.session.id,
|
session.session.id,
|
||||||
{
|
{
|
||||||
expiresAt: getDate(ctx.context.session.expiresIn, true),
|
expiresAt: getDate(ctx.context.sessionConfig.expiresIn, true),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
if (!updatedSession) {
|
if (!updatedSession) {
|
||||||
@@ -167,6 +175,16 @@ export const getSessionFromCtx = async (ctx: Context<any, any>) => {
|
|||||||
return session;
|
return session;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const sessionMiddleware = createAuthMiddleware(async (ctx) => {
|
||||||
|
const session = await getSessionFromCtx(ctx);
|
||||||
|
if (!session?.session) {
|
||||||
|
throw new APIError("UNAUTHORIZED");
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
session,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* user active sessions list
|
* user active sessions list
|
||||||
*/
|
*/
|
||||||
@@ -212,6 +230,13 @@ export const revokeSession = createAuthEndpoint(
|
|||||||
},
|
},
|
||||||
async (ctx) => {
|
async (ctx) => {
|
||||||
const id = ctx.body.id;
|
const id = ctx.body.id;
|
||||||
|
const findSession = await ctx.context.internalAdapter.findSession(id);
|
||||||
|
if (!findSession) {
|
||||||
|
return ctx.json(null, { status: 400 });
|
||||||
|
}
|
||||||
|
if (findSession.session.userId !== ctx.context.session.user.id) {
|
||||||
|
return ctx.json(null, { status: 403 });
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
await ctx.context.internalAdapter.deleteSession(id);
|
await ctx.context.internalAdapter.deleteSession(id);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { createAuthEndpoint } from "../call";
|
import { createAuthEndpoint, createAuthMiddleware } from "../call";
|
||||||
import { sessionMiddleware } from "../middlewares/session";
|
|
||||||
import { alphabet, generateRandomString } from "oslo/crypto";
|
import { alphabet, generateRandomString } from "oslo/crypto";
|
||||||
import { setSessionCookie } from "../../utils/cookies";
|
import { setSessionCookie } from "../../utils/cookies";
|
||||||
|
import { getSessionFromCtx, sessionMiddleware } from "./session";
|
||||||
|
import { APIError } from "better-call";
|
||||||
|
|
||||||
export const updateUser = createAuthEndpoint(
|
export const updateUser = createAuthEndpoint(
|
||||||
"/user/update",
|
"/user/update",
|
||||||
@@ -17,6 +18,9 @@ export const updateUser = createAuthEndpoint(
|
|||||||
async (ctx) => {
|
async (ctx) => {
|
||||||
const { name, image } = ctx.body;
|
const { name, image } = ctx.body;
|
||||||
const session = ctx.context.session;
|
const session = ctx.context.session;
|
||||||
|
if (!image && !name) {
|
||||||
|
return ctx.json(session.user);
|
||||||
|
}
|
||||||
const user = await ctx.context.internalAdapter.updateUserByEmail(
|
const user = await ctx.context.internalAdapter.updateUserByEmail(
|
||||||
session.user.email,
|
session.user.email,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export const init = (options: BetterAuthOptions) => {
|
|||||||
},
|
},
|
||||||
tables,
|
tables,
|
||||||
baseURL: baseURL || "",
|
baseURL: baseURL || "",
|
||||||
session: {
|
sessionConfig: {
|
||||||
updateAge: options.session?.updateAge || 24 * 60 * 60, // 24 hours
|
updateAge: options.session?.updateAge || 24 * 60 * 60, // 24 hours
|
||||||
expiresIn: options.session?.expiresIn || 60 * 60 * 24 * 7, // 7 days
|
expiresIn: options.session?.expiresIn || 60 * 60 * 24 * 7, // 7 days
|
||||||
},
|
},
|
||||||
@@ -83,7 +83,7 @@ export type AuthContext = {
|
|||||||
internalAdapter: ReturnType<typeof createInternalAdapter>;
|
internalAdapter: ReturnType<typeof createInternalAdapter>;
|
||||||
createAuthCookie: ReturnType<typeof createCookieGetter>;
|
createAuthCookie: ReturnType<typeof createCookieGetter>;
|
||||||
secret: string;
|
secret: string;
|
||||||
session: {
|
sessionConfig: {
|
||||||
updateAge: number;
|
updateAge: number;
|
||||||
expiresIn: number;
|
expiresIn: number;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { APIError, type Context, createEndpointCreator } from "better-call";
|
import { APIError, type Context, createEndpointCreator } from "better-call";
|
||||||
import type { Session, User } from "../../adapters/schema";
|
import type { Session, User } from "../../adapters/schema";
|
||||||
import { createAuthMiddleware, optionsMiddleware } from "../../api/call";
|
import { createAuthMiddleware, optionsMiddleware } from "../../api/call";
|
||||||
import { sessionMiddleware } from "../../api/middlewares/session";
|
import { sessionMiddleware } from "../../api";
|
||||||
import type { Role, defaultRoles } from "./access";
|
import type { Role, defaultRoles } from "./access";
|
||||||
import type { OrganizationOptions } from "./organization";
|
import type { OrganizationOptions } from "./organization";
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import { APIError } from "better-call";
|
|||||||
import { alphabet, generateRandomString } from "oslo/crypto";
|
import { alphabet, generateRandomString } from "oslo/crypto";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { createAuthEndpoint } from "../../api/call";
|
import { createAuthEndpoint } from "../../api/call";
|
||||||
import { sessionMiddleware } from "../../api/middlewares/session";
|
import { sessionMiddleware } from "../../api";
|
||||||
import { getSessionFromCtx } from "../../api/routes";
|
import { getSessionFromCtx } from "../../api/routes";
|
||||||
import type { BetterAuthPlugin } from "../../types/plugins";
|
import type { BetterAuthPlugin } from "../../types/plugins";
|
||||||
import { setSessionCookie } from "../../utils/cookies";
|
import { setSessionCookie } from "../../utils/cookies";
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { alphabet, generateRandomString } from "oslo/crypto";
|
import { alphabet, generateRandomString } from "oslo/crypto";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { createAuthEndpoint } from "../../../api/call";
|
import { createAuthEndpoint } from "../../../api/call";
|
||||||
import { sessionMiddleware } from "../../../api/middlewares/session";
|
import { sessionMiddleware } from "../../../api";
|
||||||
import { symmetricDecrypt, symmetricEncrypt } from "../../../crypto";
|
import { symmetricDecrypt, symmetricEncrypt } from "../../../crypto";
|
||||||
import { verifyTwoFactorMiddleware } from "../verify-middleware";
|
import { verifyTwoFactorMiddleware } from "../verify-middleware";
|
||||||
import type { TwoFactorProvider, UserWithTwoFactor } from "../types";
|
import type { TwoFactorProvider, UserWithTwoFactor } from "../types";
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { alphabet, generateRandomString } from "oslo/crypto";
|
import { alphabet, generateRandomString } from "oslo/crypto";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { createAuthEndpoint, createAuthMiddleware } from "../../api/call";
|
import { createAuthEndpoint, createAuthMiddleware } from "../../api/call";
|
||||||
import { sessionMiddleware } from "../../api/middlewares/session";
|
import { sessionMiddleware } from "../../api";
|
||||||
import { hs256, symmetricEncrypt } from "../../crypto";
|
import { hs256, symmetricEncrypt } from "../../crypto";
|
||||||
import type { BetterAuthPlugin } from "../../types/plugins";
|
import type { BetterAuthPlugin } from "../../types/plugins";
|
||||||
import { backupCode2fa, generateBackupCodes } from "./backup-codes";
|
import { backupCode2fa, generateBackupCodes } from "./backup-codes";
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { TimeSpan } from "oslo";
|
|||||||
import { TOTPController, createTOTPKeyURI } from "oslo/otp";
|
import { TOTPController, createTOTPKeyURI } from "oslo/otp";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { createAuthEndpoint } from "../../../api/call";
|
import { createAuthEndpoint } from "../../../api/call";
|
||||||
import { sessionMiddleware } from "../../../api/middlewares/session";
|
import { sessionMiddleware } from "../../../api";
|
||||||
import { symmetricDecrypt } from "../../../crypto";
|
import { symmetricDecrypt } from "../../../crypto";
|
||||||
import type { BackupCodeOptions } from "../backup-codes";
|
import type { BackupCodeOptions } from "../backup-codes";
|
||||||
import { verifyTwoFactorMiddleware } from "../verify-middleware";
|
import { verifyTwoFactorMiddleware } from "../verify-middleware";
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export default defineConfig((env) => {
|
|||||||
sourcemap: isBuild,
|
sourcemap: isBuild,
|
||||||
format: ["esm"],
|
format: ["esm"],
|
||||||
dts: true,
|
dts: true,
|
||||||
|
splitting: false,
|
||||||
minify: isBuild,
|
minify: isBuild,
|
||||||
minifyWhitespace: isBuild,
|
minifyWhitespace: isBuild,
|
||||||
minifyIdentifiers: isBuild,
|
minifyIdentifiers: isBuild,
|
||||||
|
|||||||
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
@@ -767,8 +767,8 @@ importers:
|
|||||||
specifier: 2.0.0-next.9
|
specifier: 2.0.0-next.9
|
||||||
version: 2.0.0-next.9
|
version: 2.0.0-next.9
|
||||||
better-call:
|
better-call:
|
||||||
specifier: 0.2.3-beta.3
|
specifier: 0.2.3-beta.8
|
||||||
version: 0.2.3-beta.3
|
version: 0.2.3-beta.8
|
||||||
better-sqlite3:
|
better-sqlite3:
|
||||||
specifier: ^11.1.2
|
specifier: ^11.1.2
|
||||||
version: 11.3.0
|
version: 11.3.0
|
||||||
@@ -10102,8 +10102,8 @@ packages:
|
|||||||
typescript: 5.6.2
|
typescript: 5.6.2
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/better-call@0.2.3-beta.3:
|
/better-call@0.2.3-beta.8:
|
||||||
resolution: {integrity: sha512-1W0HB1aJ1adhbkVAi5gBQE/0uhdz+Y1Nrg3I0xZDFQx1R6vocBq7R+bVDrI5eNX+HmbzrXdY6O+Q/CfhhczJcg==}
|
resolution: {integrity: sha512-cFD9x116voPbe9LSJFPIihY+2zDdhnEiVijQb8YWmXQXdC3PEZ7+lWyptJHBdtmLbao7xPt/JesH96/tm/o3wQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@better-fetch/fetch': 1.1.8
|
'@better-fetch/fetch': 1.1.8
|
||||||
'@types/set-cookie-parser': 2.4.10
|
'@types/set-cookie-parser': 2.4.10
|
||||||
|
|||||||
Reference in New Issue
Block a user