Remove internal table CRUD APIs

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
This commit is contained in:
Max 2026-02-21 17:57:25 -06:00
parent b0fc52ade4
commit 9778c20dbf
3 changed files with 0 additions and 346 deletions

View File

@ -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 <user-id>"
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 <user-id> <field> <value>"
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 <user-id>"
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 <key>"
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 <key> <value>"
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 <key>"
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 <field> <value> Update account (name, email)
auth users List all users
USER ADMIN COMMANDS:
user list List all users (same as auth users)
user get <user-id> Get specific user
user update <id> <field> <val> Update user field
Fields: name, email, avatar_url
user delete <user-id> Delete a user
META COMMANDS:
meta list List all meta entries
meta get <key> Get specific meta value
meta set <key> <value> Set meta key-value pair
meta delete <key> 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 ;;

View File

@ -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 });
}
}

View File

@ -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<string, unknown> = {};
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 });
}
}