Voeg 28 herkenbare kleurplaten en creatieve niveaus toe (v0.4.66-beta) #4
5 changed files with 32 additions and 7 deletions
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
||||||
0.3.55-beta
|
0.3.56-beta
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,8 @@
|
||||||
+ (names.length ? ` · ${names.join(", ")}` : "")
|
+ (names.length ? ` · ${names.join(", ")}` : "")
|
||||||
+ (u.pending ? ` · ${T("amPending")}` : "")));
|
+ (u.pending ? ` · ${T("amPending")}` : "")));
|
||||||
}
|
}
|
||||||
if(u.role!=="pupil" && can("users.role.change") && u.id!==currentUser.id){
|
const isStaff = ["teacher","admin","super"].includes(u.role);
|
||||||
|
if(isStaff && can("users.role.change") && u.id!==currentUser.id){
|
||||||
/* één functie per gebruiker: alleen de hoofdrol is te wijzigen (super);
|
/* één functie per gebruiker: alleen de hoofdrol is te wijzigen (super);
|
||||||
het aparte extra-functies-systeem is uit de UI gehaald */
|
het aparte extra-functies-systeem is uit de UI gehaald */
|
||||||
const rs = h("select","am-sel");
|
const rs = h("select","am-sel");
|
||||||
|
|
@ -221,7 +222,7 @@
|
||||||
/* elke staf-rol eenvoudig aan klassen koppelen (groepsleiding,
|
/* elke staf-rol eenvoudig aan klassen koppelen (groepsleiding,
|
||||||
schoolbeheerder én systeemmanager): huidige klassen als chips met ✕,
|
schoolbeheerder én systeemmanager): huidige klassen als chips met ✕,
|
||||||
en een select om een klas toe te voegen */
|
en een select om een klas toe te voegen */
|
||||||
if(u.role!=="pupil" && can("classes.manage") && CLASSES.length){
|
if(isStaff && can("classes.manage") && CLASSES.length){
|
||||||
const wrap = h("div","am-classes");
|
const wrap = h("div","am-classes");
|
||||||
(u.classIds||[]).forEach(cid=>{
|
(u.classIds||[]).forEach(cid=>{
|
||||||
const c = CLASSES.find(x=>Number(x.id)===Number(cid));
|
const c = CLASSES.find(x=>Number(x.id)===Number(cid));
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
/* version — shown until /api/version resolves (or if the fetch fails, e.g. offline).
|
/* 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. */
|
Kept in sync by hand with the VERSION file at the repo root on every release. */
|
||||||
const VERSION = "0.3.55-beta";
|
const VERSION = "0.3.56-beta";
|
||||||
(function(){
|
(function(){
|
||||||
const tag = document.getElementById("verTag");
|
const tag = document.getElementById("verTag");
|
||||||
tag.textContent = "v"+VERSION;
|
tag.textContent = "v"+VERSION;
|
||||||
|
|
@ -554,7 +554,9 @@ let DATA_REV = 0;
|
||||||
let saveConflict = false;
|
let saveConflict = false;
|
||||||
let saveInFlight = false;
|
let saveInFlight = false;
|
||||||
function canPersist(){
|
function canPersist(){
|
||||||
return !!currentUser && currentUser.role !== "pupil";
|
/* leerlingen en ouders slaan geen eigen borden-data op; het ouderportaal
|
||||||
|
werkt straks met gekoppelde kind-accounts i.p.v. een eigen blob */
|
||||||
|
return !!currentUser && currentUser.role !== "pupil" && currentUser.role !== "parent";
|
||||||
}
|
}
|
||||||
/* welke secties er sinds de laatste geslaagde save zijn gewijzigd; een save
|
/* welke secties er sinds de laatste geslaagde save zijn gewijzigd; een save
|
||||||
verstuurt alleen die secties i.p.v. altijd de complete blob (die MB's kan
|
verstuurt alleen die secties i.p.v. altijd de complete blob (die MB's kan
|
||||||
|
|
|
||||||
|
|
@ -344,7 +344,7 @@ export default async function api(app) {
|
||||||
if (!c || !u) return fail(reply, 404, 'klas of gebruiker onbekend');
|
if (!c || !u) return fail(reply, 404, 'klas of gebruiker onbekend');
|
||||||
if (!req.user.allRoles.includes('super') && Number(c.school_id) !== Number(req.user.school_id))
|
if (!req.user.allRoles.includes('super') && Number(c.school_id) !== Number(req.user.school_id))
|
||||||
return fail(reply, 403, 'geen rechten');
|
return fail(reply, 403, 'geen rechten');
|
||||||
if (u.role === 'pupil') return fail(reply, 400, 'leerlingen horen al bij één klas');
|
if (!['teacher', 'admin', 'super'].includes(u.role)) return fail(reply, 400, 'alleen staf kan aan een klas gekoppeld worden');
|
||||||
if (u.role !== 'super' && Number(c.school_id) !== Number(u.school_id))
|
if (u.role !== 'super' && Number(c.school_id) !== Number(u.school_id))
|
||||||
return fail(reply, 400, 'klas en gebruiker moeten bij dezelfde school horen');
|
return fail(reply, 400, 'klas en gebruiker moeten bij dezelfde school horen');
|
||||||
if (remove) await pool.query('DELETE FROM class_teachers WHERE class_id = $1 AND user_id = $2', [c.id, u.id]);
|
if (remove) await pool.query('DELETE FROM class_teachers WHERE class_id = $1 AND user_id = $2', [c.id, u.id]);
|
||||||
|
|
@ -526,7 +526,11 @@ export default async function api(app) {
|
||||||
await pool.query('DELETE FROM sessions WHERE user_id = $1', [u.id]);
|
await pool.query('DELETE FROM sessions WHERE user_id = $1', [u.id]);
|
||||||
return { ok: true, linkCode: code };
|
return { ok: true, linkCode: code };
|
||||||
}
|
}
|
||||||
if (b.role && can(req.user.allRoles, 'users.role.change') && ['super', 'admin', 'teacher'].includes(b.role) && u.role !== 'pupil')
|
// rolwijziging alleen tussen staf-rollen onderling: leerlingen blijven
|
||||||
|
// leerling en ouder-accounts kunnen nooit naar een beheerrol promoveren
|
||||||
|
if (b.role && can(req.user.allRoles, 'users.role.change')
|
||||||
|
&& ['super', 'admin', 'teacher'].includes(b.role)
|
||||||
|
&& ['super', 'admin', 'teacher'].includes(u.role))
|
||||||
await pool.query('UPDATE users SET role = $1, school_id = $2 WHERE id = $3',
|
await pool.query('UPDATE users SET role = $1, school_id = $2 WHERE id = $3',
|
||||||
[b.role, b.role === 'super' ? null : u.school_id, u.id]);
|
[b.role, b.role === 'super' ? null : u.school_id, u.id]);
|
||||||
// extra functies naast de hoofdrol (bv. een teacher die ook admin-rechten krijgt) -
|
// extra functies naast de hoofdrol (bv. een teacher die ook admin-rechten krijgt) -
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,24 @@ test('schoolbeheerder en systeemmanager kunnen aan een klas gekoppeld worden', a
|
||||||
await app4.close();
|
await app4.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('ouder-achtige rol krijgt geen promotie en geen klaskoppeling', async () => {
|
||||||
|
// rolwijziging: alleen staf → staf; een parent-account mag nooit promoveren
|
||||||
|
const { app, calls } = await makeApp(superUser, { id: 7, role: 'parent', school_id: null });
|
||||||
|
const res = await app.inject({ method: 'PATCH', url: '/api/admin/users/7', cookies,
|
||||||
|
payload: { role: 'admin' } });
|
||||||
|
assert.equal(res.statusCode, 200, res.body);
|
||||||
|
assert.ok(!calls.some((c) => c.sql.startsWith('UPDATE users SET role')),
|
||||||
|
'rolwijziging mag voor een ouder-account niet uitgevoerd worden');
|
||||||
|
await app.close();
|
||||||
|
// klaskoppeling: parent weigeren, net als pupil
|
||||||
|
const { app: app2, calls: calls2 } = await makeApp(superUser, { id: 7, role: 'parent', school_id: null });
|
||||||
|
const res2 = await app2.inject({ method: 'POST', url: '/api/admin/classes/100/teachers', cookies,
|
||||||
|
payload: { userId: 7 } });
|
||||||
|
assert.equal(res2.statusCode, 400);
|
||||||
|
assert.ok(!calls2.some((c) => c.sql.includes('INSERT INTO class_teachers')));
|
||||||
|
await app2.close();
|
||||||
|
});
|
||||||
|
|
||||||
test('hernoemen weigert een lege of te lange naam', async () => {
|
test('hernoemen weigert een lege of te lange naam', async () => {
|
||||||
const { app } = await makeApp(superUser);
|
const { app } = await makeApp(superUser);
|
||||||
const res = await app.inject({ method: 'PATCH', url: '/api/admin/schools/5', cookies,
|
const res = await app.inject({ method: 'PATCH', url: '/api/admin/schools/5', cookies,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue