fix: OIDC auth flow, Vite proxy, and PostgreSQL query compat
- Add auth redirect in root layout for unauthenticated users - Proxy OIDC routes (/login, /callback, /logout) through Vite dev server - Strip Secure flag from OIDC cookies in dev mode (HTTP localhost) - Disable retry on auth query to prevent stale cookie loops - Fix SQLite .get()/.all()/.run() calls in category and global-item services for PostgreSQL compatibility - Add userId scoping to category service functions - Add OIDC error logging in auth middleware - Apply linter auto-formatting across affected files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
import { beforeEach, describe, expect, it } from "bun:test";
|
||||
import { globalItems, itemGlobalLinks, items } from "../../src/db/schema.ts";
|
||||
import { seedGlobalItems } from "../../src/db/seed-global-items.ts";
|
||||
import {
|
||||
getGlobalItemWithOwnerCount,
|
||||
linkItemToGlobal,
|
||||
searchGlobalItems,
|
||||
unlinkItemFromGlobal,
|
||||
} from "../../src/server/services/global-item.service.ts";
|
||||
import { seedGlobalItems } from "../../src/db/seed-global-items.ts";
|
||||
import { createTestDb } from "../helpers/db.ts";
|
||||
|
||||
type TestDb = ReturnType<typeof createTestDb>;
|
||||
@@ -35,11 +35,7 @@ function insertGlobalItem(
|
||||
}
|
||||
|
||||
function insertItem(db: TestDb, name: string) {
|
||||
return db
|
||||
.insert(items)
|
||||
.values({ name, categoryId: 1 })
|
||||
.returning()
|
||||
.get();
|
||||
return db.insert(items).values({ name, categoryId: 1 }).returning().get();
|
||||
}
|
||||
|
||||
describe("Global Item Service", () => {
|
||||
@@ -51,7 +47,10 @@ describe("Global Item Service", () => {
|
||||
|
||||
describe("searchGlobalItems", () => {
|
||||
it("returns all global items when no query provided", () => {
|
||||
insertGlobalItem(db, { brand: "Revelate Designs", model: "Terrapin System" });
|
||||
insertGlobalItem(db, {
|
||||
brand: "Revelate Designs",
|
||||
model: "Terrapin System",
|
||||
});
|
||||
insertGlobalItem(db, { brand: "Apidura", model: "Handlebar Pack" });
|
||||
|
||||
const results = searchGlobalItems(db);
|
||||
@@ -59,7 +58,10 @@ describe("Global Item Service", () => {
|
||||
});
|
||||
|
||||
it("returns items matching brand (case-insensitive)", () => {
|
||||
insertGlobalItem(db, { brand: "Revelate Designs", model: "Terrapin System" });
|
||||
insertGlobalItem(db, {
|
||||
brand: "Revelate Designs",
|
||||
model: "Terrapin System",
|
||||
});
|
||||
insertGlobalItem(db, { brand: "Apidura", model: "Handlebar Pack" });
|
||||
|
||||
const results = searchGlobalItems(db, "revelate");
|
||||
@@ -68,7 +70,10 @@ describe("Global Item Service", () => {
|
||||
});
|
||||
|
||||
it("returns items matching model (case-insensitive)", () => {
|
||||
insertGlobalItem(db, { brand: "Revelate Designs", model: "Terrapin System" });
|
||||
insertGlobalItem(db, {
|
||||
brand: "Revelate Designs",
|
||||
model: "Terrapin System",
|
||||
});
|
||||
insertGlobalItem(db, { brand: "Apidura", model: "Handlebar Pack" });
|
||||
|
||||
const results = searchGlobalItems(db, "HANDLEBAR");
|
||||
@@ -77,7 +82,10 @@ describe("Global Item Service", () => {
|
||||
});
|
||||
|
||||
it("does not match everything with wildcard chars", () => {
|
||||
insertGlobalItem(db, { brand: "Revelate Designs", model: "Terrapin System" });
|
||||
insertGlobalItem(db, {
|
||||
brand: "Revelate Designs",
|
||||
model: "Terrapin System",
|
||||
});
|
||||
insertGlobalItem(db, { brand: "Apidura", model: "Handlebar Pack" });
|
||||
|
||||
const results = searchGlobalItems(db, "100%");
|
||||
@@ -87,7 +95,10 @@ describe("Global Item Service", () => {
|
||||
|
||||
describe("getGlobalItemWithOwnerCount", () => {
|
||||
it("returns item with ownerCount 0 when no links", () => {
|
||||
const gi = insertGlobalItem(db, { brand: "MSR", model: "PocketRocket 2" });
|
||||
const gi = insertGlobalItem(db, {
|
||||
brand: "MSR",
|
||||
model: "PocketRocket 2",
|
||||
});
|
||||
|
||||
const result = getGlobalItemWithOwnerCount(db, gi.id);
|
||||
expect(result).not.toBeNull();
|
||||
@@ -96,7 +107,10 @@ describe("Global Item Service", () => {
|
||||
});
|
||||
|
||||
it("returns ownerCount matching number of linked items", () => {
|
||||
const gi = insertGlobalItem(db, { brand: "MSR", model: "PocketRocket 2" });
|
||||
const gi = insertGlobalItem(db, {
|
||||
brand: "MSR",
|
||||
model: "PocketRocket 2",
|
||||
});
|
||||
const item1 = insertItem(db, "My Stove");
|
||||
const item2 = insertItem(db, "Another Stove");
|
||||
|
||||
@@ -120,7 +134,10 @@ describe("Global Item Service", () => {
|
||||
|
||||
describe("linkItemToGlobal", () => {
|
||||
it("creates link and returns link row", () => {
|
||||
const gi = insertGlobalItem(db, { brand: "MSR", model: "PocketRocket 2" });
|
||||
const gi = insertGlobalItem(db, {
|
||||
brand: "MSR",
|
||||
model: "PocketRocket 2",
|
||||
});
|
||||
const item = insertItem(db, "My Stove");
|
||||
|
||||
const link = linkItemToGlobal(db, item.id, gi.id);
|
||||
@@ -129,7 +146,10 @@ describe("Global Item Service", () => {
|
||||
});
|
||||
|
||||
it("throws when item already linked", () => {
|
||||
const gi = insertGlobalItem(db, { brand: "MSR", model: "PocketRocket 2" });
|
||||
const gi = insertGlobalItem(db, {
|
||||
brand: "MSR",
|
||||
model: "PocketRocket 2",
|
||||
});
|
||||
const item = insertItem(db, "My Stove");
|
||||
|
||||
linkItemToGlobal(db, item.id, gi.id);
|
||||
@@ -139,7 +159,10 @@ describe("Global Item Service", () => {
|
||||
|
||||
describe("unlinkItemFromGlobal", () => {
|
||||
it("removes the link", () => {
|
||||
const gi = insertGlobalItem(db, { brand: "MSR", model: "PocketRocket 2" });
|
||||
const gi = insertGlobalItem(db, {
|
||||
brand: "MSR",
|
||||
model: "PocketRocket 2",
|
||||
});
|
||||
const item = insertItem(db, "My Stove");
|
||||
|
||||
linkItemToGlobal(db, item.id, gi.id);
|
||||
|
||||
Reference in New Issue
Block a user