JavascriptMick
JavascriptMick
TtRPC
Created by JavascriptMick on 6/2/2023 in #❓-help
Use onError to change an application error into a TRPCError?
I want to use the onError handler to change any instance of a custom application error into a TRPCError (I want the HTTP Status code to be a 401 rather than a 500). I tried this but it doesn't work...
onError({error}) {
if (error instanceof AccountLimitError){
error = new TRPCError({ code: 'UNAUTHORIZED', message:error.message })
}
}
onError({error}) {
if (error instanceof AccountLimitError){
error = new TRPCError({ code: 'UNAUTHORIZED', message:error.message })
}
}
nor does this
onError({error}) {
if (error instanceof AccountLimitError){
const trpcError = new TRPCError({ code: 'UNAUTHORIZED', message:error.message })
error = Object.assign(error, trpcError)
}
}
onError({error}) {
if (error instanceof AccountLimitError){
const trpcError = new TRPCError({ code: 'UNAUTHORIZED', message:error.message })
error = Object.assign(error, trpcError)
}
}
I can set individual properties on the error object like error.message but thought there might be an easier way. Has anybody got a nifty hack for this?
8 replies
TtRPC
Created by JavascriptMick on 2/25/2023 in #❓-help
is context cached?
If I put an object on the context that represents the User record from my database...
export async function createContext(event: H3Event){
if (!dbUser) {
const userService = new UserService();
dbUser = await userService.getUser(user_id);
}

return {
dbUser,
blah....
}
};
export async function createContext(event: H3Event){
if (!dbUser) {
const userService = new UserService();
dbUser = await userService.getUser(user_id);
}

return {
dbUser,
blah....
}
};
And then I have a router function which changes important details of the user....
changeAccountLevel: protectedProcedure
.input(z.object({ user_id: z.number(), level: z.number() }))
.query(async ({ ctx, input }) => {
const userService = new UserService();
const user = await userService.changeAccountLevel(input.user_id, input.level);
return {
user,
}
}),
changeAccountLevel: protectedProcedure
.input(z.object({ user_id: z.number(), level: z.number() }))
.query(async ({ ctx, input }) => {
const userService = new UserService();
const user = await userService.changeAccountLevel(input.user_id, input.level);
return {
user,
}
}),
Do I need to 'mutate' the dbUser on the context....
ctx.dbUser = user
ctx.dbUser = user
or will subsequent calls to routes, re-invoke createContext and re-load the user from the database?
7 replies
TtRPC
Created by JavascriptMick on 2/23/2023 in #❓-help
Best way to implement input based validation on a router procedure
Hi guys, bit of a noob. I have already created a 'protectedProcedure', ensuring the user is logged in, but for some of my procedures, I also want to ensure the user is an ADMIN for the account specified on the input. This is my first try with validation just added at the top of the procedure implementation...
changeUserAccessWithinAccount: protectedProcedure
.input(z.object({ user_id: z.number(), account_id: z.number(), access: z.enum([ACCOUNT_ACCESS.ADMIN, ACCOUNT_ACCESS.OWNER, ACCOUNT_ACCESS.READ_ONLY, ACCOUNT_ACCESS.READ_WRITE]) }))
.query(async ({ ctx, input }) => {
// validate that the context user is an admin within the account specified as an input param.... where should this go.. an additional input parser?
const test_membership = ctx.dbUser.memberships.find(membership => membership.account_id == input.account_id);
if(!test_membership || (test_membership?.access !== ACCOUNT_ACCESS.ADMIN && test_membership?.access !== ACCOUNT_ACCESS.OWNER)) {
throw new TRPCError({ code: 'UNAUTHORIZED' });
}
//....do the thing...
changeUserAccessWithinAccount: protectedProcedure
.input(z.object({ user_id: z.number(), account_id: z.number(), access: z.enum([ACCOUNT_ACCESS.ADMIN, ACCOUNT_ACCESS.OWNER, ACCOUNT_ACCESS.READ_ONLY, ACCOUNT_ACCESS.READ_WRITE]) }))
.query(async ({ ctx, input }) => {
// validate that the context user is an admin within the account specified as an input param.... where should this go.. an additional input parser?
const test_membership = ctx.dbUser.memberships.find(membership => membership.account_id == input.account_id);
if(!test_membership || (test_membership?.access !== ACCOUNT_ACCESS.ADMIN && test_membership?.access !== ACCOUNT_ACCESS.OWNER)) {
throw new TRPCError({ code: 'UNAUTHORIZED' });
}
//....do the thing...
Is there a way to implement this with multiple input parsers (https://trpc.io/docs/procedures#multiple-input-parsers) ?? what would that look like?
15 replies