Flexibele kluissoorten: soorten in de database, beheer op de website

- Tabellen vault_categories en vault_category_fields (db/21), startrijen handmatig (db/handmatig/21b)
- VaultCategoryService met regels voor zichtbaarheid, gebruik en eigen velden
- Beheer > Kluissoorten (/beheer/soorten) met gebruikstellers; soort in gebruik niet te verwijderen
- Kluis en Nalatenschap (web en app) tonen soorten en eigen velden uit de database
- Socketprotocol: vault.categories; GRANTs voor mijnbesluit_app in db/02
- db/20 herhaalbaar gemaakt
- App versie 1.1 (versiecode 3)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014MGLqt1uKfNARQHut9ifcx
This commit is contained in:
jf
2026-10-20 08:15:40 +00:00
co-authored by Claude Sonnet 5.5
parent a3a0bcfc05
commit af13d0e533
36 changed files with 2540 additions and 94 deletions
+2
View File
@@ -53,6 +53,8 @@ GRANT SELECT, INSERT, UPDATE, DELETE ON `mijnbesluit`.`adverteerders` TO 'm
GRANT SELECT, INSERT, UPDATE, DELETE ON `mijnbesluit`.`campagnes` TO 'mijnbesluit_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `mijnbesluit`.`campagne_uren` TO 'mijnbesluit_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `mijnbesluit`.`sessies` TO 'mijnbesluit_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `mijnbesluit`.`vault_categories` TO 'mijnbesluit_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON `mijnbesluit`.`vault_category_fields` TO 'mijnbesluit_app'@'localhost';
-- Het logboek mag er alleen bij komen en uit gelezen worden, niet uit verdwijnen.
GRANT SELECT, INSERT ON `mijnbesluit`.`audit_log` TO 'mijnbesluit_app'@'localhost';
+30 -3
View File
@@ -3,6 +3,33 @@
-- Wie een bezorgd bericht "verwijdert" haalt het alleen bij zichzelf weg; de ander heeft er nog
-- steeds recht op. Vandaar twee vlaggen in plaats van één verwijderdatum: de afzender en de
-- ontvanger ruimen onafhankelijk van elkaar op. De rij zelf blijft altijd bestaan.
ALTER TABLE `messages`
ADD COLUMN `hidden_by_sender` TINYINT(1) NOT NULL DEFAULT 0 AFTER `read_at`,
ADD COLUMN `hidden_by_recipient` TINYINT(1) NOT NULL DEFAULT 0 AFTER `hidden_by_sender`;
--
-- Draaien met:
-- mysql -u root -p mijnbesluit < db\20_bericht_verbergen.sql
--
-- Opnieuw draaien mag: er gebeurt dan niets. (De uitroller draait alle scripts elke keer; een
-- script dat alleen "ADD COLUMN" zegt, loopt de tweede keer vast en houdt de rest tegen.)
USE `mijnbesluit`;
-- ---------------------------------------------------------------- hidden_by_sender
SET @bestaat := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'messages' AND COLUMN_NAME = 'hidden_by_sender');
SET @sql := IF(@bestaat = 0,
'ALTER TABLE `messages` ADD COLUMN `hidden_by_sender` TINYINT(1) NOT NULL DEFAULT 0 AFTER `read_at`',
'SELECT "hidden_by_sender bestaat al" AS melding');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- ---------------------------------------------------------------- hidden_by_recipient
SET @bestaat := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'messages' AND COLUMN_NAME = 'hidden_by_recipient');
SET @sql := IF(@bestaat = 0,
'ALTER TABLE `messages` ADD COLUMN `hidden_by_recipient` TINYINT(1) NOT NULL DEFAULT 0 AFTER `hidden_by_sender`',
'SELECT "hidden_by_recipient bestaat al" AS melding');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SELECT 'Klaar. Een bezorgd bericht is vanaf nu uit je eigen lijst te verwijderen.' AS melding;
+76
View File
@@ -0,0 +1,76 @@
-- MijnBesluit - kluissoorten uit de database in plaats van uit de code
--
-- Tot nu toe stond de lijst "Wachtwoord, Polis, Uitvaartwens, ..." vast in de code, met per soort
-- een eigen invulscherm. Elke nieuwe soort (denk aan "Dementie" of "Niet reanimeren") vroeg dus
-- een nieuwe versie van de app in de Play Store en de App Store. Nu staan de soorten hier, en de
-- velden van een nieuwe soort ook: de beheerder onderhoudt ze op de website (/beheer/soorten) en
-- de app tekent het formulier naar wat de server beschrijft.
--
-- vault_categories de soorten. De elf ingebouwde en "Overig" (nummer 99) krijgen hier
-- hun startrij; nieuwe soorten beginnen bij nummer 100.
-- vault_category_fields de velden van een nieuwe soort. Ingebouwde soorten hebben hier geen
-- rijen: hun invulscherm zit nog in de app zelf.
--
-- Regels die de server afdwingt (niet de database):
-- * Een soort waar kluisitems mee zijn gemaakt kan niet worden verwijderd, alleen op niet-actief
-- gezet. Niet-actief verdwijnt uit de keuzelijst van wie er nog nooit een item mee maakte;
-- wie dat wel deed, blijft de soort zien.
-- * Nieuwe items kunnen alleen in een actieve soort, of in een soort waar de eigenaar al een
-- item van heeft.
--
-- vault_items.category blijft een gewoon getal; er komt bewust geen foreign key bij, zodat
-- bestaande gegevens en oudere apps niet in de weg zitten.
--
-- Draaien met:
-- mysql -u root -p mijnbesluit < db\21_kluissoorten.sql
--
-- Opnieuw draaien mag: er gebeurt dan niets.
--
-- Na dit script, eenmalig als root:
-- mysql -u root -p < db\02_applicatiegebruiker.sql (rechten op de nieuwe tabellen)
-- mysql -u root -p mijnbesluit < db\handmatig\21b_kluissoorten_startrijen.sql (de startrijen)
USE `mijnbesluit`;
-- ---------------------------------------------------------------- vault_categories
CREATE TABLE IF NOT EXISTS `vault_categories` (
`id` INT NOT NULL AUTO_INCREMENT,
`naam` VARCHAR(80) NOT NULL,
`uitleg` VARCHAR(500) NULL, -- verschijnt onder de keuzelijst in de app
`actief` TINYINT(1) NOT NULL DEFAULT 1,
`volgorde` INT NOT NULL DEFAULT 1000,
`bespreken_met` TINYINT(1) NOT NULL DEFAULT 0, -- mag de eigenaar een beheerder kiezen om vooraf mee te bespreken?
`ingebouwd` TINYINT(1) NOT NULL DEFAULT 0, -- 1 = invulscherm zit in de app; velden hier niet te wijzigen
`aangemaakt_op` DATETIME(3) NOT NULL,
`gewijzigd_op` DATETIME(3) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ux_vault_categories_naam` (`naam`)
) ENGINE=InnoDB AUTO_INCREMENT=100;
-- ---------------------------------------------------------------- vault_category_fields
CREATE TABLE IF NOT EXISTS `vault_category_fields` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`category_id` INT NOT NULL,
`sleutel` VARCHAR(40) NOT NULL, -- vaste naam in de versleutelde inhoud; wijzigt nooit
`label` VARCHAR(100) NOT NULL,
`soort` VARCHAR(10) NOT NULL DEFAULT 'tekst', -- tekst | lang | datum | keuze | uitleg
`opties` VARCHAR(1000) NULL, -- bij 'keuze': één optie per regel
`hulptekst` VARCHAR(300) NULL,
`verplicht` TINYINT(1) NOT NULL DEFAULT 0,
`actief` TINYINT(1) NOT NULL DEFAULT 1,
`volgorde` INT NOT NULL DEFAULT 1000,
PRIMARY KEY (`id`),
UNIQUE KEY `ux_vault_category_fields_sleutel` (`category_id`, `sleutel`),
CONSTRAINT `fk_vcf_category` FOREIGN KEY (`category_id`) REFERENCES `vault_categories` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB;
-- ---------------------------------------------------------------- startrijen
-- De startrijen (de elf ingebouwde soorten en Overig) staan NIET hier maar in
-- handmatig\21b_kluissoorten_startrijen.sql.
--
-- Waarom: dit script wordt ook door de uitrolagent gedraaid, met een beperkt databaseaccount dat
-- tabellen mag maken maar er geen gegevens in mag zetten. Een INSERT hier laat de hele uitrol
-- struikelen (ERROR 1142: INSERT command denied). Gegevens neerzetten is inrichten, en dat doet een
-- mens één keer als root, net als de rechten in 02_applicatiegebruiker.sql.
SELECT 'Klaar. De tabellen voor kluissoorten staan klaar. Vergeet handmatig\\21b_kluissoorten_startrijen.sql en 02_applicatiegebruiker.sql niet (als root).' AS melding;
@@ -0,0 +1,36 @@
-- MijnBesluit - startrijen voor de kluissoorten (eenmalig, als root)
--
-- Hoort bij 21_kluissoorten.sql, dat de tabellen maakt. Dit script zet de twaalf soorten erin die
-- er altijd al waren: de elf ingebouwde en "Overig" (nummer 99). De nummers zijn die van
-- VaultCategory in de code en van vault_items.category; wijzig ze nooit.
--
-- Dit staat in de submap handmatig\ en niet in db\ zelf: de uitrolagent draait alles in db\, met een
-- beperkt account dat geen gegevens mag invoegen. Zie de kop van 21_kluissoorten.sql.
--
-- Draaien met (in cmd, NIET in PowerShell):
-- mysql -u root -p mijnbesluit < db\handmatig\21b_kluissoorten_startrijen.sql
--
-- Opnieuw draaien mag: bestaande soorten blijven zoals ze zijn (ook als je er een hernoemd of
-- op niet-actief gezet hebt).
USE `mijnbesluit`;
-- De volgorde is die van de keuzelijst in de app. Alleen uitvaartwens en donorcodicil kennen
-- "Bespreken met", precies zoals voorheen.
INSERT IGNORE INTO `vault_categories`
(`id`, `naam`, `actief`, `volgorde`, `bespreken_met`, `ingebouwd`, `aangemaakt_op`, `gewijzigd_op`) VALUES
( 3, 'Wachtwoord', 1, 10, 0, 1, UTC_TIMESTAMP(3), UTC_TIMESTAMP(3)),
( 8, 'Sociale media', 1, 20, 0, 1, UTC_TIMESTAMP(3), UTC_TIMESTAMP(3)),
( 4, 'Apparaat', 1, 30, 0, 1, UTC_TIMESTAMP(3), UTC_TIMESTAMP(3)),
( 5, 'Pincode', 1, 40, 0, 1, UTC_TIMESTAMP(3), UTC_TIMESTAMP(3)),
( 2, 'Polis', 1, 50, 0, 1, UTC_TIMESTAMP(3), UTC_TIMESTAMP(3)),
( 1, 'Uitvaartwens', 1, 60, 1, 1, UTC_TIMESTAMP(3), UTC_TIMESTAMP(3)),
( 9, 'Donorcodicil', 1, 70, 1, 1, UTC_TIMESTAMP(3), UTC_TIMESTAMP(3)),
(10, 'Rijbewijs', 1, 80, 0, 1, UTC_TIMESTAMP(3), UTC_TIMESTAMP(3)),
(11, 'Paspoort', 1, 90, 0, 1, UTC_TIMESTAMP(3), UTC_TIMESTAMP(3)),
( 6, 'Document', 1, 100, 0, 1, UTC_TIMESTAMP(3), UTC_TIMESTAMP(3)),
( 7, 'Notitie', 1, 110, 0, 1, UTC_TIMESTAMP(3), UTC_TIMESTAMP(3)),
(99, 'Overig', 1, 120, 0, 1, UTC_TIMESTAMP(3), UTC_TIMESTAMP(3));
-- Controle: dit hoort twaalf te zijn (of meer, als de beheerder er al een bij zette).
SELECT COUNT(*) AS aantal_soorten FROM `vault_categories`;