Voeg 28 herkenbare kleurplaten en creatieve niveaus toe (v0.4.66-beta) #4
4 changed files with 37 additions and 8 deletions
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
0.3.99-beta
|
||||
0.4.0-beta
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"use strict";
|
||||
/* version — shown until /api/version resolves (or if the fetch fails, e.g. offline).
|
||||
Kept in sync by hand with the VERSION file at the repo root on every release. */
|
||||
const VERSION = "0.3.99-beta";
|
||||
const VERSION = "0.4.0-beta";
|
||||
(function(){
|
||||
const tag = document.getElementById("verTag");
|
||||
tag.textContent = "v"+VERSION;
|
||||
|
|
|
|||
20
src/api.js
20
src/api.js
|
|
@ -375,12 +375,20 @@ export default async function api(app) {
|
|||
});
|
||||
app.delete('/admin/classes/:id', async (req, reply) => {
|
||||
need(req, reply, PERMISSIONS['classes.manage']);
|
||||
const r = await pool.query('SELECT * FROM classes WHERE id = $1', [req.params.id]);
|
||||
if (!r.rows[0]) return fail(reply, 404, 'klas onbekend');
|
||||
if (!req.user.allRoles.includes('super') && Number(r.rows[0].school_id) !== Number(req.user.school_id))
|
||||
return fail(reply, 403, 'geen rechten');
|
||||
await pool.query('DELETE FROM classes WHERE id = $1', [req.params.id]);
|
||||
return { ok: true };
|
||||
// Zelfde reden als bij het verwijderen van een gebruiker: alles in één
|
||||
// try/catch, zodat een mislukking de echte oorzaak teruggeeft i.p.v. terug
|
||||
// te vallen op de kale "serverfout" van de generieke handler.
|
||||
try {
|
||||
const r = await pool.query('SELECT * FROM classes WHERE id = $1', [req.params.id]);
|
||||
if (!r.rows[0]) return fail(reply, 404, 'klas onbekend');
|
||||
if (!req.user.allRoles.includes('super') && Number(r.rows[0].school_id) !== Number(req.user.school_id))
|
||||
return fail(reply, 403, 'geen rechten');
|
||||
await pool.query('DELETE FROM classes WHERE id = $1', [req.params.id]);
|
||||
return { ok: true };
|
||||
} catch (e) {
|
||||
req.log.error({ err: e }, 'verwijderen klas mislukt');
|
||||
return fail(reply, 409, `verwijderen mislukt: ${e.detail || e.message}`);
|
||||
}
|
||||
});
|
||||
// groepsleiding aan klas koppelen/loskoppelen
|
||||
// Elke staf-rol (groepsleiding, schoolbeheerder, systeemmanager) kan aan
|
||||
|
|
|
|||
|
|
@ -197,6 +197,27 @@ test('systeemmanager verplaatst een klas naar een andere school; losmaken kan ni
|
|||
await app.close(); await app2.close(); await app3.close();
|
||||
});
|
||||
|
||||
test('klas verwijderen werkt en meldt bij een fout de echte reden i.p.v. kale serverfout', async () => {
|
||||
const { app, calls } = await makeApp(superUser, null);
|
||||
const res = await app.inject({ method: 'DELETE', url: '/api/admin/classes/100', cookies });
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
assert.ok(calls.some((c) => c.sql === 'DELETE FROM classes WHERE id = $1'));
|
||||
|
||||
const { app: app2 } = await makeApp(superUser, null);
|
||||
const pool2 = app2.pg;
|
||||
const orig = pool2.query.bind(pool2);
|
||||
pool2.query = async (sql, params) => {
|
||||
if (sql === 'DELETE FROM classes WHERE id = $1') {
|
||||
const e = new Error('boom'); e.detail = 'Key is still referenced from table "iets".'; throw e;
|
||||
}
|
||||
return orig(sql, params);
|
||||
};
|
||||
const res2 = await app2.inject({ method: 'DELETE', url: '/api/admin/classes/100', cookies });
|
||||
assert.equal(res2.statusCode, 409, res2.body);
|
||||
assert.match(res2.json().error, /still referenced/);
|
||||
await app.close(); await app2.close();
|
||||
});
|
||||
|
||||
test('gebruiker verwijderen ruimt eerst alle afhankelijke rijen op (geen serverfout)', async () => {
|
||||
const { app, calls } = await makeApp(superUser, { id: 9, role: 'teacher', school_id: 2, username: 'juf' });
|
||||
const res = await app.inject({ method: 'DELETE', url: '/api/admin/users/9', cookies });
|
||||
|
|
|
|||
Loading…
Reference in a new issue