mirror of
https://github.com/Tony0410/quietthanks.git
synced 2026-05-24 21:31:41 +08:00
Add user authentication with login/register
- Add users and sessions tables to database schema - Add bcryptjs for password hashing - Create auth API routes (login, register, logout, me) - Add AuthProvider context for client-side auth state - Update all API routes to require authentication and filter by userId - Create login and register pages - Add AppShell component for authenticated layout - Update all pages to use AppShell and show user info - Each user now has their own private entries and tags Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,10 +2,16 @@ import { NextRequest, NextResponse } from "next/server";
|
||||
import { db, schema } from "@/lib/db";
|
||||
import { eq, desc, and, inArray, gte } from "drizzle-orm";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { getSession } from "@/lib/auth";
|
||||
import type { CreateEntryRequest, EntryWithTags } from "@/lib/types";
|
||||
|
||||
// GET /api/entries - List entries with optional filters
|
||||
export async function GET(request: NextRequest) {
|
||||
const user = await getSession();
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
}
|
||||
|
||||
const { searchParams } = new URL(request.url);
|
||||
const moods = searchParams.get("moods")?.split(",").map(Number).filter(Boolean);
|
||||
const tagId = searchParams.get("tagId");
|
||||
@@ -13,8 +19,8 @@ export async function GET(request: NextRequest) {
|
||||
const since = searchParams.get("since"); // YYYY-MM-DD
|
||||
|
||||
try {
|
||||
// Build conditions
|
||||
const conditions = [];
|
||||
// Build conditions - always filter by userId
|
||||
const conditions = [eq(schema.entries.userId, user.id)];
|
||||
if (moods && moods.length > 0) {
|
||||
conditions.push(inArray(schema.entries.mood, moods));
|
||||
}
|
||||
@@ -31,7 +37,7 @@ export async function GET(request: NextRequest) {
|
||||
const entries = await db
|
||||
.select()
|
||||
.from(schema.entries)
|
||||
.where(conditions.length > 0 ? and(...conditions) : undefined)
|
||||
.where(and(...conditions))
|
||||
.orderBy(desc(schema.entries.date), desc(schema.entries.createdAt));
|
||||
|
||||
// Get tags for each entry
|
||||
@@ -62,6 +68,11 @@ export async function GET(request: NextRequest) {
|
||||
|
||||
// POST /api/entries - Create or update today's entry
|
||||
export async function POST(request: NextRequest) {
|
||||
const user = await getSession();
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
}
|
||||
|
||||
try {
|
||||
const body: CreateEntryRequest = await request.json();
|
||||
const { date, text, mood, roughDay, tagNames } = body;
|
||||
@@ -72,11 +83,16 @@ export async function POST(request: NextRequest) {
|
||||
|
||||
const now = Date.now();
|
||||
|
||||
// Check if entry exists for this date
|
||||
// Check if entry exists for this date for this user
|
||||
const existing = await db
|
||||
.select()
|
||||
.from(schema.entries)
|
||||
.where(eq(schema.entries.date, date))
|
||||
.where(
|
||||
and(
|
||||
eq(schema.entries.userId, user.id),
|
||||
eq(schema.entries.date, date)
|
||||
)
|
||||
)
|
||||
.limit(1);
|
||||
|
||||
let entryId: string;
|
||||
@@ -98,6 +114,7 @@ export async function POST(request: NextRequest) {
|
||||
entryId = uuidv4();
|
||||
await db.insert(schema.entries).values({
|
||||
id: entryId,
|
||||
userId: user.id,
|
||||
date,
|
||||
text,
|
||||
mood: mood ?? null,
|
||||
@@ -117,11 +134,16 @@ export async function POST(request: NextRequest) {
|
||||
const normalizedName = name.toLowerCase().trim();
|
||||
if (!normalizedName) continue;
|
||||
|
||||
// Find or create tag
|
||||
// Find or create tag for this user
|
||||
let tag = await db
|
||||
.select()
|
||||
.from(schema.tags)
|
||||
.where(eq(schema.tags.name, normalizedName))
|
||||
.where(
|
||||
and(
|
||||
eq(schema.tags.userId, user.id),
|
||||
eq(schema.tags.name, normalizedName)
|
||||
)
|
||||
)
|
||||
.limit(1);
|
||||
|
||||
let tagId: string;
|
||||
@@ -129,6 +151,7 @@ export async function POST(request: NextRequest) {
|
||||
tagId = uuidv4();
|
||||
await db.insert(schema.tags).values({
|
||||
id: tagId,
|
||||
userId: user.id,
|
||||
name: normalizedName,
|
||||
createdAt: now,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user