andersgee
andersgee
Explore posts from servers
TTCTheo's Typesafe Cult
Created by chillihero on 3/8/2024 in #questions
Good (cheap) alternatives to Planescale
Is it not free anyway for "hobby level usage" (just requires adding payment info) edit: oh, starting April 8, 2024 thats no longer the case...
9 replies
TTCTheo's Typesafe Cult
Created by migs on 1/31/2024 in #questions
TRPC Security/ Authorization Concerns
youre welcome 🙂 btw about "careful with input", the typesafe way is also a 1 liner so might aswell use that
const { classroomId } = z.object({ classroomId: z.number() }).parse(input);
const { classroomId } = z.object({ classroomId: z.number() }).parse(input);
13 replies
TTCTheo's Typesafe Cult
Created by migs on 1/31/2024 in #questions
TRPC Security/ Authorization Concerns
I mean in programming there are always many way to do things, I feel like you are asking for "best practise" or something but as I said before, you just have to pick a way to do it that fits your use case. That being said, no I personally would not put classroomId in session. If your regular protectedProcedure looks like this
export const protectedProcedure = t.procedure.use(middleware(({ ctx, next }) => {
if (!ctx.user) throw new TRPCError({ code: "UNAUTHORIZED" });

return next({ ctx: { ...ctx, user: ctx.user } });
}));
export const protectedProcedure = t.procedure.use(middleware(({ ctx, next }) => {
if (!ctx.user) throw new TRPCError({ code: "UNAUTHORIZED" });

return next({ ctx: { ...ctx, user: ctx.user } });
}));
you could add another
export const teacherProcedure = t.procedure.use(middleware(async ({ ctx, next }) => {
if (!ctx.user) throw new TRPCError({ code: "UNAUTHORIZED" });

const role = await getUserRole(ctx.user) // fetch this from db or perhaps you already have this on "ctx.user"?
if (role !== "TEACHER") throw new TRPCError({ code: "UNAUTHORIZED" });

return next({ ctx: { ...ctx, user: ctx.user } });
}));
export const teacherProcedure = t.procedure.use(middleware(async ({ ctx, next }) => {
if (!ctx.user) throw new TRPCError({ code: "UNAUTHORIZED" });

const role = await getUserRole(ctx.user) // fetch this from db or perhaps you already have this on "ctx.user"?
if (role !== "TEACHER") throw new TRPCError({ code: "UNAUTHORIZED" });

return next({ ctx: { ...ctx, user: ctx.user } });
}));
now we can use teacherProcedure instead and again we are back to the situation where you do something like deleteClassroom({id:input.id, teacherId: session.userId})
13 replies
TTCTheo's Typesafe Cult
Created by migs on 1/31/2024 in #questions
TRPC Security/ Authorization Concerns
If someone has a session yes they will have access to protected procedures, but if the procedure does something like getUserById({userId: session.userId}) then they will only get their own info back. Another example is something like deletePostById, you dont just do deletePostById({id: input.id}) you do deletePostById({id:input.id, creatorId: session.userId}) and hence they will only be able to delete their own posts These are just examples, but you are correct, protectedProcedure is just "Authentication". you still have to think about who has access to what aka "Authorization" yourself A common thing is managing authorization with user roles but you could choose to make it as specific as your usecase needs to be
13 replies
TTCTheo's Typesafe Cult
Created by james162861 on 1/31/2024 in #questions
Call post.hello on button click
The output will be in useMutation({onSuccess: (x)=>
7 replies
TTCTheo's Typesafe Cult
Created by james162861 on 1/31/2024 in #questions
Call post.hello on button click
your trpc router should look something like hello: publicProcedure.input(...).mutation(()=>{...}) and the usage in your component looks something like
const postHello = api.post.hello.useMutation()
...
<button onClick={()=>postHello.mutate(...)}>
const postHello = api.post.hello.useMutation()
...
<button onClick={()=>postHello.mutate(...)}>
7 replies