mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-25 15:18:32 -06:00
adding file name validation
This commit is contained in:
@@ -17,6 +17,7 @@ import {
|
||||
getDateFromStringOrThrow,
|
||||
} from "@/features/local/utils/timeUtils";
|
||||
import { useCreateAssignmentMutation } from "@/features/local/assignments/assignmentHooks";
|
||||
import { validateFileName } from "@/services/fileNameValidation";
|
||||
|
||||
export default function NewItemForm({
|
||||
moduleName: defaultModuleName,
|
||||
@@ -41,20 +42,6 @@ export default function NewItemForm({
|
||||
const [name, setName] = useState("");
|
||||
const [nameError, setNameError] = useState("");
|
||||
|
||||
const validateFileName = (fileName: string): string => {
|
||||
// Check for invalid file system characters
|
||||
const invalidChars = [":", "/", "\\", "*", '"', "<", ">", "|"];
|
||||
|
||||
for (const char of fileName) {
|
||||
if (invalidChars.includes(char)) {
|
||||
return `Name contains invalid character: "${char}". Please avoid: ${invalidChars.join(
|
||||
" "
|
||||
)}`;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
const handleNameChange = (newName: string) => {
|
||||
setName(newName);
|
||||
const error = validateFileName(newName);
|
||||
|
||||
@@ -10,6 +10,7 @@ import { getCoursePathByName } from "../globalSettings/globalSettingsFileStorage
|
||||
import { promises as fs } from "fs";
|
||||
import { courseItemFileStorageService } from "../course/courseItemFileStorageService";
|
||||
import { assignmentMarkdownSerializer } from "./models/utils/assignmentMarkdownSerializer";
|
||||
import { assertValidFileName } from "@/services/fileNameValidation";
|
||||
|
||||
export const assignmentRouter = router({
|
||||
getAssignment: publicProcedure
|
||||
@@ -133,16 +134,7 @@ export async function updateOrCreateAssignmentFile({
|
||||
assignmentName: string;
|
||||
assignment: LocalAssignment;
|
||||
}) {
|
||||
const illegalCharacters = ["<", ">", ":", '"', "/", "\\", "|", "?", "*"];
|
||||
const foundIllegalCharacters = illegalCharacters.filter((char) =>
|
||||
assignmentName.includes(char)
|
||||
);
|
||||
if (foundIllegalCharacters.length > 0) {
|
||||
throw new Error(
|
||||
`"${assignmentName}" cannot contain the following characters: ${foundIllegalCharacters.join(
|
||||
" "
|
||||
)}`
|
||||
);
|
||||
assertValidFileName(assignmentName);
|
||||
}
|
||||
|
||||
const courseDirectory = await getCoursePathByName(courseName);
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import publicProcedure from "../../../services/serverFunctions/publicProcedure";
|
||||
import { z } from "zod";
|
||||
import { router } from "../../../services/serverFunctions/trpcSetup";
|
||||
import { LocalCoursePage, localPageMarkdownUtils, zodLocalCoursePage } from "@/features/local/pages/localCoursePageModels";
|
||||
import {
|
||||
LocalCoursePage,
|
||||
localPageMarkdownUtils,
|
||||
zodLocalCoursePage,
|
||||
} from "@/features/local/pages/localCoursePageModels";
|
||||
import { courseItemFileStorageService } from "../course/courseItemFileStorageService";
|
||||
import { promises as fs } from "fs";
|
||||
import path from "path";
|
||||
import { getCoursePathByName } from "../globalSettings/globalSettingsFileStorageService";
|
||||
import { assertValidFileName } from "@/services/fileNameValidation";
|
||||
|
||||
export const pageRouter = router({
|
||||
getPage: publicProcedure
|
||||
@@ -119,12 +124,13 @@ export async function updatePageFile({
|
||||
moduleName,
|
||||
pageName,
|
||||
page,
|
||||
}: {
|
||||
}: {
|
||||
courseName: string;
|
||||
moduleName: string;
|
||||
pageName: string;
|
||||
page: LocalCoursePage;
|
||||
}) {
|
||||
}) {
|
||||
assertValidFileName(pageName);
|
||||
const courseDirectory = await getCoursePathByName(courseName);
|
||||
const folder = path.join(courseDirectory, moduleName, "pages");
|
||||
await fs.mkdir(folder, { recursive: true });
|
||||
@@ -139,7 +145,7 @@ export async function updatePageFile({
|
||||
const pageMarkdown = localPageMarkdownUtils.toMarkdown(page);
|
||||
console.log(`Saving page ${filePath}`);
|
||||
await fs.writeFile(filePath, pageMarkdown);
|
||||
}
|
||||
}
|
||||
async function deletePageFile({
|
||||
courseName,
|
||||
moduleName,
|
||||
|
||||
@@ -10,6 +10,7 @@ import path from "path";
|
||||
import { promises as fs } from "fs";
|
||||
import { quizMarkdownUtils } from "./models/utils/quizMarkdownUtils";
|
||||
import { courseItemFileStorageService } from "../course/courseItemFileStorageService";
|
||||
import { assertValidFileName } from "@/services/fileNameValidation";
|
||||
|
||||
export const quizRouter = router({
|
||||
getQuiz: publicProcedure
|
||||
@@ -149,6 +150,7 @@ export async function updateQuizFile({
|
||||
quizName: string;
|
||||
quiz: LocalQuiz;
|
||||
}) {
|
||||
assertValidFileName(quizName);
|
||||
const courseDirectory = await getCoursePathByName(courseName);
|
||||
const folder = path.join(courseDirectory, moduleName, "quizzes");
|
||||
await fs.mkdir(folder, { recursive: true });
|
||||
|
||||
28
src/services/fileNameValidation.ts
Normal file
28
src/services/fileNameValidation.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
export function validateFileName(fileName: string): string {
|
||||
if (!fileName || fileName.trim() === "") {
|
||||
return "Name cannot be empty";
|
||||
}
|
||||
|
||||
const invalidChars = [":", "/", "\\", "*", "?", '"', "<", ">", "|"];
|
||||
|
||||
for (const char of fileName) {
|
||||
if (invalidChars.includes(char)) {
|
||||
return `Name contains invalid character: "${char}". Please avoid: ${invalidChars.join(
|
||||
" "
|
||||
)}`;
|
||||
}
|
||||
}
|
||||
|
||||
if (fileName !== fileName.trimEnd()) {
|
||||
return "Name cannot end with whitespace";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
export function assertValidFileName(fileName: string): void {
|
||||
const error = validateFileName(fileName);
|
||||
if (error) {
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user