Skip to content

fix(workout-session): require auth + ownership to delete a workout session#239

Open
evan188199-tech wants to merge 1 commit into
Snouzy:mainfrom
evan188199-tech:fix/delete-workout-session-auth-ownership-check
Open

fix(workout-session): require auth + ownership to delete a workout session#239
evan188199-tech wants to merge 1 commit into
Snouzy:mainfrom
evan188199-tech:fix/delete-workout-session-auth-ownership-check

Conversation

@evan188199-tech

Copy link
Copy Markdown

What

deleteWorkoutSessionAction let any logged-in user delete any other user's workout session. It was built on the unauthenticated actionClient, fetched the session's userId but never compared it to the caller, and deleted by id alone.

Root cause

export const deleteWorkoutSessionAction = actionClient.schema(...).action(async ({ parsedInput }) => {
  const { id } = parsedInput;
  const session = await prisma.workoutSession.findUnique({
    where: { id },
    select: { userId: true },     // fetched, then discarded
  });
  if (!session) { ... }
  await prisma.workoutSession.delete({ where: { id } });  // deletes unconditionally
});

actionClient performs no auth (vs authenticatedActionClient, which injects ctx.user via serverAuth()). The action had no idea who the caller was, so the selected userId could never be checked.

Fix

Switch to authenticatedActionClient and require ownership:

export const deleteWorkoutSessionAction = authenticatedActionClient
  .schema(deleteWorkoutSessionSchema)
  .action(async ({ parsedInput, ctx }) => {
    const { id } = parsedInput;
    const session = await prisma.workoutSession.findUnique({ where: { id }, select: { userId: true } });
    if (!session || session.userId !== ctx.user.id) {
      return { serverError: "Session not found" };
    }
    await prisma.workoutSession.delete({ where: { id } });
    return { success: true };
  });

The same "not found" is returned for missing and non-owned rows to avoid disclosing which session ids exist.

Fixes #238.

…ssion

deleteWorkoutSessionAction used the unauthenticated actionClient and
fetched the session's userId only to discard it, deleting by id alone —
so any logged-in user could delete any other user's session. Switch to
authenticatedActionClient (which injects ctx.user via serverAuth) and
reject when session.userId !== ctx.user.id, returning the same 'not
found' for missing and non-owned rows to avoid existence disclosure.

Fixes Snouzy#238
@vercel

vercel Bot commented Jul 7, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the Workoutcool Team Team on Vercel.

A member of the Team first needs to authorize it.

@evan188199-tech

Copy link
Copy Markdown
Author

此 PR 由 GLM-5.2 修复。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: deleteWorkoutSessionAction has no auth/ownership check — any user can delete others sessions

1 participant