I am using typegraphql-prisma and all the resolver are autogenerated. I need to
automatically set the createdBy and updatedBy fields in Prisma models based on the authenticated user’s ID, which retrieve from a Firebase token in Express middleware.
//auth.middleware.ts
import { Response, NextFunction } from "express";
import * as admin from "firebase-admin";
import { AuthRequest, FirebaseAuthError } from "./../interfaces";
export default async (req: AuthRequest, res: Response, next: NextFunction) => {
const token = req.headers.authorization?.split(" ")[1];
try {
if (token) {
const decodedToken = await admin.auth().verifyIdToken(token);
req["user"] = decodedToken;
} else {
req["authError"] = "No token provided";
}
} catch (error) {
const firebaseError = error as FirebaseAuthError;
console.error("Error verifying token:", firebaseError.message);
if (firebaseError.code && firebaseError.code === "auth/id-token-expired") {
req["authError"] = "TokenExpired";
} else {
req["authError"] = "Unauthorized";
}
}
next();
};
//schema.prisma
model User {
id String @id @default(cuid())
displayName String @db.VarChar(256)
email String @unique // The user's email address for login
passwordHash String? // Hashed password
salt String? // Salt for hashing
user_type UserType @default(INSURER_EMPLOYEE)
metadata String? @db.VarChar(2048)
insurer_employee InsurerEmployee?
regulatory Regulatory?
photoURL String? @db.Text
phoneNumber String? // The user's primary phone number, if set
disabled Boolean @default(false) // Whether or not the user is disabled
createdBy String? @db.VarChar(256)
updatedBy String? @db.VarChar(256)
created_at DateTime @default(now())
updated_at DateTime? @updatedAt
@@map("users")
}
I have created prisma middleware but I can’t get the user in prisma middlw.
// prismaClient.ts
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
prisma.$use(async (params, next) => {
if (params.action === "create" && params.args.data) {
console.log("Prisma Data", params.args.data);
params.args.data.createdBy =
params.args.data.createdBy || params.args.context.userId;
params.args.data.updatedBy =
params.args.data.updatedBy || params.args.context.userId;
} else if (params.action === "update" && params.args.data) {
console.log("Prisma Data", params.args.data);
params.args.data.updatedBy =
params.args.data.updatedBy || params.args.context.userId;
}
return next(params);
});
export default prisma;
//server.ts
async function main() {
const app = express();
const allowedOrigins = [
"https://agentdb-staging.web.app",
"https://localhost:3000",
"https://localhost:4000",
// ... other domains
];
app.use(
cors({
origin: function (origin, callback) {
// Allow requests with no origin (like mobile apps or curl requests)
if (!origin) return callback(null, true);
if (allowedOrigins.indexOf(origin) === -1) {
const errMsg = "The CORS policy for this site does not allow access from the specified origin.";
return callback(new Error(errMsg), false);
}
return callback(null, true);
},
})
);
app.use(json());
app.use(cookieParser());
app.use(authenticate); // Apply the authentication middleware to all routes
const httpServer = http.createServer(app);
const schema = await buildSchema({
resolvers: [...resolvers, ...customResolvers],
validate: false,
authChecker: customAuthChecker, // register the auth checking function
});
//const prisma = new PrismaClient();
const server = new ApolloServer<Context>({
schema,
plugins: [ApolloServerPluginDrainHttpServer({ httpServer })],
introspection: true,
});
await server.start();
app.use(
"/api",
expressMiddleware(server, {
context: async ({ req, res }) => ({
req,
res,
prisma,
user: (req as any).user, // Include user in the context
authError: (req as any).authError, // Include authError in the context
}),
})
);
await new Promise<void>((resolve) => httpServer.listen({ port: server_port }, resolve));
console.log(`🚀 Server ready at https://localhost:${server_port}/api`);
}