add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks - Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists - Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services - Add Microsoft OIDC SSO, API token management, and user lifecycle features - Add swagger-ui vendor integration and OpenAPI spec - Add production Docker setup and bin/ scripts - Update composer dependencies, config, templates, and frontend assets throughout Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
415
db/init/init.sql
415
db/init/init.sql
@@ -1,5 +1,6 @@
|
||||
-- Consolidated schema (fresh install)
|
||||
-- Includes all current tables, columns, indexes, and seed data.
|
||||
-- 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,
|
||||
@@ -21,6 +22,7 @@ CREATE TABLE IF NOT EXISTS `users` (
|
||||
`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,
|
||||
@@ -32,6 +34,7 @@ CREATE TABLE IF NOT EXISTS `users` (
|
||||
`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`),
|
||||
@@ -69,6 +72,8 @@ CREATE TABLE IF NOT EXISTS `tenants` (
|
||||
`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,
|
||||
@@ -123,6 +128,7 @@ 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,
|
||||
@@ -132,9 +138,11 @@ CREATE TABLE IF NOT EXISTS `departments` (
|
||||
`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;
|
||||
@@ -183,6 +191,42 @@ CREATE TABLE IF NOT EXISTS `settings` (
|
||||
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,
|
||||
`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,
|
||||
@@ -226,17 +270,117 @@ CREATE TABLE IF NOT EXISTS `user_departments` (
|
||||
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 `tenant_departments` (
|
||||
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,
|
||||
`department_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_tenant_department` (`tenant_id`, `department_id`),
|
||||
KEY `idx_tenant_departments_tenant` (`tenant_id`),
|
||||
KEY `idx_tenant_departments_department` (`department_id`),
|
||||
CONSTRAINT `fk_tenant_departments_tenant` FOREIGN KEY (`tenant_id`) REFERENCES `tenants` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_tenant_departments_department` FOREIGN KEY (`department_id`) REFERENCES `departments` (`id`) ON DELETE CASCADE
|
||||
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` (
|
||||
@@ -254,6 +398,169 @@ CREATE TABLE IF NOT EXISTS `mail_log` (
|
||||
KEY `idx_mail_log_to_email` (`to_email`)
|
||||
) 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 `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 `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 `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`)
|
||||
) 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 `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`)
|
||||
) 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,
|
||||
@@ -302,9 +609,11 @@ INSERT INTO `tenants` (`uuid`, `description`, `created`)
|
||||
SELECT UUID(), 'Cronus', NOW()
|
||||
WHERE NOT EXISTS (SELECT 1 FROM tenants WHERE description = 'Cronus');
|
||||
|
||||
INSERT INTO `departments` (`uuid`, `description`, `code`, `active`, `created`)
|
||||
SELECT UUID(), 'IT', 'IT', 1, NOW()
|
||||
WHERE NOT EXISTS (SELECT 1 FROM departments WHERE description = 'IT');
|
||||
INSERT INTO `departments` (`uuid`, `description`, `tenant_id`, `code`, `active`, `created`)
|
||||
SELECT UUID(), 'IT', t.id, 'IT', 1, NOW()
|
||||
FROM tenants t
|
||||
WHERE t.description = 'Cronus'
|
||||
AND NOT EXISTS (SELECT 1 FROM departments WHERE description = 'IT');
|
||||
|
||||
INSERT INTO `roles` (`uuid`, `description`, `code`, `active`, `created`)
|
||||
SELECT UUID(), 'Admin', 'ADMIN', 1, NOW()
|
||||
@@ -363,15 +672,6 @@ WHERE u.email = 'demo@user.com'
|
||||
SELECT 1 FROM user_departments ud WHERE ud.user_id = u.id AND ud.department_id = d.id
|
||||
);
|
||||
|
||||
INSERT INTO `tenant_departments` (`tenant_id`, `department_id`, `created`)
|
||||
SELECT t.id, d.id, NOW()
|
||||
FROM tenants t
|
||||
JOIN departments d ON d.description = 'IT'
|
||||
WHERE t.description = 'Cronus'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM tenant_departments td WHERE td.tenant_id = t.id AND td.department_id = d.id
|
||||
);
|
||||
|
||||
INSERT INTO `user_roles` (`user_id`, `role_id`, `created`)
|
||||
SELECT u.id, r.id, NOW()
|
||||
FROM users u
|
||||
@@ -399,6 +699,7 @@ VALUES
|
||||
('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),
|
||||
@@ -406,11 +707,13 @@ VALUES
|
||||
('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),
|
||||
@@ -421,26 +724,90 @@ VALUES
|
||||
('permissions.delete', 'Can delete permissions', 1, 1),
|
||||
('settings.view', 'Can view settings', 1, 1),
|
||||
('settings.update', 'Can update settings', 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),
|
||||
('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 `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.delete',
|
||||
'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.delete',
|
||||
'departments.view', 'departments.create', 'departments.update', 'departments.delete',
|
||||
'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',
|
||||
'mail_log.view',
|
||||
'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',
|
||||
'stats.view'
|
||||
)
|
||||
WHERE r.description IN ('Admin', 'Administrator') OR r.id = 1
|
||||
|
||||
Reference in New Issue
Block a user