Member Management

Learn about managing workspace members, roles, and access control.

Member Schema

Database

The member management system uses a PostgreSQL table with the following structure:

Schema Definition

Database schema for workspace members:

export const workspaceMembers = pgTable(
  "workspaceMembers",
  {
    // User reference
    userId: text("user_id")
      .notNull()
      .references(() => users.id, { onDelete: "cascade" }),
    
    // Workspace reference
    workspaceId: text("workspace_id")
      .notNull()
      .references(() => workspaces.id, { onDelete: "cascade" }),
    
    // Role assignment
    roleId: text("role_id")
      .notNull()
      .references(() => roles.id),
    
    // Timestamps
    createdAt: timestamp("created_at").notNull().defaultNow(),
    updatedAt: timestamp("updated_at"),
  },
  (t) => ({
    pk: primaryKey({ columns: [t.userId, t.workspaceId] }),
  })
)

Access Control

Authorization

The MemberProvider component handles workspace access control:

Member Provider

Authorization wrapper for workspace routes:

export async function MemberProvider({ children, slug }: MemberProviderProps) {
  // 1. Check authentication
  const { user } = await getCurrentUser()
  if (!user) {
    return redirect(createRoute("sign-in").href)
  }

  // 2. Verify workspace exists
  const workspace = await db.query.workspaces.findFirst({
    where: eq(workspaces.slug, slug),
    with: {
      members: {
        columns: {
          userId: true,
        },
      },
    },
  })

  if (!workspace) {
    return notFound()
  }

  // 3. Check membership
  if (!workspace.members.some((member) => member.userId === user.id)) {
    return (
      <RestrictedContent
        title="Unauthorized"
        description="You are not authorized to access this workspace."
      />
    )
  }

  return <>{children}</>
}

Member Operations

Update Member

Update member roles and permissions

const { server_updateMember } = useUpdateMember()

// Update member role
await server_updateMember({
  role: "admin",
  userId: member.id,
  slug: workspace.slug,
})

Delete Member

Remove member from workspace

const { server_deleteMember } = useDeleteMember()

// Remove member
await server_deleteMember({
  userId: member.id,
  slug: workspace.slug,
})

Leave Workspace

Member leaves workspace voluntarily

const { server_leaveWorkspace } = useLeaveWorkspace()

// Leave workspace
await server_leaveWorkspace({
  slug: workspace.slug,
})

Security Features

Access Control

  • Role-based permissions
  • Workspace membership verification
  • Automatic cleanup on deletion
  • Secure role updates

Protection

  • Rate limiting on actions
  • Input validation
  • Permission checks
  • Audit logging