From 9778c20dbfdc38d2f6b809eee8d570e63919ee33 Mon Sep 17 00:00:00 2001 From: Max Date: Sat, 21 Feb 2026 17:57:25 -0600 Subject: [PATCH] Remove internal table CRUD APIs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removed public CRUD for internal tables: - Deleted /api/meta - internal key-value store - Deleted /api/users - use auth endpoints instead - Removed CLI commands: user admin and meta operations Core app tables with CRUD: ✅ tasks - Full CRUD ✅ projects - Full CRUD (list, get, create, update, delete) ✅ sprints - Full CRUD (list, get, create, update, delete) Auth tables (internal, no public CRUD): - users - Managed via /api/auth/* endpoints - sessions - Managed by auth system - password_reset_tokens - Managed by forgot/reset flow - meta - Internal use only --- scripts/gantt.sh | 127 ------------------------------------- src/app/api/meta/route.ts | 101 ----------------------------- src/app/api/users/route.ts | 118 ---------------------------------- 3 files changed, 346 deletions(-) delete mode 100644 src/app/api/meta/route.ts delete mode 100644 src/app/api/users/route.ts diff --git a/scripts/gantt.sh b/scripts/gantt.sh index a06d13c..c28d962 100755 --- a/scripts/gantt.sh +++ b/scripts/gantt.sh @@ -526,98 +526,6 @@ cmd_auth_users() { api_call GET "/auth/users" } -#=================== -# USER ADMIN OPERATIONS -#=================== - -cmd_user_get() { - local user_id="$1" - - if [ -z "$user_id" ]; then - log_error "Usage: user get " - exit 1 - fi - - log_info "Fetching user $user_id..." - api_call GET "/users?id=$user_id" | jq '.user' -} - -cmd_user_update() { - local user_id="$1" - local field="$2" - local value="$3" - - if [ -z "$user_id" ] || [ -z "$field" ] || [ -z "$value" ]; then - log_error "Usage: user update " - echo "Fields: name, email, avatar_url" - exit 1 - fi - - log_info "Updating user $user_id: $field = $value" - local data - data=$(jq -n --arg id "$user_id" --arg field "$field" --arg value "$value" \ - '{id: $id, ($field): $value}') - api_call PATCH "/users" "$data" -} - -cmd_user_delete() { - local user_id="$1" - - if [ -z "$user_id" ]; then - log_error "Usage: user delete " - exit 1 - fi - - log_warn "Deleting user $user_id..." - api_call DELETE "/users" "{\"id\": \"$user_id\"}" -} - -#=================== -# META OPERATIONS -#=================== - -cmd_meta_list() { - log_info "Fetching meta entries..." - api_call GET "/meta" | jq '.meta' -} - -cmd_meta_get() { - local key="$1" - - if [ -z "$key" ]; then - log_error "Usage: meta get " - exit 1 - fi - - log_info "Fetching meta key: $key" - api_call GET "/meta?key=$key" | jq '.meta | .[0]' -} - -cmd_meta_set() { - local key="$1" - local value="$2" - - if [ -z "$key" ] || [ -z "$value" ]; then - log_error "Usage: meta set " - exit 1 - fi - - log_info "Setting meta $key = $value" - api_call POST "/meta" "{\"key\": \"$key\", \"value\": \"$value\"}" -} - -cmd_meta_delete() { - local key="$1" - - if [ -z "$key" ]; then - log_error "Usage: meta delete " - exit 1 - fi - - log_warn "Deleting meta key: $key" - api_call DELETE "/meta" "{\"key\": \"$key\"}" -} - #=================== # DEBUG OPERATIONS #=================== @@ -683,19 +591,6 @@ AUTH COMMANDS: auth account Update account (name, email) auth users List all users -USER ADMIN COMMANDS: - user list List all users (same as auth users) - user get Get specific user - user update Update user field - Fields: name, email, avatar_url - user delete Delete a user - -META COMMANDS: - meta list List all meta entries - meta get Get specific meta value - meta set Set meta key-value pair - meta delete Delete meta entry - OTHER COMMANDS: debug Call debug endpoint help Show this help message @@ -787,28 +682,6 @@ main() { *) log_error "Unknown auth command: $subcmd"; show_help; exit 1 ;; esac ;; - user|users) - local subcmd="${1:-list}" - shift || true - case "$subcmd" in - list|ls) cmd_auth_users "$@" ;; # Reuse auth users list - get|show) cmd_user_get "$@" ;; - update|set|edit) cmd_user_update "$@" ;; - delete|rm|remove) cmd_user_delete "$@" ;; - *) log_error "Unknown user command: $subcmd"; show_help; exit 1 ;; - esac - ;; - meta) - local subcmd="${1:-list}" - shift || true - case "$subcmd" in - list|ls) cmd_meta_list "$@" ;; - get|show) cmd_meta_get "$@" ;; - set|create|update) cmd_meta_set "$@" ;; - delete|rm|remove) cmd_meta_delete "$@" ;; - *) log_error "Unknown meta command: $subcmd"; show_help; exit 1 ;; - esac - ;; debug) cmd_debug "$@" ;; help|--help|-h) show_help ;; *) log_error "Unknown command: $cmd"; show_help; exit 1 ;; diff --git a/src/app/api/meta/route.ts b/src/app/api/meta/route.ts deleted file mode 100644 index e79fb9f..0000000 --- a/src/app/api/meta/route.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { NextResponse } from "next/server"; -import { getServiceSupabase } from "@/lib/supabase/client"; -import { getAuthenticatedUser } from "@/lib/server/auth"; - -export const runtime = "nodejs"; - -// GET - fetch all meta entries or specific key -export async function GET(request: Request) { - try { - const user = await getAuthenticatedUser(); - if (!user) { - return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); - } - - const { searchParams } = new URL(request.url); - const key = searchParams.get("key"); - - const supabase = getServiceSupabase(); - - let query = supabase.from("meta").select("*"); - if (key) { - query = query.eq("key", key); - } - - const { data, error } = await query.order("key"); - - if (error) throw error; - - return NextResponse.json({ meta: data || [] }); - } catch (error) { - console.error(">>> API GET /meta error:", error); - return NextResponse.json({ error: "Failed to fetch meta" }, { status: 500 }); - } -} - -// POST - create or update a meta entry -export async function POST(request: Request) { - try { - const user = await getAuthenticatedUser(); - if (!user) { - return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); - } - - const body = await request.json(); - const { key, value } = body; - - if (!key || typeof key !== "string") { - return NextResponse.json({ error: "Missing key" }, { status: 400 }); - } - - if (value === undefined) { - return NextResponse.json({ error: "Missing value" }, { status: 400 }); - } - - const supabase = getServiceSupabase(); - const now = new Date().toISOString(); - - const { data, error } = await supabase - .from("meta") - .upsert({ - key, - value: String(value), - updated_at: now, - }) - .select() - .single(); - - if (error) throw error; - - return NextResponse.json({ success: true, meta: data }); - } catch (error) { - console.error(">>> API POST /meta error:", error); - return NextResponse.json({ error: "Failed to save meta" }, { status: 500 }); - } -} - -// DELETE - delete a meta entry -export async function DELETE(request: Request) { - try { - const user = await getAuthenticatedUser(); - if (!user) { - return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); - } - - const { key } = await request.json(); - - if (!key) { - return NextResponse.json({ error: "Missing key" }, { status: 400 }); - } - - const supabase = getServiceSupabase(); - const { error } = await supabase.from("meta").delete().eq("key", key); - - if (error) throw error; - - return NextResponse.json({ success: true }); - } catch (error) { - console.error(">>> API DELETE /meta error:", error); - return NextResponse.json({ error: "Failed to delete meta" }, { status: 500 }); - } -} diff --git a/src/app/api/users/route.ts b/src/app/api/users/route.ts deleted file mode 100644 index ef7cd66..0000000 --- a/src/app/api/users/route.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { NextResponse } from "next/server"; -import { getServiceSupabase } from "@/lib/supabase/client"; -import { getAuthenticatedUser } from "@/lib/server/auth"; - -export const runtime = "nodejs"; - -// GET - fetch single user by ID -export async function GET(request: Request) { - try { - const currentUser = await getAuthenticatedUser(); - if (!currentUser) { - return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); - } - - const { searchParams } = new URL(request.url); - const id = searchParams.get("id"); - - if (!id) { - return NextResponse.json({ error: "Missing user id" }, { status: 400 }); - } - - const supabase = getServiceSupabase(); - const { data, error } = await supabase - .from("users") - .select("id, name, email, avatar_url, created_at") - .eq("id", id) - .single(); - - if (error) { - if (error.code === "PGRST116") { - return NextResponse.json({ error: "User not found" }, { status: 404 }); - } - throw error; - } - - return NextResponse.json({ user: data }); - } catch (error) { - console.error(">>> API GET /user error:", error); - return NextResponse.json({ error: "Failed to fetch user" }, { status: 500 }); - } -} - -// PATCH - update user fields (admin only) -export async function PATCH(request: Request) { - try { - const currentUser = await getAuthenticatedUser(); - if (!currentUser) { - return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); - } - - const body = await request.json(); - const { id, ...updates } = body; - - if (!id) { - return NextResponse.json({ error: "Missing user id" }, { status: 400 }); - } - - // Only allow certain fields to be updated - const allowedFields = ["name", "email", "avatar_url"]; - const dbUpdates: Record = {}; - - for (const field of allowedFields) { - if (updates[field] !== undefined) { - dbUpdates[field] = updates[field]; - } - } - - if (Object.keys(dbUpdates).length === 0) { - return NextResponse.json({ error: "No valid fields to update" }, { status: 400 }); - } - - const supabase = getServiceSupabase(); - const { data, error } = await supabase - .from("users") - .update(dbUpdates) - .eq("id", id) - .select("id, name, email, avatar_url, created_at") - .single(); - - if (error) throw error; - - return NextResponse.json({ success: true, user: data }); - } catch (error) { - console.error(">>> API PATCH /user error:", error); - return NextResponse.json({ error: "Failed to update user" }, { status: 500 }); - } -} - -// DELETE - delete a user (admin only) -export async function DELETE(request: Request) { - try { - const currentUser = await getAuthenticatedUser(); - if (!currentUser) { - return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); - } - - const { id } = await request.json(); - - if (!id) { - return NextResponse.json({ error: "Missing user id" }, { status: 400 }); - } - - // Prevent self-deletion - if (id === currentUser.id) { - return NextResponse.json({ error: "Cannot delete yourself" }, { status: 400 }); - } - - const supabase = getServiceSupabase(); - const { error } = await supabase.from("users").delete().eq("id", id); - - if (error) throw error; - - return NextResponse.json({ success: true }); - } catch (error) { - console.error(">>> API DELETE /user error:", error); - return NextResponse.json({ error: "Failed to delete user" }, { status: 500 }); - } -}