Eerste commit
This commit is contained in:
@@ -0,0 +1,368 @@
|
||||
-- ============================================================================
|
||||
-- MijnBesluit - databaseschema voor MariaDB 10.6 of nieuwer
|
||||
--
|
||||
-- Aanmaken (in cmd, NIET in PowerShell - die kent "<" niet):
|
||||
-- mysql -u root -p < 01_schema.sql
|
||||
-- In PowerShell of HeidiSQL: zie docs/Website-testen.md.
|
||||
--
|
||||
-- Het script mag meerdere keren gedraaid worden; bestaande tabellen blijven ongemoeid.
|
||||
--
|
||||
-- De schemanaam staat hieronder één keer. Wil je een bestaande database
|
||||
-- gebruiken, vervang dan `mijnbesluit` overal (of laat CREATE DATABASE weg
|
||||
-- en zet er een USE <jouw naam>; voor in de plaats).
|
||||
--
|
||||
-- Opzet:
|
||||
-- * Alles utf8mb4 en InnoDB, zodat namen met accenten en emoji goed gaan.
|
||||
-- * Geheimen staan als VARBINARY in de tabel: versleuteld met AES-256-GCM,
|
||||
-- nooit leesbaar. Zie docs/Beveiliging.md voor hoe de sleutels lopen.
|
||||
-- * Datums worden in UTC bewaard (DATETIME, geen TIMESTAMP), zodat zomertijd
|
||||
-- nooit een bezorgmoment kan verschuiven.
|
||||
-- ============================================================================
|
||||
|
||||
CREATE DATABASE IF NOT EXISTS `mijnbesluit`
|
||||
DEFAULT CHARACTER SET utf8mb4
|
||||
DEFAULT COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
USE `mijnbesluit`;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- ---------------------------------------------------------------- personen ---
|
||||
-- Een profiel. Kan bestaan zonder account: dan is het aangemaakt door iemand
|
||||
-- anders en wacht het op een uitnodiging.
|
||||
CREATE TABLE IF NOT EXISTS `persons` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`first_name` VARCHAR(80) NOT NULL DEFAULT '',
|
||||
`last_name` VARCHAR(80) NOT NULL DEFAULT '',
|
||||
`nickname` VARCHAR(80) NULL,
|
||||
`email` VARCHAR(255) NULL,
|
||||
`mobile_number` VARCHAR(50) NULL,
|
||||
`birth_date` DATE NULL,
|
||||
`date_of_death` DATE NULL,
|
||||
|
||||
-- Wie het profiel aanmaakte (historie) en wie het nu beheert.
|
||||
`created_by_user_id` BIGINT NULL,
|
||||
`managed_by_user_id` BIGINT NULL,
|
||||
|
||||
-- Zodra dit gevuld is, is het profiel van de persoon zelf.
|
||||
`claimed_by_user_id` BIGINT NULL,
|
||||
`claimed_at` DATETIME(3) NULL,
|
||||
|
||||
-- Aantal meldingen dat nodig is om overlijden te bevestigen, en hoeveel dagen
|
||||
-- de betrokkene daarna nog heeft om bezwaar te maken.
|
||||
`required_death_declarations` INT NOT NULL DEFAULT 3,
|
||||
`death_objection_days` INT NOT NULL DEFAULT 14,
|
||||
`death_confirmed_at` DATETIME(3) NULL,
|
||||
`death_objected_at` DATETIME(3) NULL,
|
||||
|
||||
-- Wie heeft gezegd dat deze aantekening niet over hem gaat. Zie db/17_aantekening_afgewezen.sql:
|
||||
-- dan komt die vraag niet bij elke volgende keer opnieuw.
|
||||
`link_declined_by_user_id` BIGINT NULL,
|
||||
`link_declined_at` DATETIME(3) NULL,
|
||||
|
||||
`created_at` DATETIME(3) NOT NULL,
|
||||
`updated_at` DATETIME(3) NOT NULL,
|
||||
|
||||
PRIMARY KEY (`id`),
|
||||
-- Met opzet NIET uniek. Twee mensen mogen allebei hun eigen aantekening over dezelfde
|
||||
-- persoon hebben; ze worden pas één zodra die persoon zelf beide uitnodigingen aanneemt.
|
||||
-- Zie docs/Identiteit.md en db/15_adres_niet_uniek.sql. Bij `users.email` is uniek juist
|
||||
-- wél goed: dat is een account.
|
||||
KEY `ix_persons_email` (`email`),
|
||||
KEY `ix_persons_claimed_by` (`claimed_by_user_id`),
|
||||
KEY `ix_persons_managed_by` (`managed_by_user_id`),
|
||||
KEY `ix_persons_death` (`death_confirmed_at`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ---------------------------------------------------------------- accounts ---
|
||||
CREATE TABLE IF NOT EXISTS `users` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`person_id` BIGINT NOT NULL,
|
||||
`email` VARCHAR(255) NOT NULL,
|
||||
|
||||
`security_stamp` CHAR(36) NOT NULL,
|
||||
|
||||
-- De datasleutel van deze gebruiker, versleuteld met de mastersleutel.
|
||||
`wrapped_data_key` VARBINARY(255) NOT NULL,
|
||||
|
||||
`status` TINYINT NOT NULL DEFAULT 0, -- 0 actief, 1 geblokkeerd, 2 overleden
|
||||
`email_confirmed_at` DATETIME(3) NULL,
|
||||
`two_factor_enabled` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`failed_login_count` INT NOT NULL DEFAULT 0,
|
||||
`locked_until` DATETIME(3) NULL,
|
||||
`last_login_at` DATETIME(3) NULL,
|
||||
`created_at` DATETIME(3) NOT NULL,
|
||||
`updated_at` DATETIME(3) NOT NULL,
|
||||
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `ux_users_email` (`email`),
|
||||
UNIQUE KEY `ux_users_person` (`person_id`),
|
||||
CONSTRAINT `fk_users_person` FOREIGN KEY (`person_id`) REFERENCES `persons` (`id`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- `persons` en `users` verwijzen naar elkaar, dus deze twee sleutels kunnen pas gelegd worden
|
||||
-- als beide tabellen bestaan. ALTER TABLE kent geen "IF NOT EXISTS" voor een constraint, dus
|
||||
-- wordt er eerst gekeken of hij er al ligt: zo kun je dit script gerust nog een keer draaien.
|
||||
SET @fk_claimed := (SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS
|
||||
WHERE CONSTRAINT_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'persons'
|
||||
AND CONSTRAINT_NAME = 'fk_persons_claimed_by');
|
||||
|
||||
SET @sql := IF(@fk_claimed = 0,
|
||||
'ALTER TABLE `persons` ADD CONSTRAINT `fk_persons_claimed_by` FOREIGN KEY (`claimed_by_user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL',
|
||||
'DO 0');
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @fk_managed := (SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS
|
||||
WHERE CONSTRAINT_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'persons'
|
||||
AND CONSTRAINT_NAME = 'fk_persons_managed_by');
|
||||
|
||||
SET @sql := IF(@fk_managed = 0,
|
||||
'ALTER TABLE `persons` ADD CONSTRAINT `fk_persons_managed_by` FOREIGN KEY (`managed_by_user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL',
|
||||
'DO 0');
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- ---------------------------------------------------------------- families ---
|
||||
CREATE TABLE IF NOT EXISTS `families` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`name` VARCHAR(120) NOT NULL,
|
||||
`owner_person_id` BIGINT NOT NULL,
|
||||
`is_active` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`created_at` DATETIME(3) NOT NULL,
|
||||
`updated_at` DATETIME(3) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `ix_families_owner` (`owner_person_id`),
|
||||
CONSTRAINT `fk_families_owner` FOREIGN KEY (`owner_person_id`) REFERENCES `persons` (`id`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `family_members` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`family_id` BIGINT NOT NULL,
|
||||
`person_id` BIGINT NOT NULL,
|
||||
`relation` INT NOT NULL DEFAULT 0,
|
||||
`relation_label` VARCHAR(50) NULL,
|
||||
`added_by_user_id` BIGINT NULL,
|
||||
`created_at` DATETIME(3) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `ux_family_member` (`family_id`, `person_id`),
|
||||
KEY `ix_family_members_person` (`person_id`),
|
||||
CONSTRAINT `fk_fm_family` FOREIGN KEY (`family_id`) REFERENCES `families` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_fm_person` FOREIGN KEY (`person_id`) REFERENCES `persons` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ------------------------------------------------------------ uitnodigingen ---
|
||||
-- Alleen de hash van het token staat hier; het token zelf bestaat enkel in de e-mail.
|
||||
CREATE TABLE IF NOT EXISTS `invitations` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`person_id` BIGINT NOT NULL,
|
||||
`family_id` BIGINT NOT NULL,
|
||||
`email` VARCHAR(255) NOT NULL,
|
||||
`token_hash` VARBINARY(32) NOT NULL,
|
||||
`status` INT NOT NULL DEFAULT 0,
|
||||
`created_by_user_id` BIGINT NOT NULL,
|
||||
`created_at` DATETIME(3) NOT NULL,
|
||||
`sent_at` DATETIME(3) NULL,
|
||||
`expires_at` DATETIME(3) NOT NULL,
|
||||
`accepted_at` DATETIME(3) NULL,
|
||||
`resend_count` INT NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `ux_invitations_token` (`token_hash`),
|
||||
KEY `ix_invitations_person` (`person_id`, `status`),
|
||||
CONSTRAINT `fk_inv_person` FOREIGN KEY (`person_id`) REFERENCES `persons` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_inv_family` FOREIGN KEY (`family_id`) REFERENCES `families` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ------------------------------------------------------------------- kluis ---
|
||||
-- Bijlagen: de bytes staan versleuteld buiten de database, hier alleen de verwijzing.
|
||||
CREATE TABLE IF NOT EXISTS `vault_files` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`owner_person_id` BIGINT NOT NULL,
|
||||
`file_name` VARCHAR(255) NOT NULL,
|
||||
`content_type` VARCHAR(120) NOT NULL DEFAULT 'application/octet-stream',
|
||||
`size_bytes` BIGINT NOT NULL DEFAULT 0,
|
||||
`storage_key` VARCHAR(255) NOT NULL,
|
||||
`nonce` VARBINARY(12) NOT NULL,
|
||||
`tag` VARBINARY(16) NOT NULL,
|
||||
`wrapped_content_key` VARBINARY(96) NOT NULL,
|
||||
`sha256` VARBINARY(32) NOT NULL,
|
||||
`created_at` DATETIME(3) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `ix_vault_files_owner` (`owner_person_id`),
|
||||
CONSTRAINT `fk_vf_owner` FOREIGN KEY (`owner_person_id`) REFERENCES `persons` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- Kluisitems. `title` en `category` zijn leesbaar zodat er gezocht kan worden;
|
||||
-- de inhoud zit versleuteld in `ciphertext`.
|
||||
CREATE TABLE IF NOT EXISTS `vault_items` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`owner_person_id` BIGINT NOT NULL,
|
||||
`category` INT NOT NULL,
|
||||
`title` VARCHAR(150) NOT NULL,
|
||||
`ciphertext` LONGBLOB NOT NULL,
|
||||
`nonce` VARBINARY(12) NOT NULL,
|
||||
`tag` VARBINARY(16) NOT NULL,
|
||||
`wrapped_content_key` VARBINARY(96) NOT NULL,
|
||||
`release_policy` INT NOT NULL DEFAULT 0, -- 0 alleen ikzelf, 1 na overlijden, 2 op datum
|
||||
`release_at` DATETIME(3) NULL,
|
||||
`vault_file_id` BIGINT NULL,
|
||||
`created_at` DATETIME(3) NOT NULL,
|
||||
`updated_at` DATETIME(3) NOT NULL,
|
||||
`deleted_at` DATETIME(3) NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `ix_vault_items_owner` (`owner_person_id`, `category`),
|
||||
KEY `ix_vault_items_release` (`release_policy`, `release_at`),
|
||||
CONSTRAINT `fk_vi_owner` FOREIGN KEY (`owner_person_id`) REFERENCES `persons` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_vi_file` FOREIGN KEY (`vault_file_id`) REFERENCES `vault_files` (`id`) ON DELETE SET NULL
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- Toegang van een ander tot een item: dezelfde contentsleutel, ingepakt met
|
||||
-- de datasleutel van die ander. Zonder rij hier is er geen toegang, punt.
|
||||
CREATE TABLE IF NOT EXISTS `content_grants` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`resource_type` VARCHAR(30) NOT NULL, -- VaultItem | VaultFile | Message
|
||||
`resource_id` BIGINT NOT NULL,
|
||||
`user_id` BIGINT NOT NULL,
|
||||
`wrapped_content_key` VARBINARY(96) NOT NULL,
|
||||
`reason` VARCHAR(50) NOT NULL, -- ontvanger | nalatenschap | gedeeld
|
||||
`granted_at` DATETIME(3) NOT NULL,
|
||||
`revoked_at` DATETIME(3) NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `ux_grant` (`resource_type`, `resource_id`, `user_id`),
|
||||
KEY `ix_grants_user` (`user_id`),
|
||||
CONSTRAINT `fk_grant_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ---------------------------------------------------------------- berichten ---
|
||||
CREATE TABLE IF NOT EXISTS `messages` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`from_person_id` BIGINT NOT NULL,
|
||||
`to_person_id` BIGINT NOT NULL,
|
||||
`kind` INT NOT NULL DEFAULT 0, -- 0 tekst, 1 video, 2 audio, 3 document
|
||||
`subject` VARCHAR(200) NOT NULL,
|
||||
`ciphertext` LONGBLOB NOT NULL,
|
||||
`nonce` VARBINARY(12) NOT NULL,
|
||||
`tag` VARBINARY(16) NOT NULL,
|
||||
`wrapped_content_key` VARBINARY(96) NOT NULL,
|
||||
`vault_file_id` BIGINT NULL,
|
||||
`deliver_at` DATETIME(3) NULL,
|
||||
`deliver_after_death` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`status` INT NOT NULL DEFAULT 0, -- 0 concept, 1 gepland, 2 bezorgd, 3 gelezen, 4 ingetrokken
|
||||
`delivered_at` DATETIME(3) NULL,
|
||||
`read_at` DATETIME(3) NULL,
|
||||
`created_at` DATETIME(3) NOT NULL,
|
||||
`updated_at` DATETIME(3) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `ix_messages_to` (`to_person_id`, `status`),
|
||||
KEY `ix_messages_from` (`from_person_id`),
|
||||
-- De index waarop de bezorgtaak draait.
|
||||
KEY `ix_messages_due` (`status`, `deliver_at`, `deliver_after_death`),
|
||||
CONSTRAINT `fk_msg_from` FOREIGN KEY (`from_person_id`) REFERENCES `persons` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_msg_to` FOREIGN KEY (`to_person_id`) REFERENCES `persons` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_msg_file` FOREIGN KEY (`vault_file_id`) REFERENCES `vault_files` (`id`) ON DELETE SET NULL
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ------------------------------------------------------- overlijden & nalatenschap ---
|
||||
-- Eén melding per gebruiker per profiel; dat dwingt de unieke sleutel af.
|
||||
CREATE TABLE IF NOT EXISTS `death_declarations` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`person_id` BIGINT NOT NULL,
|
||||
`declared_by_user_id` BIGINT NOT NULL,
|
||||
`date_of_death` DATE NULL,
|
||||
`note` VARCHAR(500) NULL,
|
||||
`declared_at` DATETIME(3) NOT NULL,
|
||||
`revoked_at` DATETIME(3) NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `ux_declaration` (`person_id`, `declared_by_user_id`),
|
||||
CONSTRAINT `fk_dd_person` FOREIGN KEY (`person_id`) REFERENCES `persons` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_dd_user` FOREIGN KEY (`declared_by_user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `legacy_managers` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`person_id` BIGINT NOT NULL,
|
||||
`manager_person_id` BIGINT NOT NULL,
|
||||
`priority` INT NOT NULL DEFAULT 1,
|
||||
`accepted_at` DATETIME(3) NULL,
|
||||
`access_granted_at` DATETIME(3) NULL,
|
||||
`created_at` DATETIME(3) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `ux_legacy_manager` (`person_id`, `manager_person_id`),
|
||||
CONSTRAINT `fk_lm_person` FOREIGN KEY (`person_id`) REFERENCES `persons` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_lm_manager` FOREIGN KEY (`manager_person_id`) REFERENCES `persons` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ------------------------------------------------------------------ sessies ---
|
||||
CREATE TABLE IF NOT EXISTS `refresh_tokens` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`user_id` BIGINT NOT NULL,
|
||||
`token_hash` VARBINARY(32) NOT NULL,
|
||||
`device` VARCHAR(120) NULL,
|
||||
`created_by_ip` VARCHAR(45) NULL,
|
||||
`created_at` DATETIME(3) NOT NULL,
|
||||
`expires_at` DATETIME(3) NOT NULL,
|
||||
`revoked_at` DATETIME(3) NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `ux_refresh_token` (`token_hash`),
|
||||
KEY `ix_refresh_user` (`user_id`, `expires_at`),
|
||||
CONSTRAINT `fk_rt_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ---------------------------------------------------------------- sessies ---
|
||||
-- Een aanmelding van de app. Staat in de database en niet in het geheugen van de SocketServer,
|
||||
-- want anders logt elke herstart van de service iedereen uit - en dan is de vingerafdruk waarmee
|
||||
-- je de app opent niets waard. Het token zelf staat er niet in, alleen de SHA-256 ervan.
|
||||
CREATE TABLE IF NOT EXISTS `sessies` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`token_hash` VARBINARY(32) NOT NULL,
|
||||
`user_id` BIGINT NOT NULL,
|
||||
`person_id` BIGINT NOT NULL,
|
||||
`toestel` VARCHAR(120) NULL,
|
||||
`aangemaakt_op` DATETIME(3) NOT NULL,
|
||||
`verloopt_op` DATETIME(3) NOT NULL,
|
||||
`laatst_gezien` DATETIME(3) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `ux_sessies_token` (`token_hash`),
|
||||
KEY `ix_sessies_verloopt` (`verloopt_op`),
|
||||
CONSTRAINT `fk_sessies_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ------------------------------------------------------------- inlogcodes ---
|
||||
-- Er zijn geen wachtwoorden: je logt in met een code die per e-mail komt.
|
||||
-- De code staat hier niet leesbaar in, alleen de hash ervan.
|
||||
CREATE TABLE IF NOT EXISTS `login_codes` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`email` VARCHAR(255) NOT NULL,
|
||||
`purpose` INT NOT NULL DEFAULT 0, -- 0 inloggen, 1 registreren
|
||||
`code_hash` VARCHAR(255) NOT NULL,
|
||||
`first_name` VARCHAR(80) NULL, -- alleen bij registreren
|
||||
`last_name` VARCHAR(80) NULL,
|
||||
`created_at` DATETIME(3) NOT NULL,
|
||||
`expires_at` DATETIME(3) NOT NULL,
|
||||
`consumed_at` DATETIME(3) NULL,
|
||||
`attempts` INT NOT NULL DEFAULT 0,
|
||||
`requested_from_ip` VARCHAR(45) NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
-- De index waarop het opzoeken van een openstaande code draait.
|
||||
KEY `ix_login_codes_open` (`email`, `purpose`, `expires_at`),
|
||||
KEY `ix_login_codes_created` (`email`, `created_at`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ----------------------------------------------------------------- logboek ---
|
||||
-- Alleen toevoegen, nooit wijzigen. Bij een kluis wil je kunnen nagaan wie wat wanneer deed.
|
||||
CREATE TABLE IF NOT EXISTS `audit_log` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`user_id` BIGINT NULL,
|
||||
`action` INT NOT NULL,
|
||||
`entity_type` VARCHAR(50) NULL,
|
||||
`entity_id` BIGINT NULL,
|
||||
`ip_address` VARCHAR(45) NULL,
|
||||
`user_agent` VARCHAR(255) NULL,
|
||||
`details` VARCHAR(1000) NULL,
|
||||
`created_at` DATETIME(3) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `ix_audit_user_time` (`user_id`, `created_at`),
|
||||
KEY `ix_audit_entity` (`entity_type`, `entity_id`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
Reference in New Issue
Block a user