can add existing courses

This commit is contained in:
2025-07-22 14:23:40 -06:00
parent 67b67100c1
commit 704a5ae404
18 changed files with 209 additions and 30 deletions

View File

@@ -47,6 +47,7 @@ export const fileStorageService = {
await fs.mkdir(courseDirectory, { recursive: true });
},
async createModuleFolderForTesting(courseName: string, moduleName: string) {
const courseDirectory = path.join(basePath, courseName, moduleName);
@@ -57,6 +58,12 @@ export const fileStorageService = {
relativePath: string
): Promise<{ files: string[]; folders: string[] }> {
const fullPath = path.join(basePath, relativePath);
// Security: ensure fullPath is inside basePath
const resolvedBase = path.resolve(basePath);
const resolvedFull = path.resolve(fullPath);
if (!resolvedFull.startsWith(resolvedBase)) {
return { files: [], folders: [] };
}
if (!(await directoryOrFileExists(fullPath))) {
throw new Error(`Directory ${fullPath} does not exist`);
}

View File

@@ -1,5 +1,8 @@
import { GlobalSettings } from "@/models/local/globalSettings";
import { parseGlobalSettingsYaml } from "@/models/local/globalSettingsUtils";
import {
globalSettingsToYaml,
parseGlobalSettingsYaml,
} from "@/models/local/globalSettingsUtils";
import { promises as fs } from "fs";
import path from "path";
import { basePath } from "./utils/fileSystemUtils";
@@ -34,3 +37,8 @@ export const getCoursePathByName = async (courseName: string) => {
}
return path.join(basePath, course.path);
};
export const updateGlobalSettings = async (globalSettings: GlobalSettings) => {
const globalSettingsString = globalSettingsToYaml(globalSettings);
await fs.writeFile(SETTINGS_FILE_PATH, globalSettingsString, "utf-8");
};

View File

@@ -86,4 +86,11 @@ export const settingsFileStorageService = {
console.log(`Saving settings ${settingsPath}`);
await fs.writeFile(settingsPath, settingsMarkdown);
},
async folderIsCourse(folderPath: string) {
const settingsPath = path.join(basePath, folderPath, "settings.yml");
if (!(await directoryOrFileExists(settingsPath))) {
return false;
}
return true;
},
};

View File

@@ -3,6 +3,7 @@ import { createCallerFactory, router } from "../trpcSetup";
import { assignmentRouter } from "./assignmentRouter";
import { canvasFileRouter } from "./canvasFileRouter";
import { directoriesRouter } from "./directoriesRouter";
import { globalSettingsRouter } from "./globalSettingsRouter";
import { lectureRouter } from "./lectureRouter";
import { moduleRouter } from "./moduleRouter";
import { pageRouter } from "./pageRouter";
@@ -18,6 +19,7 @@ export const trpcAppRouter = router({
module: moduleRouter,
directories: directoriesRouter,
canvasFile: canvasFileRouter,
globalSettings: globalSettingsRouter,
});
export const createCaller = createCallerFactory(trpcAppRouter);

View File

@@ -16,4 +16,13 @@ export const directoriesRouter = router({
.query(async ({ input: { relativePath } }) => {
return await fileStorageService.getDirectoryContents(relativePath);
}),
directoryIsCourse: publicProcedure
.input(
z.object({
folderPath: z.string(),
})
)
.query(async ({ input: { folderPath } }) => {
return await fileStorageService.settings.folderIsCourse(folderPath);
}),
});

View File

@@ -0,0 +1,23 @@
import { zodGlobalSettings } from "@/models/local/globalSettings";
import { router } from "../trpcSetup";
import z from "zod";
import publicProcedure from "../procedures/public";
import {
getGlobalSettings,
updateGlobalSettings,
} from "@/services/fileStorage/globalSettingsFileStorageService";
export const globalSettingsRouter = router({
getGlobalSettings: publicProcedure.query(async () => {
return await getGlobalSettings();
}),
updateGlobalSettings: publicProcedure
.input(
z.object({
globalSettings: zodGlobalSettings,
})
)
.mutation(async ({ input: { globalSettings } }) => {
return await updateGlobalSettings(globalSettings);
}),
});