fixes #2082, fixes #2066 - fallback to cuid2 if filename contains non-latin characters

This commit is contained in:
Amruth Pillai
2025-01-12 18:06:44 +01:00
parent 2d62504895
commit 6335ad1571
11 changed files with 54 additions and 36 deletions
@@ -33,7 +33,8 @@ import {
Input,
Tooltip,
} from "@reactive-resume/ui";
import { cn, generateRandomName, kebabCase } from "@reactive-resume/utils";
import { cn, generateRandomName } from "@reactive-resume/utils";
import slugify from "@sindresorhus/slugify";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { z } from "zod";
@@ -71,7 +72,7 @@ export const ResumeDialog = () => {
}, [isOpen, payload]);
useEffect(() => {
const slug = kebabCase(form.watch("title"));
const slug = slugify(form.watch("title"));
form.setValue("slug", slug);
}, [form.watch("title")]);
@@ -122,7 +123,7 @@ export const ResumeDialog = () => {
const onGenerateRandomName = () => {
const name = generateRandomName();
form.setValue("title", name);
form.setValue("slug", kebabCase(name));
form.setValue("slug", slugify(name));
};
const onCreateSample = async () => {
@@ -130,7 +131,7 @@ export const ResumeDialog = () => {
await duplicateResume({
title: randomName,
slug: kebabCase(randomName),
slug: slugify(randomName),
data: sampleResume,
});
@@ -209,6 +209,8 @@ export class PrinterService {
return resumeUrl;
} catch (error) {
this.logger.error(error);
throw new InternalServerErrorException(
ErrorMessage.ResumePrinterError,
(error as Error).message,
+4 -3
View File
@@ -8,7 +8,8 @@ import { Prisma } from "@prisma/client";
import { CreateResumeDto, ImportResumeDto, ResumeDto, UpdateResumeDto } from "@reactive-resume/dto";
import { defaultResumeData, ResumeData } from "@reactive-resume/schema";
import type { DeepPartial } from "@reactive-resume/utils";
import { ErrorMessage, generateRandomName, kebabCase } from "@reactive-resume/utils";
import { ErrorMessage, generateRandomName } from "@reactive-resume/utils";
import slugify from "@sindresorhus/slugify";
import deepmerge from "deepmerge";
import { PrismaService } from "nestjs-prisma";
@@ -40,7 +41,7 @@ export class ResumeService {
userId,
title: createResumeDto.title,
visibility: createResumeDto.visibility,
slug: createResumeDto.slug ?? kebabCase(createResumeDto.title),
slug: createResumeDto.slug ?? slugify(createResumeDto.title),
},
});
}
@@ -54,7 +55,7 @@ export class ResumeService {
visibility: "private",
data: importResumeDto.data,
title: importResumeDto.title ?? randomTitle,
slug: importResumeDto.slug ?? kebabCase(randomTitle),
slug: importResumeDto.slug ?? slugify(randomTitle),
},
});
}
+8 -2
View File
@@ -1,6 +1,7 @@
import { Injectable, InternalServerErrorException, Logger, OnModuleInit } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { createId } from "@paralleldrive/cuid2";
import slugify from "@sindresorhus/slugify";
import { MinioClient, MinioService } from "nestjs-minio-client";
import sharp from "sharp";
@@ -116,14 +117,19 @@ export class StorageService implements OnModuleInit {
) {
const extension = type === "resumes" ? "pdf" : "jpg";
const storageUrl = this.configService.getOrThrow<string>("STORAGE_URL");
const filepath = `${userId}/${type}/${filename}.${extension}`;
let normalizedFilename = slugify(filename);
if (!normalizedFilename) normalizedFilename = createId();
const filepath = `${userId}/${type}/${normalizedFilename}.${extension}`;
const url = `${storageUrl}/${filepath}`;
const metadata =
extension === "jpg"
? { "Content-Type": "image/jpeg" }
: {
"Content-Type": "application/pdf",
"Content-Disposition": `attachment; filename=${filename}.${extension}`,
"Content-Disposition": `attachment; filename=${normalizedFilename}.${extension}`,
};
try {