fix : le premier membre qui rejoint une classe devient admin

- joinClass : si aucun admin 'réel' (is_creator=0) n'existe, le nouveau membre est admin
- Seed : ne crée plus de membre admin — la première personne qui rejoint gère la classe
- Régression : 'Mathis' rejoignant TERMS2 devient admin au lieu d'élève
- v0.4.1
This commit is contained in:
Mathis 2026-10-04 21:38:47 +02:00
parent 0cc4b9841a
commit eb1f626d17
3 changed files with 25 additions and 17 deletions

View file

@ -79,6 +79,7 @@ export function joinClass(code: string, nickname: string): NewSession | null {
const klass: ClassInfo = { id: row.id, name: row.name, level: row.level, flashMessage: row.flash_message }
const token = newToken()
// Membre existant : on lui rouvre une session avec son rôle d'origine.
if (existing) {
db.prepare('UPDATE members SET token = ? WHERE id = ?').run(token, existing.id)
return {
@ -88,12 +89,23 @@ export function joinClass(code: string, nickname: string): NewSession | null {
}
}
// Premier vrai membre de la classe (aucun admin « réel » encore) : il devient admin.
// Un admin « réel » = role='admin' ET is_creator=0 (créé via promotion, pas par le seed).
const realAdminCount = db
.prepare<[number], { n: number }>(
`SELECT COUNT(*) AS n FROM members WHERE class_id = ? AND role = 'admin' AND is_creator = 0`,
)
.get(row.id)!
const isFirstRealMember = realAdminCount.n === 0
const role: Role = isFirstRealMember ? 'admin' : 'student'
const memberId = db
.prepare('INSERT INTO members (class_id, nickname, role, is_creator, token, created_at) VALUES (?, ?, ?, ?, ?, ?)')
.run(row.id, nickname, 'student', 0, token, nowIso()).lastInsertRowid as number
.run(row.id, nickname, role, 0, token, nowIso()).lastInsertRowid as number
return {
token,
member: { id: memberId, classId: row.id, nickname, role: 'student', isCreator: false },
member: { id: memberId, classId: row.id, nickname, role, isCreator: false },
klass,
}
}

View file

@ -28,7 +28,6 @@ if (existing.n > 0) {
const CLASS_NAME = 'Terminale S2'
const LEVEL = 'Lycée'
const ADMIN_NICK = 'Thomas S.'
const CLASS_CODE = 'TERMS2'
const DAY_MS = 86_400_000
@ -89,15 +88,12 @@ const seed = db.transaction(() => {
const classId = db.prepare<[string], { id: number }>('SELECT id FROM classes WHERE code = ?')
.get(CLASS_CODE)!.id
const adminToken = newToken()
const adminId = db
.prepare('INSERT INTO members (class_id, nickname, role, token, created_at) VALUES (?, ?, ?, ?, ?)')
.run(classId, ADMIN_NICK, 'admin', adminToken, nowIso()).lastInsertRowid as number
// Quelques élèves : ils donneront du volume aux votes du radar plus tard.
// Pas de membre admin créé par le seed : la première personne qui rejoint
// la classe via l'app devient automatiquement admin (cf. joinClass).
// Quelques élèves fictifs pour donner du volume aux votes du radar plus tard.
for (const nick of ['Léa M.', 'Karim B.', 'Chloé D.', 'Inès R.', 'Lucas P.', 'Mehdi A.']) {
db.prepare('INSERT INTO members (class_id, nickname, role, token, created_at) VALUES (?, ?, ?, ?, ?)')
.run(classId, nick, 'student', newToken(), nowIso())
db.prepare('INSERT INTO members (class_id, nickname, role, is_creator, token, created_at) VALUES (?, ?, ?, ?, ?, ?)')
.run(classId, nick, 'student', 0, newToken(), nowIso())
}
const insert = db.prepare(
@ -113,18 +109,18 @@ const seed = db.transaction(() => {
insert.run(
classId, e.subject, e.teacher, e.room, e.chapter,
date.toISOString(), e.durationMin, e.weight, e.kind, e.note,
adminId, now, now,
null, now, now,
)
}
return { classId, adminToken }
return { classId }
})
const { adminToken } = seed()
const { classId } = seed()
console.log('Seed terminé.')
console.log(` Classe : ${CLASS_NAME} (${LEVEL})`)
console.log(` Code invite : ${CLASS_CODE}`)
console.log(` Admin : ${ADMIN_NICK}`)
console.log(` Classe ID : ${classId}`)
console.log(` Évaluations : ${exams.length}`)
console.log(` Jeton admin : ${adminToken}`)
console.log(' → La première personne qui rejoint avec ce code devient admin.')