118 lines
4.6 KiB
SQL
118 lines
4.6 KiB
SQL
-- Create task_status enum type
|
|
CREATE TYPE task_status AS ENUM ('todo', 'in_progress', 'in_review', 'done');
|
|
|
|
-- Create tasks table
|
|
CREATE TABLE IF NOT EXISTS "public"."tasks" (
|
|
"id" "text" DEFAULT "public"."generate_random_string"(24) NOT NULL,
|
|
"tablo_id" "text" NOT NULL,
|
|
"title" character varying(500) NOT NULL,
|
|
"description" "text",
|
|
"status" task_status DEFAULT 'todo' NOT NULL,
|
|
"assignee_id" "uuid",
|
|
"position" integer DEFAULT 0 NOT NULL,
|
|
"created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
"updated_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
CONSTRAINT "tasks_pkey" PRIMARY KEY ("id"),
|
|
CONSTRAINT "tasks_tablo_id_fkey" FOREIGN KEY ("tablo_id") REFERENCES "public"."tablos"("id") ON DELETE CASCADE,
|
|
CONSTRAINT "tasks_assignee_id_fkey" FOREIGN KEY ("assignee_id") REFERENCES "auth"."users"("id") ON DELETE SET NULL
|
|
);
|
|
|
|
ALTER TABLE "public"."tasks" OWNER TO "postgres";
|
|
|
|
-- Add comments
|
|
COMMENT ON TABLE "public"."tasks" IS 'Kanban tasks for tablos';
|
|
COMMENT ON COLUMN "public"."tasks"."id" IS 'Primary key: random 24-character alphanumeric string';
|
|
COMMENT ON COLUMN "public"."tasks"."tablo_id" IS 'Foreign key to tablos table';
|
|
COMMENT ON COLUMN "public"."tasks"."title" IS 'Task title';
|
|
COMMENT ON COLUMN "public"."tasks"."description" IS 'Optional task description';
|
|
COMMENT ON COLUMN "public"."tasks"."status" IS 'Task status: todo, in_progress, in_review, or done';
|
|
COMMENT ON COLUMN "public"."tasks"."assignee_id" IS 'Optional user ID of task assignee';
|
|
COMMENT ON COLUMN "public"."tasks"."position" IS 'Position within the column for ordering';
|
|
COMMENT ON COLUMN "public"."tasks"."created_at" IS 'Timestamp when the task was created';
|
|
COMMENT ON COLUMN "public"."tasks"."updated_at" IS 'Timestamp when the task was last updated (auto-updated by trigger)';
|
|
|
|
-- Create indexes for better query performance
|
|
CREATE INDEX "tasks_tablo_id_idx" ON "public"."tasks" USING btree ("tablo_id");
|
|
CREATE INDEX "tasks_status_idx" ON "public"."tasks" USING btree ("status");
|
|
CREATE INDEX "tasks_assignee_id_idx" ON "public"."tasks" USING btree ("assignee_id");
|
|
CREATE INDEX "tasks_position_idx" ON "public"."tasks" USING btree ("tablo_id", "status", "position");
|
|
|
|
-- Create trigger to auto-update updated_at timestamp
|
|
CREATE TRIGGER "update_tasks_updated_at"
|
|
BEFORE UPDATE ON "public"."tasks"
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION "public"."update_updated_at_column"();
|
|
|
|
-- Enable Row Level Security
|
|
ALTER TABLE "public"."tasks" ENABLE ROW LEVEL SECURITY;
|
|
|
|
-- RLS Policies: Users can only access tasks from tablos they have access to
|
|
CREATE POLICY "Users can view tasks from their tablos"
|
|
ON "public"."tasks"
|
|
FOR SELECT
|
|
USING (
|
|
EXISTS (
|
|
SELECT 1 FROM "public"."tablo_access"
|
|
WHERE "tablo_access"."tablo_id" = "tasks"."tablo_id"
|
|
AND "tablo_access"."user_id" = auth.uid()
|
|
AND "tablo_access"."is_active" = true
|
|
)
|
|
);
|
|
|
|
CREATE POLICY "Users can create tasks in their tablos"
|
|
ON "public"."tasks"
|
|
FOR INSERT
|
|
WITH CHECK (
|
|
EXISTS (
|
|
SELECT 1 FROM "public"."tablo_access"
|
|
WHERE "tablo_access"."tablo_id" = "tasks"."tablo_id"
|
|
AND "tablo_access"."user_id" = auth.uid()
|
|
AND "tablo_access"."is_active" = true
|
|
)
|
|
);
|
|
|
|
CREATE POLICY "Users can update tasks in their tablos"
|
|
ON "public"."tasks"
|
|
FOR UPDATE
|
|
USING (
|
|
EXISTS (
|
|
SELECT 1 FROM "public"."tablo_access"
|
|
WHERE "tablo_access"."tablo_id" = "tasks"."tablo_id"
|
|
AND "tablo_access"."user_id" = auth.uid()
|
|
AND "tablo_access"."is_active" = true
|
|
)
|
|
);
|
|
|
|
CREATE POLICY "Users can delete tasks in their tablos"
|
|
ON "public"."tasks"
|
|
FOR DELETE
|
|
USING (
|
|
EXISTS (
|
|
SELECT 1 FROM "public"."tablo_access"
|
|
WHERE "tablo_access"."tablo_id" = "tasks"."tablo_id"
|
|
AND "tablo_access"."user_id" = auth.uid()
|
|
AND "tablo_access"."is_active" = true
|
|
)
|
|
);
|
|
|
|
-- Create a view that includes assignee information
|
|
CREATE OR REPLACE VIEW "public"."tasks_with_assignee" WITH ("security_invoker"='true') AS
|
|
SELECT
|
|
t.id,
|
|
t.tablo_id,
|
|
t.title,
|
|
t.description,
|
|
t.status,
|
|
t.assignee_id,
|
|
t.position,
|
|
t.created_at,
|
|
t.updated_at,
|
|
p.name AS assignee_name,
|
|
p.avatar_url AS assignee_avatar
|
|
FROM "public"."tasks" t
|
|
LEFT JOIN "public"."profiles" p ON t.assignee_id = p.id;
|
|
|
|
ALTER TABLE "public"."tasks_with_assignee" OWNER TO "postgres";
|
|
|
|
COMMENT ON VIEW "public"."tasks_with_assignee" IS 'View that returns tasks with assignee information from profiles';
|
|
|