feat: add sync router for handling user data synchronization

This commit is contained in:
Marco Pedone 2025-09-04 12:41:07 +02:00
parent 917d6e2a84
commit 710ed8a97b
3 changed files with 105 additions and 8 deletions

View file

@ -19,6 +19,7 @@ import { stripeRouter } from "~/server/api/routers/stripe";
import { testRouter } from "~/server/api/routers/test";
import { usersRouter } from "~/server/api/routers/users";
import { createTRPCRouter } from "~/server/api/trpc";
import { syncRouter } from "./routers/sync";
export const appRouter = createTRPCRouter({
annunci: annunciRouter,
@ -41,5 +42,6 @@ export const appRouter = createTRPCRouter({
stripe: stripeRouter,
test: testRouter,
users: usersRouter,
sync: syncRouter,
});
export type AppRouter = typeof appRouter;

View file

@ -0,0 +1,96 @@
import z from "zod";
import { createTRPCRouter, protectedApiProcedure } from "~/server/api/trpc";
import { db } from "~/server/db";
type ClienteData = {
cognome?: string | undefined;
nome?: string | undefined;
cf?: string | undefined;
telefono?: string | undefined;
email?: string | undefined;
data_nascita?: string | undefined;
luogo_nascita?: string | undefined;
naz_residenza?: string | undefined;
provincia_residenza?: string | undefined;
cap_residenza?: string | undefined;
comune_residenza?: string | undefined;
indirizzo_residenza?: string | undefined;
civico_residenza?: string | undefined;
};
const clienteDataSchema = z.object({
cap_residenza: z.string().optional(),
cf: z.string().optional(),
civico_residenza: z.string().optional(),
cognome: z.string().optional(),
comune_residenza: z.string().optional(),
data_nascita: z.string().optional(),
email: z.string().optional(),
indirizzo_residenza: z.string().optional(),
luogo_nascita: z.string().optional(),
naz_residenza: z.string().optional(),
nome: z.string().optional(),
provincia_residenza: z.string().optional(),
telefono: z.string().optional(),
});
export const syncRouter = createTRPCRouter({
syncGet: protectedApiProcedure
.input(z.object({ cf: z.string() }))
.query(async ({ input }) => {
const user = await db
.selectFrom("users_anagrafica")
.select([
"users_anagrafica.codice_fiscale",
"users_anagrafica.userid",
"users_anagrafica.data_nascita",
"users_anagrafica.luogo_nascita",
"users_anagrafica.nazione_residenza",
"users_anagrafica.provincia_residenza",
"users_anagrafica.cap_residenza",
"users_anagrafica.comune_residenza",
"users_anagrafica.via_residenza",
"users_anagrafica.civico_residenza",
])
.innerJoin("users", "users.id", "users_anagrafica.userid")
.select([
"users.nome",
"users.cognome",
"users.email",
"users.telefono",
])
.where("users_anagrafica.codice_fiscale", "=", input.cf)
.executeTakeFirst();
const result: ClienteData = {
cognome: user?.cognome,
nome: user?.nome,
cf: user?.codice_fiscale || undefined,
telefono: user?.telefono,
email: user?.email,
data_nascita: user?.data_nascita?.toLocaleDateString("it-IT", {
year: "numeric",
month: "2-digit",
day: "2-digit",
}),
luogo_nascita: user?.luogo_nascita || undefined,
naz_residenza: user?.nazione_residenza || undefined,
provincia_residenza: user?.provincia_residenza || undefined,
cap_residenza: user?.cap_residenza || undefined,
comune_residenza: user?.comune_residenza || undefined,
indirizzo_residenza: user?.via_residenza || undefined,
civico_residenza: user?.civico_residenza || undefined,
};
return result;
}),
syncPost: protectedApiProcedure
.input(z.object({ data: clienteDataSchema }))
.mutation(async ({ input }) => {
console.log("input", input);
// const parsed = clienteDataSchema.safeParse(JSON.parse(input.data));
// console.log("parsed", parsed);
return { message: "Data received" };
}),
});

View file

@ -13,8 +13,9 @@ import type { NextApiRequest, NextApiResponse } from "next";
import superjson from "superjson";
import z, { ZodError } from "zod/v4";
import { env } from "~/env.mjs";
import { ACCESS_TOKEN_COOKIE_NAME, verifyToken } from "~/server/auth/jwt";
import { verifyToken } from "~/server/auth/jwt";
import { zUserId } from "~/server/utils/zod_types";
import { TOKEN_CONFIG } from "../auth/configs";
/**
* 1. CONTEXT
@ -62,7 +63,7 @@ export const createTRPCContext = async ({
);
}
const accessToken = req.cookies[ACCESS_TOKEN_COOKIE_NAME];
const accessToken = req.cookies[TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_NAME];
// Get the session from the server using the getServerSession wrapper function
const session = accessToken ? await verifyToken(accessToken) : null;
@ -200,15 +201,14 @@ const enforceProtectedApi = t.middleware(async ({ ctx, next, path }) => {
if (!ctx.req || !ctx.res) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: `User is not Admin, error in path: ${path}`,
message: `No request or response object, error in path: ${path}`,
});
}
const basicAuth = ctx.req.headers.authorization;
if (!basicAuth) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: `User is not Admin, error in path: ${path}`,
message: `No Auth header found: ${path}`,
});
}
@ -217,7 +217,7 @@ const enforceProtectedApi = t.middleware(async ({ ctx, next, path }) => {
if (!authValue) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: `User is not Admin, error in path: ${path}`,
message: `Auth value invalid: ${path}`,
});
}
@ -226,10 +226,9 @@ const enforceProtectedApi = t.middleware(async ({ ctx, next, path }) => {
if (user !== env.EXP_API_USER || pwd !== env.EXP_API_PASS) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: `User is not Admin, error in path: ${path}`,
message: `User or Secret not valid: ${path}`,
});
}
return next({
ctx: {
// infers the `session` as non-nullable