feat: shared workspace - remove user scoping from tasks, projects, and labels

This commit is contained in:
2026-01-28 19:38:53 +00:00
parent 1bc0ab091b
commit 617eaacc5f
3 changed files with 18 additions and 58 deletions

View File

@@ -1,14 +1,13 @@
import { Elysia, t } from 'elysia'; import { Elysia, t } from 'elysia';
import { db } from '../db'; import { db } from '../db';
import { labels, taskLabels } from '../db/schema'; import { labels, taskLabels } from '../db/schema';
import { eq, and, asc, sql } from 'drizzle-orm'; import { eq, asc, sql } from 'drizzle-orm';
import type { User } from '../lib/auth'; import type { User } from '../lib/auth';
export const labelRoutes = new Elysia({ prefix: '/labels' }) export const labelRoutes = new Elysia({ prefix: '/labels' })
// List all labels for user // List all labels for user
.get('/', async ({ user }) => { .get('/', async ({ user }) => {
const userLabels = await db.query.labels.findMany({ const userLabels = await db.query.labels.findMany({
where: eq(labels.userId, (user as User).id),
orderBy: [asc(labels.sortOrder), asc(labels.name)], orderBy: [asc(labels.sortOrder), asc(labels.name)],
}); });
@@ -33,10 +32,7 @@ export const labelRoutes = new Elysia({ prefix: '/labels' })
// Get single label with tasks // Get single label with tasks
.get('/:id', async ({ params, user, set }) => { .get('/:id', async ({ params, user, set }) => {
const label = await db.query.labels.findFirst({ const label = await db.query.labels.findFirst({
where: and( where: eq(labels.id, params.id),
eq(labels.id, params.id),
eq(labels.userId, (user as User).id)
),
}); });
if (!label) { if (!label) {
@@ -70,10 +66,7 @@ export const labelRoutes = new Elysia({ prefix: '/labels' })
// Update label // Update label
.patch('/:id', async ({ params, body, user, set }) => { .patch('/:id', async ({ params, body, user, set }) => {
const existing = await db.query.labels.findFirst({ const existing = await db.query.labels.findFirst({
where: and( where: eq(labels.id, params.id),
eq(labels.id, params.id),
eq(labels.userId, (user as User).id)
),
}); });
if (!existing) { if (!existing) {
@@ -106,10 +99,7 @@ export const labelRoutes = new Elysia({ prefix: '/labels' })
// Delete label // Delete label
.delete('/:id', async ({ params, user, set }) => { .delete('/:id', async ({ params, user, set }) => {
const existing = await db.query.labels.findFirst({ const existing = await db.query.labels.findFirst({
where: and( where: eq(labels.id, params.id),
eq(labels.id, params.id),
eq(labels.userId, (user as User).id)
),
}); });
if (!existing) { if (!existing) {

View File

@@ -8,10 +8,7 @@ export const projectRoutes = new Elysia({ prefix: '/projects' })
// List all projects for user // List all projects for user
.get('/', async ({ user }) => { .get('/', async ({ user }) => {
const userProjects = await db.query.projects.findMany({ const userProjects = await db.query.projects.findMany({
where: and( where: eq(projects.isArchived, false),
eq(projects.userId, (user as User).id),
eq(projects.isArchived, false)
),
orderBy: [desc(projects.isInbox), asc(projects.sortOrder), asc(projects.createdAt)], orderBy: [desc(projects.isInbox), asc(projects.sortOrder), asc(projects.createdAt)],
with: { with: {
sections: { sections: {
@@ -25,10 +22,7 @@ export const projectRoutes = new Elysia({ prefix: '/projects' })
// Get single project with sections and task counts // Get single project with sections and task counts
.get('/:projectId', async ({ params, user, set }) => { .get('/:projectId', async ({ params, user, set }) => {
const project = await db.query.projects.findFirst({ const project = await db.query.projects.findFirst({
where: and( where: eq(projects.id, params.projectId),
eq(projects.id, params.projectId),
eq(projects.userId, (user as User).id)
),
with: { with: {
sections: { sections: {
orderBy: [asc(sections.sortOrder)], orderBy: [asc(sections.sortOrder)],
@@ -69,10 +63,7 @@ export const projectRoutes = new Elysia({ prefix: '/projects' })
// Update project // Update project
.patch('/:projectId', async ({ params, body, user, set }) => { .patch('/:projectId', async ({ params, body, user, set }) => {
const existing = await db.query.projects.findFirst({ const existing = await db.query.projects.findFirst({
where: and( where: eq(projects.id, params.projectId),
eq(projects.id, params.projectId),
eq(projects.userId, (user as User).id)
),
}); });
if (!existing) { if (!existing) {
@@ -113,10 +104,7 @@ export const projectRoutes = new Elysia({ prefix: '/projects' })
// Delete project // Delete project
.delete('/:projectId', async ({ params, user, set }) => { .delete('/:projectId', async ({ params, user, set }) => {
const existing = await db.query.projects.findFirst({ const existing = await db.query.projects.findFirst({
where: and( where: eq(projects.id, params.projectId),
eq(projects.id, params.projectId),
eq(projects.userId, (user as User).id)
),
}); });
if (!existing) { if (!existing) {
@@ -142,12 +130,9 @@ export const projectRoutes = new Elysia({ prefix: '/projects' })
// Create section in project // Create section in project
.post('/:projectId/sections', async ({ params, body, user, set }) => { .post('/:projectId/sections', async ({ params, body, user, set }) => {
// Verify project ownership // Verify project exists
const project = await db.query.projects.findFirst({ const project = await db.query.projects.findFirst({
where: and( where: eq(projects.id, params.projectId),
eq(projects.id, params.projectId),
eq(projects.userId, (user as User).id)
),
}); });
if (!project) { if (!project) {
@@ -174,12 +159,9 @@ export const projectRoutes = new Elysia({ prefix: '/projects' })
// Update section // Update section
.patch('/:projectId/sections/:sectionId', async ({ params, body, user, set }) => { .patch('/:projectId/sections/:sectionId', async ({ params, body, user, set }) => {
// Verify project ownership // Verify project exists
const project = await db.query.projects.findFirst({ const project = await db.query.projects.findFirst({
where: and( where: eq(projects.id, params.projectId),
eq(projects.id, params.projectId),
eq(projects.userId, (user as User).id)
),
}); });
if (!project) { if (!project) {
@@ -219,12 +201,9 @@ export const projectRoutes = new Elysia({ prefix: '/projects' })
// Delete section // Delete section
.delete('/:projectId/sections/:sectionId', async ({ params, user, set }) => { .delete('/:projectId/sections/:sectionId', async ({ params, user, set }) => {
// Verify project ownership // Verify project exists
const project = await db.query.projects.findFirst({ const project = await db.query.projects.findFirst({
where: and( where: eq(projects.id, params.projectId),
eq(projects.id, params.projectId),
eq(projects.userId, (user as User).id)
),
}); });
if (!project) { if (!project) {

View File

@@ -49,7 +49,7 @@ export const taskRoutes = new Elysia({ prefix: '/tasks' })
// List tasks with filters // List tasks with filters
.get('/', async ({ user, query }) => { .get('/', async ({ user, query }) => {
const userId = (user as User).id; const userId = (user as User).id;
const conditions = [eq(tasks.userId, userId)]; const conditions: ReturnType<typeof eq>[] = [];
// Filter by project // Filter by project
if (query.projectId) { if (query.projectId) {
@@ -169,10 +169,7 @@ export const taskRoutes = new Elysia({ prefix: '/tasks' })
// Get single task with full details // Get single task with full details
.get('/:id', async ({ params, user, set }) => { .get('/:id', async ({ params, user, set }) => {
const task = await db.query.tasks.findFirst({ const task = await db.query.tasks.findFirst({
where: and( where: eq(tasks.id, params.id),
eq(tasks.id, params.id),
eq(tasks.userId, (user as User).id)
),
with: { with: {
project: true, project: true,
section: true, section: true,
@@ -326,10 +323,7 @@ export const taskRoutes = new Elysia({ prefix: '/tasks' })
const userId = (user as User).id; const userId = (user as User).id;
const existing = await db.query.tasks.findFirst({ const existing = await db.query.tasks.findFirst({
where: and( where: eq(tasks.id, params.id),
eq(tasks.id, params.id),
eq(tasks.userId, userId)
),
}); });
if (!existing) { if (!existing) {
@@ -461,10 +455,7 @@ export const taskRoutes = new Elysia({ prefix: '/tasks' })
// Delete task // Delete task
.delete('/:id', async ({ params, user, set }) => { .delete('/:id', async ({ params, user, set }) => {
const existing = await db.query.tasks.findFirst({ const existing = await db.query.tasks.findFirst({
where: and( where: eq(tasks.id, params.id),
eq(tasks.id, params.id),
eq(tasks.userId, (user as User).id)
),
}); });
if (!existing) { if (!existing) {