Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ You can also check the
component for smaller breakpoints
- Maintenance
- Improved code organization around Browse page
- Security
- Improved security of color palette API routes

### 6.0.0 - 2025-09-05

Expand Down
54 changes: 43 additions & 11 deletions app/db/palettes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
} from "@/utils/chart-config/api";

export const createPaletteForUser = async (
data: CreateCustomColorPalette & { user_id?: number }
data: CreateCustomColorPalette & { user_id: number }
): Promise<CustomPaletteType> => {
const palette = await prisma.palette.create({
data: {
Expand All @@ -28,9 +28,11 @@ export const createPaletteForUser = async (
};
};

export const getPalettesForUser = async (
user_id?: number
): Promise<CustomPaletteType[]> => {
export const getPalettesForUser = async ({
user_id,
}: {
user_id: number;
}): Promise<CustomPaletteType[]> => {
const palettes = await prisma.palette.findMany({
where: {
user_id,
Expand All @@ -47,25 +49,55 @@ export const getPalettesForUser = async (
});
};

export const deletePaletteForUser = async (paletteId: string) => {
export const deletePaletteForUser = async ({
paletteId,
user_id,
}: {
paletteId: string;
user_id: number;
}) => {
const palette = await prisma.palette.findUnique({
where: {
paletteId,
},
});

if (!palette || palette.user_id !== user_id) {
throw new Error("Palette not found");
}

await prisma.palette.delete({
where: {
paletteId,
},
});
};

export const updatePaletteForUser = async (data: UpdateCustomColorPalette) => {
const type = data.type && convertPaletteTypeToDBType(data.type);
export const updatePaletteForUser = async ({
type,
paletteId,
name,
colors,
user_id,
}: UpdateCustomColorPalette & { user_id: number }) => {
const palette = await prisma.palette.findUnique({
where: {
paletteId,
},
});

if (!palette || palette.user_id !== user_id) {
throw new Error("Palette not found");
}

await prisma.palette.update({
where: {
paletteId: data.paletteId,
paletteId,
},
data: {
name: data.name,
colors: data.colors,
type,
name,
colors,
type: type && convertPaletteTypeToDBType(type),
updated_at: new Date(),
},
});
Expand Down
2 changes: 1 addition & 1 deletion app/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ model Palette {
created_at DateTime @default(now()) @db.Timestamp(6)
updated_at DateTime @default(now()) @db.Timestamp(6)

user User? @relation(fields: [user_id], references: [id])
user User? @relation(fields: [user_id], references: [id], onDelete: Cascade)
user_id Int?

@@map("palettes")
Expand Down
42 changes: 36 additions & 6 deletions app/server/user-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ export const UserController = controller({
createPalette: async ({ req, res }) => {
const session = await getServerSession(req, res, nextAuthOptions);
const userId = session?.user?.id;

if (!userId) {
throw new Error(
"You must be logged in to create a custom color palette!"
);
}

const data: CreateCustomColorPalette = req.body;

return await createPaletteForUser({
Expand All @@ -29,18 +36,41 @@ export const UserController = controller({
const session = await getServerSession(req, res, nextAuthOptions);
const userId = session?.user?.id;

return await getPalettesForUser(userId);
if (!userId) {
throw new Error(
"You must be logged in to view your custom color palettes!"
);
}

return await getPalettesForUser({ user_id: userId });
},
deletePalette: async ({ req }) => {
deletePalette: async ({ req, res }) => {
const session = await getServerSession(req, res, nextAuthOptions);
const userId = session?.user?.id;

if (!userId) {
throw new Error(
"You must be logged in to delete a custom color palette!"
);
}

const data: DeleteCustomColorPalette = req.body;
const paletteId = data.paletteId;

await deletePaletteForUser(paletteId);
await deletePaletteForUser({ ...data, user_id: userId });
},

updatePalette: async ({ req }) => {
updatePalette: async ({ req, res }) => {
const session = await getServerSession(req, res, nextAuthOptions);
const userId = session?.user?.id;

if (!userId) {
throw new Error(
"You must be logged in to update a custom color palette!"
);
}

const data: UpdateCustomColorPalette = req.body;

await updatePaletteForUser(data);
await updatePaletteForUser({ ...data, user_id: userId });
},
});
9 changes: 5 additions & 4 deletions app/utils/chart-config/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { createId } from "../create-id";
import type apiConfig from "../../pages/api/config/[key]";
import type apiConfigCreate from "../../pages/api/config-create";
import type apiConfigUpdate from "../../pages/api/config-update";
import type apiUserColorPalette from "../../pages/api/user/color-palette";

export type CreateCustomColorPalette = Omit<CustomPaletteType, "paletteId">;
export type UpdateCustomColorPalette = Partial<
Expand Down Expand Up @@ -116,7 +117,7 @@ export const fetchChartViewCount = async (id: string) => {
export const createCustomColorPalette = async (
options: CreateCustomColorPalette
) => {
return (await apiFetch<InferAPIResponse<typeof apiConfigCreate, "POST">>(
return (await apiFetch<InferAPIResponse<typeof apiUserColorPalette, "POST">>(
"/api/user/color-palette",
{
method: "POST",
Expand All @@ -128,7 +129,7 @@ export const createCustomColorPalette = async (
export const getCustomColorPalettes = async (): Promise<
CustomPaletteType[]
> => {
return (await apiFetch<InferAPIResponse<typeof apiConfigCreate, "GET">>(
return (await apiFetch<InferAPIResponse<typeof apiUserColorPalette, "GET">>(
"/api/user/color-palette",
{
method: "GET",
Expand All @@ -139,7 +140,7 @@ export const getCustomColorPalettes = async (): Promise<
export const deleteCustomColorPalette = async (
options: DeleteCustomColorPalette
) => {
await apiFetch<InferAPIResponse<typeof apiConfigCreate, "DELETE">>(
await apiFetch<InferAPIResponse<typeof apiUserColorPalette, "DELETE">>(
"/api/user/color-palette",
{
method: "DELETE",
Expand All @@ -151,7 +152,7 @@ export const deleteCustomColorPalette = async (
export const updateCustomColorPalette = async (
options: UpdateCustomColorPalette
) => {
await apiFetch<InferAPIResponse<typeof apiConfigCreate, "PUT">>(
await apiFetch<InferAPIResponse<typeof apiUserColorPalette, "PUT">>(
"/api/user/color-palette",
{
method: "PUT",
Expand Down