Files
docs-app/pages/api/tina/[...routes].ts
2026-04-01 19:15:22 +02:00

125 lines
3.5 KiB
TypeScript

import {
TinaNodeBackend,
LocalBackendAuthProvider,
} from "@tinacms/datalayer";
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { getServerSession } from "next-auth/next";
import databaseClient from "../../../tina/__generated__/databaseClient";
const isLocal = process.env.TINA_PUBLIC_IS_LOCAL === "true";
const TINA_CREDENTIALS_PROVIDER_NAME = "TinaCredentials";
const authenticate = async (
dbClient: typeof databaseClient,
username: string,
password: string
) => {
try {
const result = await dbClient.authenticate({ username, password });
return result.data?.authenticate || null;
} catch (e) {
return null;
}
};
const authOptions = {
callbacks: {
jwt: async ({ token: jwt, account }: any) => {
if (account) {
try {
if (jwt?.sub) {
const result = await databaseClient.authorize({ sub: jwt.sub });
jwt.role = result.data?.authorize ? "user" : "guest";
jwt.passwordChangeRequired =
result.data?.authorize?._password?.passwordChangeRequired ||
false;
}
} catch {
// ignore auth errors
}
if (jwt.role === undefined) {
jwt.role = "guest";
}
}
return jwt;
},
session: async ({ session, token: jwt }: any) => {
session.user.role = jwt.role;
session.user.passwordChangeRequired = jwt.passwordChangeRequired;
session.user.sub = jwt.sub;
return session;
},
},
session: { strategy: "jwt" as const },
secret: process.env.NEXTAUTH_SECRET as string,
providers: [
CredentialsProvider({
name: TINA_CREDENTIALS_PROVIDER_NAME,
credentials: {
username: { label: "Username", type: "text" },
password: { label: "Password", type: "password" },
},
authorize: async (credentials: any) =>
authenticate(databaseClient, credentials.username, credentials.password),
}),
],
};
const handler = TinaNodeBackend({
authProvider: isLocal
? LocalBackendAuthProvider()
: {
initialize: async () => {},
isAuthorized: async (req: any, res: any) => {
const session = await getServerSession(req, res, authOptions);
if (!req.session) {
Object.defineProperty(req, "session", {
value: session,
writable: false,
});
}
if (!(session as any)?.user) {
return {
errorCode: 401,
errorMessage: "Unauthorized",
isAuthorized: false,
};
}
if ((session as any)?.user?.role !== "user") {
return {
errorCode: 403,
errorMessage: "Forbidden",
isAuthorized: false,
};
}
return { isAuthorized: true };
},
extraRoutes: {
auth: {
secure: false,
handler: async (req: any, res: any, opts: any) => {
const url = new URL(
req.url,
`http://${req.headers?.host || "localhost"}`
);
const authSubRoutes = url.pathname
?.replace(`${opts.basePath}auth/`, "")
?.split("/");
req.query.nextauth = authSubRoutes;
await NextAuth(authOptions)(req, res);
},
},
},
},
databaseClient,
});
export default (req: any, res: any) => {
return handler(req, res);
};
export { authOptions };