Dyrecteddyrected
Recipes

Limit Documents to Their Owner

Enforce row-level access and assign ownership on the trusted server.

Owner scoping must protect reads, updates, and deletion, while create logic must prevent clients from choosing another owner.

Return a where constraint from access control so authenticated users only read their own records.

Use this when

  • users should only see their own records
  • add row level access
  • scope documents by owner
  • prevent users reading another user's data

Dyrected concepts

access.read, where, row-level access

Additional packages: No additional packages.

Complete recipe

This is the canonical source compiled and behavior-tested by @dyrected/knowledge.

import { defineCollection, defineRelationshipField, defineTextField } from "@dyrected/core";

export const Projects = defineCollection({
  slug: "projects",
  access: {
    read: ({ user }) => (user ? { owner: { equals: user.sub } } : false),
    create: ({ user }) => Boolean(user),
    update: ({ user }) => (user ? { owner: { equals: user.sub } } : false),
    delete: ({ user }) => (user ? { owner: { equals: user.sub } } : false),
  },
  hooks: {
    beforeChange: [
      ({ data, operation, user }) => {
        if (operation !== "create") return data;
        if (!user) throw new Error("Authentication is required to create a project.");
        return { ...data, owner: user.sub };
      },
    ],
  },
  fields: [
    defineTextField({ name: "name", label: "Project name", required: true }),
    defineRelationshipField({
      name: "owner",
      label: "Owner",
      relationTo: "users",
      required: true,
      admin: { readOnly: true },
    }),
  ],
});

Decisions and cautions

  • Add create access requiring an authenticated user.
  • Set or overwrite owner in a server beforeChange hook during creation.
  • Apply the same owner constraint to every operation that should be private.
  • Decide whether administrators need an explicit bypass; do not grant it accidentally.
  • Prefer hiding or making the owner field read-only in the Admin UI, but keep server enforcement regardless.

Test anonymous, owner, non-owner, and administrator cases for each operation.

On this page