1032 lines
45 KiB
SQL
1032 lines
45 KiB
SQL
-- Consolidated schema (fresh install)
|
|
-- Generated: 2026-02-19
|
|
-- Includes all current tables, columns, indexes and seed data.
|
|
|
|
CREATE TABLE IF NOT EXISTS `users` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`uuid` CHAR(36) NOT NULL,
|
|
`first_name` VARCHAR(100) NOT NULL,
|
|
`last_name` VARCHAR(100) NOT NULL,
|
|
`display_name` VARCHAR(210) NOT NULL,
|
|
`email` VARCHAR(255) NOT NULL,
|
|
`profile_description` TEXT NULL,
|
|
`job_title` VARCHAR(160) NULL,
|
|
`phone` VARCHAR(50) NULL,
|
|
`mobile` VARCHAR(50) NULL,
|
|
`short_dial` VARCHAR(20) NULL,
|
|
`address` VARCHAR(255) NULL,
|
|
`postal_code` VARCHAR(20) NULL,
|
|
`city` VARCHAR(100) NULL,
|
|
`country` VARCHAR(100) NULL,
|
|
`region` VARCHAR(100) NULL,
|
|
`hire_date` DATE NULL,
|
|
`email_verified_at` DATETIME NULL DEFAULT NULL,
|
|
`last_login_at` DATETIME NULL DEFAULT NULL,
|
|
`last_login_provider` VARCHAR(20) NULL DEFAULT NULL,
|
|
`password` VARCHAR(255) NOT NULL,
|
|
`locale` VARCHAR(10) DEFAULT NULL,
|
|
`totp_secret` VARCHAR(255) DEFAULT NULL,
|
|
`theme` VARCHAR(10) NOT NULL DEFAULT 'light',
|
|
`primary_tenant_id` INT NULL,
|
|
`current_tenant_id` INT UNSIGNED NULL,
|
|
`created_by` INT UNSIGNED DEFAULT NULL,
|
|
`modified_by` INT UNSIGNED DEFAULT NULL,
|
|
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
`modified` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
|
`active` TINYINT(1) NOT NULL DEFAULT 1,
|
|
`authz_version` INT UNSIGNED NOT NULL DEFAULT 1,
|
|
`active_changed_at` DATETIME NULL DEFAULT NULL,
|
|
`active_changed_by` INT UNSIGNED DEFAULT NULL,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `uniq_users_uuid` (`uuid`),
|
|
UNIQUE KEY `uniq_users_email` (`email`),
|
|
KEY `idx_users_primary_tenant_id` (`primary_tenant_id`),
|
|
KEY `idx_users_current_tenant_id` (`current_tenant_id`),
|
|
KEY `idx_users_created_by` (`created_by`),
|
|
KEY `idx_users_modified_by` (`modified_by`),
|
|
KEY `idx_users_active_changed_by` (`active_changed_by`),
|
|
CONSTRAINT `fk_users_created_by` FOREIGN KEY (`created_by`) REFERENCES `users` (`id`) ON DELETE SET NULL,
|
|
CONSTRAINT `fk_users_modified_by` FOREIGN KEY (`modified_by`) REFERENCES `users` (`id`) ON DELETE SET NULL,
|
|
CONSTRAINT `fk_users_active_changed_by` FOREIGN KEY (`active_changed_by`) REFERENCES `users` (`id`) ON DELETE SET NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `tenants` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`uuid` CHAR(36) NOT NULL,
|
|
`description` VARCHAR(255) NOT NULL,
|
|
`address` VARCHAR(255) NULL,
|
|
`postal_code` VARCHAR(20) NULL,
|
|
`city` VARCHAR(100) NULL,
|
|
`country` VARCHAR(100) NULL,
|
|
`region` VARCHAR(100) NULL,
|
|
`vat_id` VARCHAR(50) NULL,
|
|
`tax_number` VARCHAR(50) NULL,
|
|
`phone` VARCHAR(50) NULL,
|
|
`fax` VARCHAR(100) NULL,
|
|
`email` VARCHAR(190) NULL,
|
|
`support_email` VARCHAR(190) NULL,
|
|
`support_phone` VARCHAR(50) NULL,
|
|
`billing_email` VARCHAR(190) NULL,
|
|
`website` VARCHAR(255) NULL,
|
|
`privacy_url` VARCHAR(255) NULL,
|
|
`imprint_url` VARCHAR(255) NULL,
|
|
`primary_color` VARCHAR(7) NULL,
|
|
`default_theme` VARCHAR(32) NULL,
|
|
`allow_user_theme` TINYINT(1) NULL,
|
|
`status` VARCHAR(20) NOT NULL DEFAULT 'active',
|
|
`status_changed_at` DATETIME NULL DEFAULT NULL,
|
|
`status_changed_by` INT UNSIGNED DEFAULT NULL,
|
|
`created_by` INT UNSIGNED DEFAULT NULL,
|
|
`modified_by` INT UNSIGNED DEFAULT NULL,
|
|
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
`modified` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `uniq_tenants_uuid` (`uuid`),
|
|
KEY `idx_tenants_created_by` (`created_by`),
|
|
KEY `idx_tenants_modified_by` (`modified_by`),
|
|
KEY `idx_tenants_status_changed_by` (`status_changed_by`),
|
|
CONSTRAINT `chk_tenants_status` CHECK (`status` IN ('active', 'inactive')),
|
|
CONSTRAINT `fk_tenants_created_by` FOREIGN KEY (`created_by`) REFERENCES `users` (`id`) ON DELETE SET NULL,
|
|
CONSTRAINT `fk_tenants_modified_by` FOREIGN KEY (`modified_by`) REFERENCES `users` (`id`) ON DELETE SET NULL,
|
|
CONSTRAINT `fk_tenants_status_changed_by` FOREIGN KEY (`status_changed_by`) REFERENCES `users` (`id`) ON DELETE SET NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
SET @fk_users_current_tenant_exists = (
|
|
SELECT COUNT(*)
|
|
FROM information_schema.TABLE_CONSTRAINTS
|
|
WHERE CONSTRAINT_SCHEMA = DATABASE()
|
|
AND TABLE_NAME = 'users'
|
|
AND CONSTRAINT_NAME = 'fk_users_current_tenant'
|
|
AND CONSTRAINT_TYPE = 'FOREIGN KEY'
|
|
);
|
|
SET @sql_add_fk_users_current_tenant = IF(
|
|
@fk_users_current_tenant_exists = 0,
|
|
'ALTER TABLE `users` ADD CONSTRAINT `fk_users_current_tenant` FOREIGN KEY (`current_tenant_id`) REFERENCES `tenants` (`id`) ON DELETE SET NULL',
|
|
'SELECT 1'
|
|
);
|
|
PREPARE stmt_add_fk_users_current_tenant FROM @sql_add_fk_users_current_tenant;
|
|
EXECUTE stmt_add_fk_users_current_tenant;
|
|
DEALLOCATE PREPARE stmt_add_fk_users_current_tenant;
|
|
|
|
CREATE TABLE IF NOT EXISTS `roles` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`uuid` CHAR(36) NOT NULL,
|
|
`description` VARCHAR(255) NOT NULL,
|
|
`code` VARCHAR(50) DEFAULT NULL,
|
|
`active` TINYINT(1) NOT NULL DEFAULT 1,
|
|
`created_by` INT UNSIGNED DEFAULT NULL,
|
|
`modified_by` INT UNSIGNED DEFAULT NULL,
|
|
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
`modified` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `uniq_roles_uuid` (`uuid`),
|
|
UNIQUE KEY `uniq_roles_code` (`code`),
|
|
KEY `idx_roles_active` (`active`),
|
|
KEY `idx_roles_created_by` (`created_by`),
|
|
KEY `idx_roles_modified_by` (`modified_by`),
|
|
CONSTRAINT `fk_roles_created_by` FOREIGN KEY (`created_by`) REFERENCES `users` (`id`) ON DELETE SET NULL,
|
|
CONSTRAINT `fk_roles_modified_by` FOREIGN KEY (`modified_by`) REFERENCES `users` (`id`) ON DELETE SET NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `permissions` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`key` VARCHAR(191) NOT NULL,
|
|
`description` VARCHAR(255) DEFAULT NULL,
|
|
`active` TINYINT(1) NOT NULL DEFAULT 1,
|
|
`is_system` TINYINT(1) NOT NULL DEFAULT 0,
|
|
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `uniq_permissions_key` (`key`),
|
|
KEY `idx_permissions_active` (`active`),
|
|
KEY `idx_permissions_system` (`is_system`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `departments` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`uuid` CHAR(36) NOT NULL,
|
|
`description` VARCHAR(255) NOT NULL,
|
|
`tenant_id` INT UNSIGNED NOT NULL,
|
|
`code` VARCHAR(50) DEFAULT NULL,
|
|
`cost_center` VARCHAR(50) DEFAULT NULL,
|
|
`active` TINYINT(1) NOT NULL DEFAULT 1,
|
|
`created_by` INT UNSIGNED DEFAULT NULL,
|
|
`modified_by` INT UNSIGNED DEFAULT NULL,
|
|
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
`modified` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `uniq_departments_uuid` (`uuid`),
|
|
KEY `idx_departments_tenant` (`tenant_id`),
|
|
KEY `idx_departments_active` (`active`),
|
|
KEY `idx_departments_created_by` (`created_by`),
|
|
KEY `idx_departments_modified_by` (`modified_by`),
|
|
CONSTRAINT `fk_departments_tenant` FOREIGN KEY (`tenant_id`) REFERENCES `tenants` (`id`) ON DELETE RESTRICT,
|
|
CONSTRAINT `fk_departments_created_by` FOREIGN KEY (`created_by`) REFERENCES `users` (`id`) ON DELETE SET NULL,
|
|
CONSTRAINT `fk_departments_modified_by` FOREIGN KEY (`modified_by`) REFERENCES `users` (`id`) ON DELETE SET NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `pages` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`uuid` CHAR(36) NOT NULL,
|
|
`slug` VARCHAR(190) NOT NULL,
|
|
`created_by` INT UNSIGNED NULL,
|
|
`modified_by` INT UNSIGNED NULL,
|
|
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
`modified` DATETIME NULL DEFAULT NULL,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `uniq_pages_uuid` (`uuid`),
|
|
UNIQUE KEY `uniq_pages_slug` (`slug`),
|
|
KEY `idx_pages_created_by` (`created_by`),
|
|
KEY `idx_pages_modified_by` (`modified_by`),
|
|
CONSTRAINT `fk_pages_created_by` FOREIGN KEY (`created_by`) REFERENCES `users` (`id`) ON DELETE SET NULL,
|
|
CONSTRAINT `fk_pages_modified_by` FOREIGN KEY (`modified_by`) REFERENCES `users` (`id`) ON DELETE SET NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `page_contents` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`page_id` INT UNSIGNED NOT NULL,
|
|
`locale` VARCHAR(10) NOT NULL,
|
|
`content` LONGTEXT NULL,
|
|
`created_by` INT UNSIGNED NULL,
|
|
`modified_by` INT UNSIGNED NULL,
|
|
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
`modified` DATETIME NULL DEFAULT NULL,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `uniq_page_locale` (`page_id`, `locale`),
|
|
KEY `idx_page_id` (`page_id`),
|
|
KEY `idx_page_contents_created_by` (`created_by`),
|
|
KEY `idx_page_contents_modified_by` (`modified_by`),
|
|
CONSTRAINT `fk_page_contents_page` FOREIGN KEY (`page_id`) REFERENCES `pages` (`id`) ON DELETE CASCADE,
|
|
CONSTRAINT `fk_page_contents_created_by` FOREIGN KEY (`created_by`) REFERENCES `users` (`id`) ON DELETE SET NULL,
|
|
CONSTRAINT `fk_page_contents_modified_by` FOREIGN KEY (`modified_by`) REFERENCES `users` (`id`) ON DELETE SET NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `settings` (
|
|
`key` VARCHAR(64) NOT NULL,
|
|
`value` TEXT NULL,
|
|
`description` VARCHAR(255) NULL,
|
|
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`key`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `tenant_auth_microsoft` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`tenant_id` INT UNSIGNED NOT NULL,
|
|
`enabled` TINYINT(1) NOT NULL DEFAULT 0,
|
|
`enforce_microsoft_login` TINYINT(1) NOT NULL DEFAULT 0,
|
|
`sync_profile_on_login` TINYINT(1) NOT NULL DEFAULT 0,
|
|
`sync_profile_fields` TEXT NULL,
|
|
`entra_tenant_id` VARCHAR(64) NULL,
|
|
`allowed_domains` TEXT NULL,
|
|
`use_shared_app` TINYINT(1) NOT NULL DEFAULT 1,
|
|
`client_id_override` VARCHAR(191) NULL,
|
|
`client_secret_override_enc` TEXT NULL,
|
|
`auto_remember_mode` TINYINT(1) NULL DEFAULT NULL,
|
|
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
`modified` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `uniq_tenant_auth_microsoft_tenant` (`tenant_id`),
|
|
CONSTRAINT `fk_tenant_auth_microsoft_tenant` FOREIGN KEY (`tenant_id`) REFERENCES `tenants` (`id`) ON DELETE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `user_external_identities` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`user_id` INT UNSIGNED NOT NULL,
|
|
`provider` VARCHAR(32) NOT NULL,
|
|
`oid` VARCHAR(128) NOT NULL,
|
|
`tid` VARCHAR(64) NOT NULL,
|
|
`issuer` VARCHAR(255) NOT NULL,
|
|
`subject` VARCHAR(255) NOT NULL,
|
|
`email_at_link_time` VARCHAR(255) NULL,
|
|
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `uniq_user_external_provider_tid_oid` (`provider`, `tid`, `oid`),
|
|
UNIQUE KEY `uniq_user_external_provider_iss_sub` (`provider`, `issuer`, `subject`),
|
|
KEY `idx_user_external_user` (`user_id`),
|
|
CONSTRAINT `fk_user_external_identity_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `user_tenants` (
|
|
`user_id` INT UNSIGNED NOT NULL,
|
|
`tenant_id` INT UNSIGNED NOT NULL,
|
|
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`user_id`, `tenant_id`),
|
|
KEY `idx_user_tenants_user` (`user_id`),
|
|
KEY `idx_user_tenants_tenant` (`tenant_id`),
|
|
CONSTRAINT `fk_user_tenants_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE,
|
|
CONSTRAINT `fk_user_tenants_tenant` FOREIGN KEY (`tenant_id`) REFERENCES `tenants` (`id`) ON DELETE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `user_roles` (
|
|
`user_id` INT UNSIGNED NOT NULL,
|
|
`role_id` INT UNSIGNED NOT NULL,
|
|
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`user_id`, `role_id`),
|
|
KEY `idx_user_roles_user` (`user_id`),
|
|
KEY `idx_user_roles_role` (`role_id`),
|
|
CONSTRAINT `fk_user_roles_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE,
|
|
CONSTRAINT `fk_user_roles_role` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `role_permissions` (
|
|
`role_id` INT UNSIGNED NOT NULL,
|
|
`permission_id` INT UNSIGNED NOT NULL,
|
|
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`role_id`, `permission_id`),
|
|
KEY `idx_role_permissions_permission` (`permission_id`),
|
|
CONSTRAINT `fk_role_permissions_role` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE,
|
|
CONSTRAINT `fk_role_permissions_permission` FOREIGN KEY (`permission_id`) REFERENCES `permissions` (`id`) ON DELETE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `user_departments` (
|
|
`user_id` INT UNSIGNED NOT NULL,
|
|
`department_id` INT UNSIGNED NOT NULL,
|
|
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`user_id`, `department_id`),
|
|
KEY `idx_user_departments_user` (`user_id`),
|
|
KEY `idx_user_departments_department` (`department_id`),
|
|
CONSTRAINT `fk_user_departments_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE,
|
|
CONSTRAINT `fk_user_departments_department` FOREIGN KEY (`department_id`) REFERENCES `departments` (`id`) ON DELETE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `user_saved_filters` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`uuid` CHAR(36) NOT NULL,
|
|
`user_id` INT UNSIGNED NOT NULL,
|
|
`context` VARCHAR(64) NOT NULL,
|
|
`name` VARCHAR(120) NOT NULL,
|
|
`query_json` TEXT NOT NULL,
|
|
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
`modified` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `uniq_user_saved_filters_uuid` (`uuid`),
|
|
KEY `idx_user_saved_filters_user_context` (`user_id`, `context`),
|
|
KEY `idx_user_saved_filters_user_context_created` (`user_id`, `context`, `created`),
|
|
CONSTRAINT `fk_user_saved_filters_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `tenant_custom_field_definitions` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`uuid` CHAR(36) NOT NULL,
|
|
`tenant_id` INT UNSIGNED NOT NULL,
|
|
`field_key` VARCHAR(120) NOT NULL,
|
|
`label` VARCHAR(160) NOT NULL,
|
|
`type` VARCHAR(32) NOT NULL,
|
|
`is_required` TINYINT(1) NOT NULL DEFAULT 0,
|
|
`is_filterable` TINYINT(1) NOT NULL DEFAULT 0,
|
|
`active` TINYINT(1) NOT NULL DEFAULT 1,
|
|
`sort_order` INT NOT NULL DEFAULT 100,
|
|
`created_by` INT UNSIGNED DEFAULT NULL,
|
|
`modified_by` INT UNSIGNED DEFAULT NULL,
|
|
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
`modified` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `uniq_tenant_custom_field_uuid` (`uuid`),
|
|
UNIQUE KEY `uniq_tenant_custom_field_key` (`tenant_id`, `field_key`),
|
|
KEY `idx_tenant_custom_field_tenant_active` (`tenant_id`, `active`, `sort_order`),
|
|
KEY `idx_tenant_custom_field_created_by` (`created_by`),
|
|
KEY `idx_tenant_custom_field_modified_by` (`modified_by`),
|
|
CONSTRAINT `fk_tenant_custom_field_tenant` FOREIGN KEY (`tenant_id`) REFERENCES `tenants` (`id`) ON DELETE CASCADE,
|
|
CONSTRAINT `fk_tenant_custom_field_created_by` FOREIGN KEY (`created_by`) REFERENCES `users` (`id`) ON DELETE SET NULL,
|
|
CONSTRAINT `fk_tenant_custom_field_modified_by` FOREIGN KEY (`modified_by`) REFERENCES `users` (`id`) ON DELETE SET NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `tenant_custom_field_options` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`definition_id` INT UNSIGNED NOT NULL,
|
|
`option_key` VARCHAR(120) NOT NULL,
|
|
`label` VARCHAR(160) NOT NULL,
|
|
`active` TINYINT(1) NOT NULL DEFAULT 1,
|
|
`sort_order` INT NOT NULL DEFAULT 100,
|
|
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
`modified` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `uniq_custom_field_option_key` (`definition_id`, `option_key`),
|
|
KEY `idx_custom_field_option_definition_active` (`definition_id`, `active`, `sort_order`),
|
|
CONSTRAINT `fk_custom_field_option_definition` FOREIGN KEY (`definition_id`) REFERENCES `tenant_custom_field_definitions` (`id`) ON DELETE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `user_custom_field_values` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`user_id` INT UNSIGNED NOT NULL,
|
|
`definition_id` INT UNSIGNED NOT NULL,
|
|
`value_text` TEXT NULL,
|
|
`value_bool` TINYINT(1) NULL,
|
|
`value_date` DATE NULL,
|
|
`option_id` INT UNSIGNED NULL,
|
|
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
`modified` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `uniq_user_custom_field_definition` (`user_id`, `definition_id`),
|
|
KEY `idx_ucfv_definition` (`definition_id`),
|
|
KEY `idx_ucfv_option` (`option_id`),
|
|
KEY `idx_ucfv_bool` (`definition_id`, `value_bool`),
|
|
KEY `idx_ucfv_date` (`definition_id`, `value_date`),
|
|
CONSTRAINT `fk_ucfv_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE,
|
|
CONSTRAINT `fk_ucfv_definition` FOREIGN KEY (`definition_id`) REFERENCES `tenant_custom_field_definitions` (`id`) ON DELETE CASCADE,
|
|
CONSTRAINT `fk_ucfv_option` FOREIGN KEY (`option_id`) REFERENCES `tenant_custom_field_options` (`id`) ON DELETE SET NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `user_custom_field_value_options` (
|
|
`value_id` INT UNSIGNED NOT NULL,
|
|
`option_id` INT UNSIGNED NOT NULL,
|
|
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`value_id`, `option_id`),
|
|
KEY `idx_ucfvo_option` (`option_id`),
|
|
CONSTRAINT `fk_ucfvo_value` FOREIGN KEY (`value_id`) REFERENCES `user_custom_field_values` (`id`) ON DELETE CASCADE,
|
|
CONSTRAINT `fk_ucfvo_option` FOREIGN KEY (`option_id`) REFERENCES `tenant_custom_field_options` (`id`) ON DELETE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `user_api_tokens` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`uuid` CHAR(36) NOT NULL,
|
|
`user_id` INT UNSIGNED NOT NULL,
|
|
`name` VARCHAR(120) NOT NULL DEFAULT '',
|
|
`selector` CHAR(24) NOT NULL,
|
|
`token_hash` CHAR(64) NOT NULL,
|
|
`tenant_id` INT UNSIGNED NULL COMMENT 'Optional: scope token to specific tenant',
|
|
`last_used_at` DATETIME NULL DEFAULT NULL,
|
|
`last_ip` VARCHAR(45) NULL DEFAULT NULL,
|
|
`expires_at` DATETIME NULL DEFAULT NULL,
|
|
`revoked_at` DATETIME NULL DEFAULT NULL,
|
|
`created_by` INT UNSIGNED NULL,
|
|
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `uniq_user_api_token_uuid` (`uuid`),
|
|
UNIQUE KEY `uniq_user_api_token_selector` (`selector`),
|
|
KEY `idx_user_api_token_user` (`user_id`),
|
|
KEY `idx_user_api_token_tenant` (`tenant_id`),
|
|
KEY `idx_user_api_token_expires` (`expires_at`),
|
|
CONSTRAINT `fk_user_api_token_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE,
|
|
CONSTRAINT `fk_user_api_token_tenant` FOREIGN KEY (`tenant_id`) REFERENCES `tenants` (`id`) ON DELETE SET NULL,
|
|
CONSTRAINT `fk_user_api_token_created_by` FOREIGN KEY (`created_by`) REFERENCES `users` (`id`) ON DELETE SET NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `mail_log` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`to_email` VARCHAR(255) NOT NULL,
|
|
`subject` VARCHAR(255) NOT NULL,
|
|
`template` VARCHAR(100) NULL,
|
|
`status` VARCHAR(20) NOT NULL DEFAULT 'queued',
|
|
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
`sent_at` DATETIME NULL DEFAULT NULL,
|
|
`error_message` TEXT NULL,
|
|
`provider_message_id` VARCHAR(255) NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `idx_mail_log_status` (`status`),
|
|
KEY `idx_mail_log_to_email` (`to_email`),
|
|
CONSTRAINT `chk_mail_log_status` CHECK (`status` IN ('queued', 'sent', 'failed'))
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `api_audit_log` (
|
|
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`request_id` CHAR(36) NOT NULL,
|
|
`method` VARCHAR(8) NOT NULL,
|
|
`path` VARCHAR(255) NOT NULL,
|
|
`query_json` TEXT NULL,
|
|
`status_code` SMALLINT UNSIGNED NOT NULL,
|
|
`duration_ms` INT UNSIGNED NULL,
|
|
`error_code` VARCHAR(100) NULL,
|
|
`user_id` INT UNSIGNED NULL,
|
|
`tenant_id` INT UNSIGNED NULL,
|
|
`api_token_id` INT UNSIGNED NULL,
|
|
`token_tenant_id` INT UNSIGNED NULL,
|
|
`ip` VARCHAR(45) NULL,
|
|
`user_agent` VARCHAR(255) NULL,
|
|
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `uniq_api_audit_request_id_created` (`request_id`, `created_at`),
|
|
KEY `idx_api_audit_created` (`created_at`),
|
|
KEY `idx_api_audit_status_created` (`status_code`, `created_at`),
|
|
KEY `idx_api_audit_user_created` (`user_id`, `created_at`),
|
|
KEY `idx_api_audit_tenant_created` (`tenant_id`, `created_at`),
|
|
KEY `idx_api_audit_path_created` (`path`, `created_at`),
|
|
KEY `idx_api_audit_error_created` (`error_code`, `created_at`),
|
|
KEY `idx_api_audit_token_created` (`api_token_id`, `created_at`),
|
|
CONSTRAINT `fk_api_audit_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL,
|
|
CONSTRAINT `fk_api_audit_tenant` FOREIGN KEY (`tenant_id`) REFERENCES `tenants` (`id`) ON DELETE SET NULL,
|
|
CONSTRAINT `fk_api_audit_token` FOREIGN KEY (`api_token_id`) REFERENCES `user_api_tokens` (`id`) ON DELETE SET NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `system_audit_log` (
|
|
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`event_uuid` CHAR(36) NOT NULL,
|
|
`request_id` CHAR(36) NULL,
|
|
`channel` VARCHAR(16) NOT NULL,
|
|
`event_type` VARCHAR(64) NOT NULL,
|
|
`outcome` VARCHAR(16) NOT NULL,
|
|
`error_code` VARCHAR(100) NULL,
|
|
`actor_user_id` INT UNSIGNED NULL,
|
|
`actor_tenant_id` INT UNSIGNED NULL,
|
|
`target_type` VARCHAR(64) NULL,
|
|
`target_id` INT UNSIGNED NULL,
|
|
`target_uuid` CHAR(36) NULL,
|
|
`method` VARCHAR(8) NULL,
|
|
`path` VARCHAR(255) NULL,
|
|
`ip_hash` CHAR(64) NULL,
|
|
`user_agent_hash` CHAR(64) NULL,
|
|
`metadata_json` TEXT NULL,
|
|
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `uniq_system_audit_event_uuid` (`event_uuid`),
|
|
KEY `idx_system_audit_created` (`created_at`),
|
|
KEY `idx_system_audit_event_created` (`event_type`, `created_at`),
|
|
KEY `idx_system_audit_actor_created` (`actor_user_id`, `created_at`),
|
|
KEY `idx_system_audit_target_created` (`target_type`, `target_uuid`, `created_at`),
|
|
KEY `idx_system_audit_request_created` (`request_id`, `created_at`),
|
|
KEY `idx_system_audit_outcome_created` (`outcome`, `created_at`),
|
|
CONSTRAINT `chk_system_audit_log_channel` CHECK (`channel` IN ('web', 'api', 'scheduler', 'cli')),
|
|
CONSTRAINT `chk_system_audit_log_outcome` CHECK (`outcome` IN ('success', 'failed', 'denied')),
|
|
CONSTRAINT `fk_system_audit_actor_user` FOREIGN KEY (`actor_user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL,
|
|
CONSTRAINT `fk_system_audit_actor_tenant` FOREIGN KEY (`actor_tenant_id`) REFERENCES `tenants` (`id`) ON DELETE SET NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `import_audit_runs` (
|
|
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`run_uuid` CHAR(36) NOT NULL,
|
|
`profile_key` VARCHAR(32) NOT NULL,
|
|
`status` VARCHAR(16) NOT NULL,
|
|
`source_filename` VARCHAR(255) NULL,
|
|
`mapped_targets_csv` TEXT NULL,
|
|
`rows_total` INT UNSIGNED NOT NULL DEFAULT 0,
|
|
`created_count` INT UNSIGNED NOT NULL DEFAULT 0,
|
|
`skipped_count` INT UNSIGNED NOT NULL DEFAULT 0,
|
|
`failed_count` INT UNSIGNED NOT NULL DEFAULT 0,
|
|
`error_codes_json` TEXT NULL,
|
|
`started_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
`finished_at` DATETIME NULL DEFAULT NULL,
|
|
`duration_ms` INT UNSIGNED NULL,
|
|
`user_id` INT UNSIGNED NULL,
|
|
`current_tenant_id` INT UNSIGNED NULL,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `uniq_import_audit_run_uuid` (`run_uuid`),
|
|
KEY `idx_import_audit_started` (`started_at`),
|
|
KEY `idx_import_audit_status_started` (`status`, `started_at`),
|
|
KEY `idx_import_audit_profile_started` (`profile_key`, `started_at`),
|
|
KEY `idx_import_audit_user_started` (`user_id`, `started_at`),
|
|
CONSTRAINT `chk_import_audit_runs_status` CHECK (`status` IN ('running', 'success', 'partial', 'failed')),
|
|
CONSTRAINT `fk_import_audit_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL,
|
|
CONSTRAINT `fk_import_audit_tenant` FOREIGN KEY (`current_tenant_id`) REFERENCES `tenants` (`id`) ON DELETE SET NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `user_lifecycle_audit_log` (
|
|
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`run_uuid` CHAR(36) NOT NULL,
|
|
`action` VARCHAR(16) NOT NULL,
|
|
`trigger_type` VARCHAR(16) NOT NULL,
|
|
`status` VARCHAR(16) NOT NULL,
|
|
`reason_code` VARCHAR(64) NULL,
|
|
`policy_deactivate_days` INT UNSIGNED NOT NULL DEFAULT 0,
|
|
`policy_delete_days` INT UNSIGNED NOT NULL DEFAULT 0,
|
|
`actor_user_id` INT UNSIGNED NULL,
|
|
`target_user_id` INT UNSIGNED NULL,
|
|
`target_user_uuid` CHAR(36) NULL,
|
|
`target_user_email` VARCHAR(255) NULL,
|
|
`snapshot_enc` LONGTEXT NULL,
|
|
`snapshot_version` SMALLINT UNSIGNED NOT NULL DEFAULT 1,
|
|
`restored_at` DATETIME NULL DEFAULT NULL,
|
|
`restored_by_user_id` INT UNSIGNED NULL,
|
|
`restored_user_id` INT UNSIGNED NULL,
|
|
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
KEY `idx_user_lifecycle_created` (`created_at`),
|
|
KEY `idx_user_lifecycle_action_created` (`action`, `created_at`),
|
|
KEY `idx_user_lifecycle_status_created` (`status`, `created_at`),
|
|
KEY `idx_user_lifecycle_target_uuid_created` (`target_user_uuid`, `created_at`),
|
|
KEY `idx_user_lifecycle_run_uuid` (`run_uuid`),
|
|
KEY `idx_user_lifecycle_restored` (`restored_at`),
|
|
CONSTRAINT `chk_user_lifecycle_action` CHECK (`action` IN ('deactivate', 'delete', 'restore')),
|
|
CONSTRAINT `chk_user_lifecycle_trigger_type` CHECK (`trigger_type` IN ('manual', 'cron', 'system')),
|
|
CONSTRAINT `chk_user_lifecycle_status` CHECK (`status` IN ('success', 'skipped', 'failed')),
|
|
CONSTRAINT `fk_user_lifecycle_actor` FOREIGN KEY (`actor_user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL,
|
|
CONSTRAINT `fk_user_lifecycle_target` FOREIGN KEY (`target_user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL,
|
|
CONSTRAINT `fk_user_lifecycle_restored_by` FOREIGN KEY (`restored_by_user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL,
|
|
CONSTRAINT `fk_user_lifecycle_restored_user` FOREIGN KEY (`restored_user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `scheduled_jobs` (
|
|
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`job_key` VARCHAR(64) NOT NULL,
|
|
`label` VARCHAR(120) NOT NULL,
|
|
`description` VARCHAR(255) NULL,
|
|
`enabled` TINYINT(1) NOT NULL DEFAULT 1,
|
|
`timezone` VARCHAR(64) NOT NULL DEFAULT 'Europe/Berlin',
|
|
`schedule_type` VARCHAR(16) NOT NULL,
|
|
`schedule_interval` SMALLINT UNSIGNED NOT NULL DEFAULT 1,
|
|
`schedule_time` CHAR(5) NULL,
|
|
`schedule_weekdays_csv` VARCHAR(32) NULL,
|
|
`catchup_once` TINYINT(1) NOT NULL DEFAULT 1,
|
|
`next_run_at` DATETIME NULL DEFAULT NULL,
|
|
`last_run_started_at` DATETIME NULL DEFAULT NULL,
|
|
`last_run_finished_at` DATETIME NULL DEFAULT NULL,
|
|
`last_run_status` VARCHAR(16) NULL,
|
|
`last_error_code` VARCHAR(64) NULL,
|
|
`last_error_message` VARCHAR(255) NULL,
|
|
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
`updated_at` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `uniq_scheduled_jobs_job_key` (`job_key`),
|
|
KEY `idx_scheduled_jobs_enabled_next` (`enabled`, `next_run_at`),
|
|
KEY `idx_scheduled_jobs_status` (`last_run_status`),
|
|
CONSTRAINT `chk_scheduled_jobs_last_run_status` CHECK (`last_run_status` IS NULL OR `last_run_status` IN ('running', 'success', 'failed', 'skipped'))
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `scheduled_job_runs` (
|
|
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`run_uuid` CHAR(36) NOT NULL,
|
|
`job_id` BIGINT UNSIGNED NOT NULL,
|
|
`job_key` VARCHAR(64) NOT NULL,
|
|
`trigger_type` VARCHAR(16) NOT NULL,
|
|
`status` VARCHAR(16) NOT NULL,
|
|
`actor_user_id` INT UNSIGNED NULL,
|
|
`started_at` DATETIME NOT NULL,
|
|
`finished_at` DATETIME NULL DEFAULT NULL,
|
|
`duration_ms` INT UNSIGNED NULL,
|
|
`error_code` VARCHAR(64) NULL,
|
|
`error_message` VARCHAR(255) NULL,
|
|
`result_json` TEXT NULL,
|
|
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `uniq_sched_runs_run_uuid` (`run_uuid`),
|
|
KEY `idx_sched_runs_job_created` (`job_id`, `created_at`),
|
|
KEY `idx_sched_runs_status_created` (`status`, `created_at`),
|
|
KEY `idx_sched_runs_trigger_created` (`trigger_type`, `created_at`),
|
|
CONSTRAINT `chk_scheduled_job_runs_status` CHECK (`status` IN ('success', 'failed', 'skipped')),
|
|
CONSTRAINT `chk_scheduled_job_runs_trigger_type` CHECK (`trigger_type` IN ('scheduler', 'manual')),
|
|
CONSTRAINT `fk_sched_runs_job` FOREIGN KEY (`job_id`) REFERENCES `scheduled_jobs` (`id`) ON DELETE CASCADE,
|
|
CONSTRAINT `fk_sched_runs_actor_user` FOREIGN KEY (`actor_user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `scheduler_runtime_status` (
|
|
`id` TINYINT UNSIGNED NOT NULL,
|
|
`last_heartbeat_at` DATETIME NOT NULL,
|
|
`last_result` VARCHAR(32) NULL,
|
|
`last_error_code` VARCHAR(64) NULL,
|
|
`updated_at` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
CONSTRAINT `chk_scheduler_runtime_status_last_result` CHECK (`last_result` IS NULL OR `last_result` IN ('ok', 'lock_not_acquired', 'unexpected_error'))
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `request_rate_limits` (
|
|
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`scope` VARCHAR(64) NOT NULL,
|
|
`subject_hash` CHAR(64) NOT NULL,
|
|
`hits` INT UNSIGNED NOT NULL DEFAULT 0,
|
|
`window_started_at` DATETIME NOT NULL,
|
|
`blocked_until` DATETIME NULL DEFAULT NULL,
|
|
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
`modified` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `uniq_request_rate_scope_subject` (`scope`, `subject_hash`),
|
|
KEY `idx_request_rate_scope_blocked` (`scope`, `blocked_until`),
|
|
KEY `idx_request_rate_modified` (`modified`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `password_resets` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`user_id` INT UNSIGNED NOT NULL,
|
|
`code_hash` VARCHAR(255) NOT NULL,
|
|
`expires_at` DATETIME NOT NULL,
|
|
`attempts` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'Failed verification attempts',
|
|
`used_at` DATETIME NULL DEFAULT NULL,
|
|
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
KEY `idx_password_resets_user` (`user_id`),
|
|
KEY `idx_password_resets_expires` (`expires_at`),
|
|
CONSTRAINT `fk_password_resets_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `email_verifications` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`user_id` INT UNSIGNED NOT NULL,
|
|
`code_hash` VARCHAR(255) NOT NULL,
|
|
`expires_at` DATETIME NOT NULL,
|
|
`attempts` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'Failed verification attempts',
|
|
`used_at` DATETIME NULL DEFAULT NULL,
|
|
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
KEY `idx_email_verifications_user` (`user_id`),
|
|
KEY `idx_email_verifications_expires` (`expires_at`),
|
|
CONSTRAINT `fk_email_verifications_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `user_remember_tokens` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`user_id` INT UNSIGNED NOT NULL,
|
|
`selector` CHAR(24) NOT NULL,
|
|
`token_hash` CHAR(64) NOT NULL,
|
|
`expires_at` DATETIME NOT NULL,
|
|
`expired_by_admin_at` DATETIME NULL DEFAULT NULL COMMENT 'Expired by admin action',
|
|
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
`last_used` DATETIME NULL DEFAULT NULL,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `uniq_user_remember_selector` (`selector`),
|
|
KEY `idx_user_remember_user` (`user_id`),
|
|
KEY `idx_user_remember_expires` (`expires_at`),
|
|
CONSTRAINT `fk_user_remember_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
INSERT INTO `tenants` (`uuid`, `description`, `created`)
|
|
SELECT UUID(), 'MusterMandant', NOW()
|
|
WHERE NOT EXISTS (SELECT 1 FROM tenants WHERE description = 'MusterMandant');
|
|
|
|
INSERT INTO `departments` (`uuid`, `description`, `tenant_id`, `code`, `active`, `created`)
|
|
SELECT UUID(), 'Musterabteilung', t.id, 'MUSTER', 1, NOW()
|
|
FROM tenants t
|
|
WHERE t.description = 'MusterMandant'
|
|
AND NOT EXISTS (
|
|
SELECT 1 FROM departments d
|
|
WHERE d.tenant_id = t.id
|
|
AND d.description = 'Musterabteilung'
|
|
);
|
|
|
|
INSERT INTO `departments` (`uuid`, `description`, `tenant_id`, `code`, `active`, `created`)
|
|
SELECT UUID(), 'Musterabteilung 2', t.id, 'MUSTER2', 1, NOW()
|
|
FROM tenants t
|
|
WHERE t.description = 'MusterMandant'
|
|
AND NOT EXISTS (
|
|
SELECT 1 FROM departments d
|
|
WHERE d.tenant_id = t.id
|
|
AND d.description = 'Musterabteilung 2'
|
|
);
|
|
|
|
INSERT INTO `roles` (`uuid`, `description`, `code`, `active`, `created`)
|
|
SELECT UUID(), 'Admin', 'ADMIN', 1, NOW()
|
|
WHERE NOT EXISTS (SELECT 1 FROM roles WHERE description = 'Admin');
|
|
|
|
INSERT INTO `roles` (`uuid`, `description`, `code`, `active`, `created`)
|
|
SELECT UUID(), 'User', 'USER', 1, NOW()
|
|
WHERE NOT EXISTS (SELECT 1 FROM roles WHERE code = 'USER');
|
|
|
|
INSERT INTO `users` (
|
|
`uuid`,
|
|
`first_name`,
|
|
`last_name`,
|
|
`display_name`,
|
|
`email`,
|
|
`profile_description`,
|
|
`job_title`,
|
|
`phone`,
|
|
`mobile`,
|
|
`short_dial`,
|
|
`address`,
|
|
`postal_code`,
|
|
`city`,
|
|
`country`,
|
|
`region`,
|
|
`hire_date`,
|
|
`email_verified_at`,
|
|
`password`,
|
|
`locale`,
|
|
`totp_secret`,
|
|
`theme`,
|
|
`primary_tenant_id`,
|
|
`created_by`,
|
|
`created`,
|
|
`active`,
|
|
`active_changed_at`,
|
|
`active_changed_by`
|
|
)
|
|
SELECT
|
|
UUID(),
|
|
'Detlef',
|
|
'Demo',
|
|
'Detlef Demo',
|
|
'demo@user.com',
|
|
'Demo-Nutzer fuer Vorschau und Test der Adressbuchdarstellung.',
|
|
'Sachbearbeiter',
|
|
'+49 30 1234567',
|
|
'+49 171 2345678',
|
|
'123',
|
|
'Musterstrasse 1',
|
|
'10115',
|
|
'Berlin',
|
|
'Deutschland',
|
|
'Berlin',
|
|
'2024-01-15',
|
|
NOW(),
|
|
'$2y$12$KVCQvuy4Pl1aySBuzSpc7ehpZhAzYZkndDI9OaMi05E2P/Mhob5HO',
|
|
'de',
|
|
NULL,
|
|
'light',
|
|
(SELECT id FROM tenants WHERE description = 'MusterMandant' LIMIT 1),
|
|
NULL,
|
|
NOW(),
|
|
1,
|
|
NOW(),
|
|
NULL
|
|
WHERE NOT EXISTS (SELECT 1 FROM users WHERE email = 'demo@user.com');
|
|
|
|
UPDATE `users`
|
|
SET `email_verified_at` = COALESCE(`email_verified_at`, NOW())
|
|
WHERE `email` = 'demo@user.com';
|
|
|
|
UPDATE `users`
|
|
SET
|
|
`profile_description` = COALESCE(`profile_description`, 'Demo-Nutzer fuer Vorschau und Test der Adressbuchdarstellung.'),
|
|
`job_title` = COALESCE(`job_title`, 'Sachbearbeiter'),
|
|
`phone` = COALESCE(`phone`, '+49 30 1234567'),
|
|
`mobile` = COALESCE(`mobile`, '+49 171 2345678'),
|
|
`short_dial` = COALESCE(`short_dial`, '123'),
|
|
`address` = COALESCE(`address`, 'Musterstrasse 1'),
|
|
`postal_code` = COALESCE(`postal_code`, '10115'),
|
|
`city` = COALESCE(`city`, 'Berlin'),
|
|
`country` = COALESCE(`country`, 'Deutschland'),
|
|
`region` = COALESCE(`region`, 'Berlin'),
|
|
`hire_date` = COALESCE(`hire_date`, '2024-01-15')
|
|
WHERE `email` = 'demo@user.com';
|
|
|
|
INSERT INTO `user_tenants` (`user_id`, `tenant_id`, `created`)
|
|
SELECT u.id, t.id, NOW()
|
|
FROM users u
|
|
JOIN tenants t ON t.description = 'MusterMandant'
|
|
WHERE u.email = 'demo@user.com'
|
|
AND NOT EXISTS (
|
|
SELECT 1 FROM user_tenants ut WHERE ut.user_id = u.id AND ut.tenant_id = t.id
|
|
);
|
|
|
|
INSERT INTO `user_departments` (`user_id`, `department_id`, `created`)
|
|
SELECT u.id, d.id, NOW()
|
|
FROM users u
|
|
JOIN departments d ON d.code = 'MUSTER'
|
|
JOIN tenants t ON t.id = d.tenant_id AND t.description = 'MusterMandant'
|
|
WHERE u.email = 'demo@user.com'
|
|
AND NOT EXISTS (
|
|
SELECT 1 FROM user_departments ud WHERE ud.user_id = u.id AND ud.department_id = d.id
|
|
);
|
|
|
|
INSERT INTO `user_roles` (`user_id`, `role_id`, `created`)
|
|
SELECT u.id, r.id, NOW()
|
|
FROM users u
|
|
JOIN roles r ON r.description = 'Admin'
|
|
WHERE u.email = 'demo@user.com'
|
|
AND NOT EXISTS (
|
|
SELECT 1 FROM user_roles ur WHERE ur.user_id = u.id AND ur.role_id = r.id
|
|
);
|
|
|
|
INSERT INTO `pages` (`uuid`, `slug`, `created`)
|
|
SELECT UUID(), 'impressum', NOW()
|
|
WHERE NOT EXISTS (SELECT 1 FROM pages WHERE slug = 'impressum');
|
|
|
|
INSERT INTO `page_contents` (`page_id`, `locale`, `content`, `created`)
|
|
SELECT p.id, 'de', NULL, p.created
|
|
FROM pages p
|
|
WHERE NOT EXISTS (
|
|
SELECT 1 FROM page_contents pc WHERE pc.page_id = p.id AND pc.locale = 'de'
|
|
);
|
|
|
|
INSERT INTO `permissions` (`key`, `description`, `active`, `is_system`)
|
|
VALUES
|
|
('users.view', 'Can view users', 1, 1),
|
|
('users.view_meta', 'Can view user status and meta', 1, 1),
|
|
('users.view_audit', 'Can view user audit log', 1, 1),
|
|
('users.create', 'Can create users', 1, 1),
|
|
('users.update', 'Can update users', 1, 1),
|
|
('users.access_pdf', 'Can generate onboarding access PDFs', 1, 1),
|
|
('users.delete', 'Can delete users', 1, 1),
|
|
('users.self_update', 'Can update own user', 1, 1),
|
|
('users.update_assignments', 'Can update user assignments', 1, 1),
|
|
('address_book.view', 'Can view address book', 1, 1),
|
|
('tenants.view', 'Can view tenants', 1, 1),
|
|
('tenants.create', 'Can create tenants', 1, 1),
|
|
('tenants.update', 'Can update tenants', 1, 1),
|
|
('tenants.sso_manage', 'Can manage tenant Microsoft SSO settings', 1, 1),
|
|
('tenants.delete', 'Can delete tenants', 1, 1),
|
|
('departments.view', 'Can view departments', 1, 1),
|
|
('departments.create', 'Can create departments', 1, 1),
|
|
('departments.update', 'Can update departments', 1, 1),
|
|
('departments.delete', 'Can delete departments', 1, 1),
|
|
('departments.import', 'Can import departments', 1, 1),
|
|
('roles.view', 'Can view roles', 1, 1),
|
|
('roles.create', 'Can create roles', 1, 1),
|
|
('roles.update', 'Can update roles', 1, 1),
|
|
('roles.delete', 'Can delete roles', 1, 1),
|
|
('permissions.view', 'Can view permissions', 1, 1),
|
|
('permissions.create', 'Can create permissions', 1, 1),
|
|
('permissions.update', 'Can update permissions', 1, 1),
|
|
('permissions.delete', 'Can delete permissions', 1, 1),
|
|
('settings.view', 'Can view settings', 1, 1),
|
|
('settings.update', 'Can update settings', 1, 1),
|
|
('tenant.scope.global', 'Can bypass tenant scope globally', 1, 1),
|
|
('imports.view', 'Can view imports', 1, 1),
|
|
('imports.audit.view', 'Can view import audit logs', 1, 1),
|
|
('jobs.view', 'Can view scheduled jobs', 1, 1),
|
|
('jobs.manage', 'Can manage scheduled jobs', 1, 1),
|
|
('jobs.run_now', 'Can run scheduled jobs manually', 1, 1),
|
|
('user_lifecycle_audit.view', 'Can view user lifecycle audit logs', 1, 1),
|
|
('users.import', 'Can import users', 1, 1),
|
|
('users.import_assignments', 'Can assign tenant, role and department during user import', 1, 1),
|
|
('users.lifecycle_restore', 'Can restore users from lifecycle audit', 1, 1),
|
|
('custom_fields.manage', 'Can manage tenant custom field definitions', 1, 1),
|
|
('custom_fields.edit_values', 'Can edit user custom field values', 1, 1),
|
|
('api_docs.view', 'Can view API documentation', 1, 1),
|
|
('docs.view', 'Can view developer documentation', 1, 1),
|
|
('mail_log.view', 'Can view mail logs', 1, 1),
|
|
('api_audit.view', 'Can view API audit logs', 1, 1),
|
|
('system_audit.view', 'Can view system audit logs', 1, 1),
|
|
('system_audit.purge', 'Can purge system audit logs', 1, 1),
|
|
('stats.view', 'Can view statistics', 1, 1)
|
|
ON DUPLICATE KEY UPDATE
|
|
`description` = VALUES(`description`),
|
|
`active` = VALUES(`active`),
|
|
`is_system` = VALUES(`is_system`);
|
|
|
|
INSERT INTO `scheduled_jobs` (
|
|
`job_key`,
|
|
`label`,
|
|
`description`,
|
|
`enabled`,
|
|
`timezone`,
|
|
`schedule_type`,
|
|
`schedule_interval`,
|
|
`schedule_time`,
|
|
`schedule_weekdays_csv`,
|
|
`catchup_once`,
|
|
`next_run_at`
|
|
)
|
|
VALUES (
|
|
'user_lifecycle_run',
|
|
'User lifecycle run',
|
|
'Runs automatic user deactivate/delete policy',
|
|
1,
|
|
'Europe/Berlin',
|
|
'daily',
|
|
1,
|
|
'02:15',
|
|
NULL,
|
|
1,
|
|
NULL
|
|
)
|
|
ON DUPLICATE KEY UPDATE
|
|
`label` = VALUES(`label`),
|
|
`description` = VALUES(`description`);
|
|
|
|
INSERT INTO `scheduled_jobs` (
|
|
`job_key`,
|
|
`label`,
|
|
`description`,
|
|
`enabled`,
|
|
`timezone`,
|
|
`schedule_type`,
|
|
`schedule_interval`,
|
|
`schedule_time`,
|
|
`schedule_weekdays_csv`,
|
|
`catchup_once`,
|
|
`next_run_at`
|
|
)
|
|
VALUES (
|
|
'system_audit_purge',
|
|
'System audit purge',
|
|
'Purges system audit entries by retention policy',
|
|
1,
|
|
'Europe/Berlin',
|
|
'daily',
|
|
1,
|
|
'03:00',
|
|
NULL,
|
|
1,
|
|
NULL
|
|
)
|
|
ON DUPLICATE KEY UPDATE
|
|
`label` = VALUES(`label`),
|
|
`description` = VALUES(`description`);
|
|
|
|
INSERT INTO `scheduler_runtime_status` (
|
|
`id`,
|
|
`last_heartbeat_at`,
|
|
`last_result`,
|
|
`last_error_code`
|
|
)
|
|
VALUES (
|
|
1,
|
|
NOW(),
|
|
'ok',
|
|
NULL
|
|
)
|
|
ON DUPLICATE KEY UPDATE
|
|
`id` = `id`;
|
|
|
|
INSERT INTO `role_permissions` (`role_id`, `permission_id`, `created`)
|
|
SELECT r.id, p.id, NOW()
|
|
FROM roles r
|
|
JOIN permissions p ON p.`key` IN (
|
|
'users.view', 'users.view_meta', 'users.view_audit', 'users.create', 'users.update', 'users.access_pdf', 'users.delete',
|
|
'users.self_update', 'users.update_assignments',
|
|
'address_book.view',
|
|
'tenants.view', 'tenants.create', 'tenants.update', 'tenants.sso_manage', 'tenants.delete',
|
|
'departments.view', 'departments.create', 'departments.update', 'departments.delete', 'departments.import',
|
|
'roles.view', 'roles.create', 'roles.update', 'roles.delete',
|
|
'permissions.view', 'permissions.create', 'permissions.update', 'permissions.delete',
|
|
'settings.view', 'settings.update', 'tenant.scope.global',
|
|
'imports.view', 'imports.audit.view', 'jobs.view', 'jobs.manage', 'jobs.run_now',
|
|
'user_lifecycle_audit.view', 'users.import', 'users.import_assignments',
|
|
'users.lifecycle_restore',
|
|
'custom_fields.manage', 'custom_fields.edit_values',
|
|
'api_docs.view', 'docs.view',
|
|
'mail_log.view', 'api_audit.view', 'system_audit.view', 'system_audit.purge',
|
|
'stats.view'
|
|
)
|
|
WHERE r.description IN ('Admin', 'Administrator') OR r.id = 1
|
|
ON DUPLICATE KEY UPDATE role_id = role_id;
|
|
|
|
INSERT INTO `role_permissions` (`role_id`, `permission_id`, `created`)
|
|
SELECT r.id, p.id, NOW()
|
|
FROM roles r
|
|
JOIN permissions p ON p.`key` IN ('users.self_update', 'address_book.view')
|
|
WHERE r.code = 'USER' OR r.description = 'User'
|
|
ON DUPLICATE KEY UPDATE role_id = role_id;
|
|
|
|
INSERT INTO `settings` (`key`, `value`, `description`)
|
|
SELECT 'default_tenant_id', CAST(t.id AS CHAR), 'setting.default_tenant'
|
|
FROM tenants t
|
|
WHERE t.description = 'MusterMandant'
|
|
LIMIT 1
|
|
ON DUPLICATE KEY UPDATE
|
|
`key` = `key`;
|
|
|
|
INSERT INTO `settings` (`key`, `value`, `description`)
|
|
SELECT 'default_department_id', CAST(d.id AS CHAR), 'setting.default_department'
|
|
FROM departments d
|
|
JOIN tenants t ON t.id = d.tenant_id
|
|
WHERE d.code = 'MUSTER'
|
|
AND t.description = 'MusterMandant'
|
|
LIMIT 1
|
|
ON DUPLICATE KEY UPDATE
|
|
`key` = `key`;
|
|
|
|
INSERT INTO `settings` (`key`, `value`, `description`)
|
|
SELECT 'default_role_id', CAST(r.id AS CHAR), 'setting.default_role'
|
|
FROM roles r
|
|
WHERE r.code = 'USER'
|
|
LIMIT 1
|
|
ON DUPLICATE KEY UPDATE
|
|
`key` = `key`;
|
|
|
|
INSERT INTO `settings` (`key`, `value`, `description`)
|
|
SELECT 'api_cors_allowed_origins', CONCAT('http://localhost:8080', CHAR(10), 'http://127.0.0.1:8080'), 'setting.api_cors_allowed_origins'
|
|
ON DUPLICATE KEY UPDATE
|
|
`key` = `key`;
|
|
|
|
INSERT INTO `settings` (`key`, `value`, `description`)
|
|
VALUES
|
|
('app_title', 'CoreCore', 'setting.app_title'),
|
|
('app_locale', 'de', 'setting.app_locale'),
|
|
('app_theme', 'light', 'setting.app_theme'),
|
|
('app_theme_user', '1', 'setting.app_theme_user'),
|
|
('app_registration', '1', 'setting.app_registration'),
|
|
('app_primary_color', '#105433', 'setting.app_primary_color'),
|
|
('api_token_default_ttl_days', '90', 'setting.api_token_default_ttl_days'),
|
|
('api_token_max_ttl_days', '365', 'setting.api_token_max_ttl_days'),
|
|
('session_idle_timeout_minutes', '30', 'setting.session_idle_timeout_minutes'),
|
|
('session_absolute_timeout_hours', '8', 'setting.session_absolute_timeout_hours'),
|
|
('user_inactivity_deactivate_days', '180', 'setting.user_inactivity_deactivate_days'),
|
|
('user_inactivity_delete_days', '365', 'setting.user_inactivity_delete_days'),
|
|
('system_audit_enabled', '1', 'setting.system_audit_enabled'),
|
|
('system_audit_retention_days', '365', 'setting.system_audit_retention_days'),
|
|
('frontend_telemetry_enabled', '1', 'setting.frontend_telemetry_enabled'),
|
|
('frontend_telemetry_sample_rate', '0.2', 'setting.frontend_telemetry_sample_rate'),
|
|
('frontend_telemetry_allowed_events', 'ajax_error,warn_once', 'setting.frontend_telemetry_allowed_events'),
|
|
('microsoft_auto_remember_default', '0', 'setting.microsoft_auto_remember_default'),
|
|
('remember_token_lifetime_days', '30', 'setting.remember_token_lifetime_days')
|
|
ON DUPLICATE KEY UPDATE
|
|
`key` = `key`;
|