diff --git a/server/api/admin.js b/server/api/admin.js index 3b5fb98..cb7044f 100644 --- a/server/api/admin.js +++ b/server/api/admin.js @@ -6,6 +6,11 @@ export function registerAdmin(app) { app.post("/api/admin/timetable", createTimetable); app.put("/api/admin/timetable", editTimetable); app.delete("/api/admin/timetable", deleteTimetable); + + app.get("/api/admin/key", listKeys); + app.post("/api/admin/key", createKey); + app.put("/api/admin/key", editKey); + app.delete("/api/admin/key", deleteKey); } function sendMissingArguments(res) { @@ -76,3 +81,72 @@ async function deleteTimetable(req, res) { res.status(500).send(e); } } + +async function listKeys(_, res) { + res.send(await prisma.key.findMany()); +} + +async function createKey(req, res) { + let data = req.body; + if (!data.key) { + sendMissingArguments(res); + return; + } + const existingKey = await prisma.key.findUnique({ + where: { + key: data.key, + }, + }); + if (existingKey) { + res.status(400).send({ + success: false, + error: "key_already_exists", + }); + return; + } + + const key = await prisma.key.create({ + data: { + key: data.key, + permissions: data.permissions || [], + validUntil: data.validUntil, + notes: data.notes, + }, + }); + res.status(201).send(key); +} + +async function editKey(req, res) { + if (!req.query.id) { + sendMissingArguments(res); + return; + } + try { + const timetable = await prisma.key.update({ + where: { + key: req.query.id, + }, + data: req.body, + }); + res.status(201).send(timetable); + } catch (e) { + res.status(500).send(e); + } +} + +async function deleteKey(req, res) { + if (!req.query.id) { + sendMissingArguments(res); + return; + } + try { + await prisma.key.delete({ + where: { + key: req.query.id, + }, + }); + res.status(200).send(); + } catch (e) { + res.status(500).send(e); + } +} diff --git a/src/components/settings/expand-section.vue b/src/components/settings/expand-section.vue index a6a9d8a..9e8de26 100644 --- a/src/components/settings/expand-section.vue +++ b/src/components/settings/expand-section.vue @@ -24,5 +24,6 @@ defineProps(["title"]); user-select: none; font-size: 19px; margin: 5px 0px; + cursor: pointer; } diff --git a/src/components/settings/key-card.vue b/src/components/settings/key-card.vue index 9e17ed5..078ca54 100644 --- a/src/components/settings/key-card.vue +++ b/src/components/settings/key-card.vue @@ -1,4 +1,5 @@ {{ keyData.key }} + {{ keyData.notes }} + @@ -49,6 +52,12 @@ defineEmits(["delete"]); padding: 15px 10px 0px 10px; } +.notes { + padding: 0px 10px; + font-size: 14px; + opacity: 0.7; +} + .permissions { display: flex; flex-direction: row; diff --git a/src/views/settings/AdminSettings.vue b/src/views/settings/AdminSettings.vue index 95fc4c5..94fbfca 100644 --- a/src/views/settings/AdminSettings.vue +++ b/src/views/settings/AdminSettings.vue @@ -1,71 +1,112 @@ @@ -80,15 +121,27 @@ fetchTimetables(); Trusted - + Create Timetable - + Save Timetable - + Cancel edit @@ -98,12 +151,12 @@ fetchTimetables(); :key="timetable" :timetable="timetable" :editable="true" - :selected="timetable.id == editId" + :selected="timetable.id == timetableEditId" :admin="true" - @delete="deleteTimetable(timetable.id)" + @delete="deleteObject('timetable', timetable.id)" @edit=" () => { - editId = timetable.id; + timetableEditId = timetable.id; timetableName = timetable.title; timetableClass = timetable.class; timetableSource = timetable.source; @@ -113,6 +166,63 @@ fetchTimetables(); /> + + + + + + + + + + + + Create Key + + + + Save Key + + + + Cancel edit + + + { + if ( + key.permissions.includes('admin') && + !confirm('Are you sure you want to delete an admin key?') + ) { + return; + } + deleteObject('key', key.key); + } + " + @edit=" + () => { + keyEditId = key.key; + keyId = key.key; + keyPermissions = key.permissions.join(','); + keyNotes = key.notes; + } + " + /> + + diff --git a/src/views/settings/KeySettings.vue b/src/views/settings/KeySettings.vue index 3f55440..eb9b650 100644 --- a/src/views/settings/KeySettings.vue +++ b/src/views/settings/KeySettings.vue @@ -77,6 +77,7 @@ async function revokeKey(key) { v-for="key in sessionInfo.appliedKeys" :key="key" :keyData="key" + :edit="false" @delete="() => revokeKey(key.key)" />
{{ keyData.key }}
{{ keyData.notes }}