mirror of
https://github.com/OHTU-German-learning-website/OHTU-German-learning-website.git
synced 2026-10-12 19:13:51 +03:00
added requirement to be admin and authenticated to access
This commit is contained in:
@@ -1,53 +1,60 @@
|
||||
import { DB } from "@/backend/db";
|
||||
import { withAuth } from "@/backend/middleware/withAuth";
|
||||
|
||||
export async function POST(request) {
|
||||
const json = await request.json();
|
||||
const { title, targetCategory, targetWords, allWords } = json;
|
||||
export const POST = withAuth(
|
||||
async (request) => {
|
||||
const json = await request.json();
|
||||
const { title, targetCategory, targetWords, allWords } = json;
|
||||
|
||||
if (!title || !targetCategory || !targetWords || !allWords) {
|
||||
return Response.json(
|
||||
{ error: "Alle Felder sind erforderlich." },
|
||||
{ status: 400 }
|
||||
if (!title || !targetCategory || !targetWords || !allWords) {
|
||||
return Response.json(
|
||||
{ error: "Alle Felder sind erforderlich." },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
if (title.length < 3 || title.length > 50) {
|
||||
return Response.json(
|
||||
{ error: "Der Titel muss zwischen 3 und 50 Zeichen lang sein." },
|
||||
{ status: 422 }
|
||||
);
|
||||
}
|
||||
if (targetCategory.length < 3 || targetCategory.length > 30) {
|
||||
return Response.json(
|
||||
{ error: "Die Kategorie muss zwischen 3 und 30 Zeichen lang sein." },
|
||||
{ status: 422 }
|
||||
);
|
||||
}
|
||||
if (targetWords.length < 1 || targetWords.length > 1000) {
|
||||
return Response.json(
|
||||
{ error: "Es müssen zwischen 1 und 1000 Zielwörter vorhanden sein." },
|
||||
{ status: 422 }
|
||||
);
|
||||
}
|
||||
if (allWords.length < 1 || allWords.length > 1000) {
|
||||
return Response.json(
|
||||
{ error: "Es müssen zwischen 1 und 1000 Wörter vorhanden sein." },
|
||||
{ status: 422 }
|
||||
);
|
||||
}
|
||||
const existingExercise = await DB.pool(
|
||||
"SELECT * FROM click_exercises WHERE title = $1",
|
||||
[title]
|
||||
);
|
||||
}
|
||||
if (title.length < 3 || title.length > 50) {
|
||||
return Response.json(
|
||||
{ error: "Der Titel muss zwischen 3 und 50 Zeichen lang sein." },
|
||||
{ status: 422 }
|
||||
);
|
||||
}
|
||||
if (targetCategory.length < 3 || targetCategory.length > 30) {
|
||||
return Response.json(
|
||||
{ error: "Die Kategorie muss zwischen 3 und 30 Zeichen lang sein." },
|
||||
{ status: 422 }
|
||||
);
|
||||
}
|
||||
if (targetWords.length < 1 || targetWords.length > 1000) {
|
||||
return Response.json(
|
||||
{ error: "Es müssen zwischen 1 und 1000 Zielwörter vorhanden sein." },
|
||||
{ status: 422 }
|
||||
);
|
||||
}
|
||||
if (allWords.length < 1 || allWords.length > 1000) {
|
||||
return Response.json(
|
||||
{ error: "Es müssen zwischen 1 und 1000 Wörter vorhanden sein." },
|
||||
{ status: 422 }
|
||||
);
|
||||
}
|
||||
const existingExercise = await DB.pool(
|
||||
"SELECT * FROM click_exercises WHERE title = $1",
|
||||
[title]
|
||||
);
|
||||
if (existingExercise.rows.length > 0) {
|
||||
return Response.json(
|
||||
{ error: "Eine Übung mit diesem Titel existiert bereits." },
|
||||
{ status: 409 }
|
||||
);
|
||||
}
|
||||
const id = await DB.pool(
|
||||
`INSERT INTO click_exercises (title, category, target_words, all_words)
|
||||
if (existingExercise.rows.length > 0) {
|
||||
return Response.json(
|
||||
{ error: "Eine Übung mit diesem Titel existiert bereits." },
|
||||
{ status: 409 }
|
||||
);
|
||||
}
|
||||
const id = await DB.pool(
|
||||
`INSERT INTO click_exercises (title, category, target_words, all_words)
|
||||
VALUES ($1, $2, $3, $4) returning id`,
|
||||
[title, targetCategory, targetWords, allWords]
|
||||
);
|
||||
return Response.json({ id: id.rows[0].id }, { status: 201 });
|
||||
}
|
||||
[title, targetCategory, targetWords, allWords]
|
||||
);
|
||||
return Response.json({ id: id.rows[0].id }, { status: 201 });
|
||||
},
|
||||
{
|
||||
requireAdmin: true,
|
||||
requireAuth: true,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,84 +1,91 @@
|
||||
import { DB } from "@/backend/db";
|
||||
import { withAuth } from "@/backend/middleware/withAuth";
|
||||
|
||||
export async function POST(request) {
|
||||
try {
|
||||
const rawBody = await request.json();
|
||||
const body = rawBody.body ?? rawBody;
|
||||
const title = body.title;
|
||||
const fields = body.fields;
|
||||
export const POST = withAuth(
|
||||
async (request) => {
|
||||
try {
|
||||
const rawBody = await request.json();
|
||||
const body = rawBody.body ?? rawBody;
|
||||
const title = body.title;
|
||||
const fields = body.fields;
|
||||
|
||||
if (!fields || !Array.isArray(fields) || fields.length === 0) {
|
||||
return Response.json({ error: "No fields provided" }, { status: 400 });
|
||||
}
|
||||
if (!fields || !Array.isArray(fields) || fields.length === 0) {
|
||||
return Response.json({ error: "No fields provided" }, { status: 400 });
|
||||
}
|
||||
|
||||
const created_by = 1;
|
||||
const exerciseCategory = "dnd";
|
||||
const created_by = 1;
|
||||
const exerciseCategory = "dnd";
|
||||
|
||||
// 1. Insert into exercises
|
||||
const exRes = await DB.pool(
|
||||
`INSERT INTO exercises (created_by, category)
|
||||
// 1. Insert into exercises
|
||||
const exRes = await DB.pool(
|
||||
`INSERT INTO exercises (created_by, category)
|
||||
VALUES ($1, $2)
|
||||
RETURNING id`,
|
||||
[created_by, exerciseCategory]
|
||||
);
|
||||
const exercise_id = exRes.rows[0].id;
|
||||
[created_by, exerciseCategory]
|
||||
);
|
||||
const exercise_id = exRes.rows[0].id;
|
||||
|
||||
// 2. Insert into dnd_exercises
|
||||
const dndRes = await DB.pool(
|
||||
`INSERT INTO dnd_exercises (created_by, exercise_id, title)
|
||||
// 2. Insert into dnd_exercises
|
||||
const dndRes = await DB.pool(
|
||||
`INSERT INTO dnd_exercises (created_by, exercise_id, title)
|
||||
VALUES ($1, $2, $3)
|
||||
RETURNING id`,
|
||||
[created_by, exercise_id, title]
|
||||
);
|
||||
const dnd_id = dndRes.rows[0].id;
|
||||
// Process fields
|
||||
for (const field of fields) {
|
||||
// Insert category
|
||||
const catRes = await DB.pool(
|
||||
`INSERT INTO dnd_categories (category, color)
|
||||
[created_by, exercise_id, title]
|
||||
);
|
||||
const dnd_id = dndRes.rows[0].id;
|
||||
// Process fields
|
||||
for (const field of fields) {
|
||||
// Insert category
|
||||
const catRes = await DB.pool(
|
||||
`INSERT INTO dnd_categories (category, color)
|
||||
VALUES ($1, $2)
|
||||
ON CONFLICT (category, color) DO NOTHING
|
||||
RETURNING id`,
|
||||
[field.category, field.color]
|
||||
);
|
||||
[field.category, field.color]
|
||||
);
|
||||
|
||||
const category_id =
|
||||
catRes.rows[0]?.id ||
|
||||
(
|
||||
await DB.pool(
|
||||
`SELECT id FROM dnd_categories WHERE category = $1 AND color = $2`,
|
||||
[field.category, field.color]
|
||||
)
|
||||
).rows[0].id;
|
||||
const category_id =
|
||||
catRes.rows[0]?.id ||
|
||||
(
|
||||
await DB.pool(
|
||||
`SELECT id FROM dnd_categories WHERE category = $1 AND color = $2`,
|
||||
[field.category, field.color]
|
||||
)
|
||||
).rows[0].id;
|
||||
|
||||
// Insert words
|
||||
const words = field.content.split(",").map((word) => word.trim());
|
||||
for (const word of words) {
|
||||
const wordRes = await DB.pool(
|
||||
`INSERT INTO draggable_words (word)
|
||||
// Insert words
|
||||
const words = field.content.split(",").map((word) => word.trim());
|
||||
for (const word of words) {
|
||||
const wordRes = await DB.pool(
|
||||
`INSERT INTO draggable_words (word)
|
||||
VALUES ($1)
|
||||
ON CONFLICT (word) DO UPDATE SET word = EXCLUDED.word
|
||||
RETURNING id`,
|
||||
[word]
|
||||
);
|
||||
[word]
|
||||
);
|
||||
|
||||
const word_id = wordRes.rows[0]?.id;
|
||||
const word_id = wordRes.rows[0]?.id;
|
||||
|
||||
// Insert mapping
|
||||
await DB.pool(
|
||||
`INSERT INTO word_category_mappings (word_id, category_id, exercise_id)
|
||||
// Insert mapping
|
||||
await DB.pool(
|
||||
`INSERT INTO word_category_mappings (word_id, category_id, exercise_id)
|
||||
VALUES ($1, $2, $3)`,
|
||||
[word_id, category_id, dnd_id]
|
||||
);
|
||||
[word_id, category_id, dnd_id]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Response.json({ success: true, exerciseId: exercise_id });
|
||||
} catch (err) {
|
||||
console.error("Error creating dragdrop exercise:", err);
|
||||
return Response.json(
|
||||
{ error: "Fehler beim Erstellen der Übung." },
|
||||
{ status: 500 }
|
||||
);
|
||||
return Response.json({ success: true, exerciseId: exercise_id });
|
||||
} catch (err) {
|
||||
console.error("Error creating dragdrop exercise:", err);
|
||||
return Response.json(
|
||||
{ error: "Fehler beim Erstellen der Übung." },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
requireAdmin: true,
|
||||
requireAuth: true,
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,87 +1,99 @@
|
||||
import { DB } from "@/backend/db";
|
||||
import { withAuth } from "@/backend/middleware/withAuth";
|
||||
|
||||
export async function POST(request) {
|
||||
try {
|
||||
const json = await request.json();
|
||||
const { title, description, content } = json;
|
||||
export const POST = withAuth(
|
||||
async (request) => {
|
||||
try {
|
||||
const json = await request.json();
|
||||
const { title, description, content } = json;
|
||||
|
||||
// Validation
|
||||
if (!title || !content || !Array.isArray(content) || content.length === 0) {
|
||||
return Response.json(
|
||||
{ error: "Titel und Inhalt erforderlich." },
|
||||
{ status: 400 }
|
||||
// Validation
|
||||
if (
|
||||
!title ||
|
||||
!content ||
|
||||
!Array.isArray(content) ||
|
||||
content.length === 0
|
||||
) {
|
||||
return Response.json(
|
||||
{ error: "Titel und Inhalt erforderlich." },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// Prevent duplicates
|
||||
const exists = await DB.pool(
|
||||
"SELECT id FROM multichoice_exercises WHERE title = $1",
|
||||
[title]
|
||||
);
|
||||
}
|
||||
if (exists.rows.length > 0) {
|
||||
return Response.json(
|
||||
{ error: "Eine Übung mit diesem Titel existiert bereits." },
|
||||
{ status: 409 }
|
||||
);
|
||||
}
|
||||
|
||||
// Prevent duplicates
|
||||
const exists = await DB.pool(
|
||||
"SELECT id FROM multichoice_exercises WHERE title = $1",
|
||||
[title]
|
||||
);
|
||||
if (exists.rows.length > 0) {
|
||||
return Response.json(
|
||||
{ error: "Eine Übung mit diesem Titel existiert bereits." },
|
||||
{ status: 409 }
|
||||
// Insert into exercises table
|
||||
const exResult = await DB.pool(
|
||||
`INSERT INTO exercises (category) VALUES ('multichoice') RETURNING id`
|
||||
);
|
||||
}
|
||||
const exercise_id = exResult.rows[0].id;
|
||||
|
||||
// Insert into exercises table
|
||||
const exResult = await DB.pool(
|
||||
`INSERT INTO exercises (category) VALUES ('multichoice') RETURNING id`
|
||||
);
|
||||
const exercise_id = exResult.rows[0].id;
|
||||
|
||||
// Insert into multichoice_exercises metadata table
|
||||
const mcRes = await DB.pool(
|
||||
`INSERT INTO multichoice_exercises (exercise_id, title, exercise_description)
|
||||
// Insert into multichoice_exercises metadata table
|
||||
const mcRes = await DB.pool(
|
||||
`INSERT INTO multichoice_exercises (exercise_id, title, exercise_description)
|
||||
VALUES ($1, $2, $3)
|
||||
RETURNING id`,
|
||||
[exercise_id, title, description ?? null]
|
||||
);
|
||||
const multichoice_id = mcRes.rows[0].id;
|
||||
[exercise_id, title, description ?? null]
|
||||
);
|
||||
const multichoice_id = mcRes.rows[0].id;
|
||||
|
||||
// Insert content rows
|
||||
let contentOrder = 1;
|
||||
for (const item of content) {
|
||||
const contentRes = await DB.pool(
|
||||
`INSERT INTO multichoice_content
|
||||
// Insert content rows
|
||||
let contentOrder = 1;
|
||||
for (const item of content) {
|
||||
const contentRes = await DB.pool(
|
||||
`INSERT INTO multichoice_content
|
||||
(multichoice_exercise_id, content_type, content_value, content_order, correct_answer)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING id`,
|
||||
[
|
||||
multichoice_id,
|
||||
item.type,
|
||||
item.value ?? "",
|
||||
contentOrder,
|
||||
item.type === "multichoice" ? item.correct : null,
|
||||
]
|
||||
);
|
||||
[
|
||||
multichoice_id,
|
||||
item.type,
|
||||
item.value ?? "",
|
||||
contentOrder,
|
||||
item.type === "multichoice" ? item.correct : null,
|
||||
]
|
||||
);
|
||||
|
||||
const content_id = contentRes.rows[0].id;
|
||||
const content_id = contentRes.rows[0].id;
|
||||
|
||||
// Insert options if it is a selection field
|
||||
if (item.type === "multichoice" && item.options?.length > 0) {
|
||||
for (const option of item.options) {
|
||||
await DB.pool(
|
||||
`INSERT INTO multichoice_options (multichoice_content_id, option_value)
|
||||
// Insert options if it is a selection field
|
||||
if (item.type === "multichoice" && item.options?.length > 0) {
|
||||
for (const option of item.options) {
|
||||
await DB.pool(
|
||||
`INSERT INTO multichoice_options (multichoice_content_id, option_value)
|
||||
VALUES ($1, $2)`,
|
||||
[content_id, option]
|
||||
);
|
||||
[content_id, option]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
contentOrder++;
|
||||
}
|
||||
|
||||
contentOrder++;
|
||||
return Response.json(
|
||||
{ success: true, exerciseId: exercise_id },
|
||||
{ status: 201 }
|
||||
);
|
||||
} catch (err) {
|
||||
console.error("Error saving multichoice exercise:", err);
|
||||
return Response.json(
|
||||
{ error: "Fehler beim Speichern der Übung." },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
|
||||
return Response.json(
|
||||
{ success: true, exerciseId: exercise_id },
|
||||
{ status: 201 }
|
||||
);
|
||||
} catch (err) {
|
||||
console.error("Error saving multichoice exercise:", err);
|
||||
return Response.json(
|
||||
{ error: "Fehler beim Speichern der Übung." },
|
||||
{ status: 500 }
|
||||
);
|
||||
},
|
||||
{
|
||||
requireAdmin: true,
|
||||
requireAuth: true,
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user