185 lines
9.8 KiB
SQL
185 lines
9.8 KiB
SQL
-- Phase 1 authentication and authorization baseline.
|
|
-- Internal BIGINT identifiers are never exposed through public APIs.
|
|
|
|
CREATE TABLE `users` (
|
|
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`public_id` CHAR(36) NOT NULL,
|
|
`status` ENUM('ACTIVE', 'SUSPENDED', 'DISABLED') NOT NULL DEFAULT 'ACTIVE',
|
|
`user_type` ENUM('PUBLIC', 'STAFF') NOT NULL,
|
|
`mobile_encrypted` VARCHAR(512) NULL,
|
|
`mobile_hash` CHAR(64) NULL,
|
|
`nickname` VARCHAR(100) NULL,
|
|
`avatar_url` VARCHAR(512) NULL,
|
|
`last_login_at` DATETIME(3) NULL,
|
|
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
`updated_at` DATETIME(3) NOT NULL,
|
|
UNIQUE INDEX `users_public_id_key`(`public_id`),
|
|
UNIQUE INDEX `users_mobile_hash_key`(`mobile_hash`),
|
|
PRIMARY KEY (`id`)
|
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE `wechat_identities` (
|
|
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`user_id` BIGINT UNSIGNED NOT NULL,
|
|
`appid` VARCHAR(64) NOT NULL,
|
|
`openid_ciphertext` VARCHAR(512) NOT NULL,
|
|
`openid_hash` CHAR(64) NOT NULL,
|
|
`unionid_ciphertext` VARCHAR(512) NULL,
|
|
`unionid_hash` CHAR(64) NULL,
|
|
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
`updated_at` DATETIME(3) NOT NULL,
|
|
INDEX `wechat_identities_user_id_idx`(`user_id`),
|
|
UNIQUE INDEX `wechat_identities_appid_openid_hash_key`(`appid`, `openid_hash`),
|
|
PRIMARY KEY (`id`)
|
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE `staff_profiles` (
|
|
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`user_id` BIGINT UNSIGNED NOT NULL,
|
|
`employee_no` VARCHAR(50) NULL,
|
|
`display_name` VARCHAR(100) NOT NULL,
|
|
`department` VARCHAR(100) NULL,
|
|
`status` ENUM('ACTIVE', 'INACTIVE') NOT NULL DEFAULT 'ACTIVE',
|
|
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
`updated_at` DATETIME(3) NOT NULL,
|
|
UNIQUE INDEX `staff_profiles_user_id_key`(`user_id`),
|
|
UNIQUE INDEX `staff_profiles_employee_no_key`(`employee_no`),
|
|
PRIMARY KEY (`id`)
|
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE `admin_credentials` (
|
|
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`user_id` BIGINT UNSIGNED NOT NULL,
|
|
`username` VARCHAR(64) NOT NULL,
|
|
`password_hash` VARCHAR(255) NOT NULL,
|
|
`failed_login_count` INTEGER UNSIGNED NOT NULL DEFAULT 0,
|
|
`locked_until` DATETIME(3) NULL,
|
|
`password_changed_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
`updated_at` DATETIME(3) NOT NULL,
|
|
UNIQUE INDEX `admin_credentials_user_id_key`(`user_id`),
|
|
UNIQUE INDEX `admin_credentials_username_key`(`username`),
|
|
PRIMARY KEY (`id`)
|
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE `auth_sessions` (
|
|
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`public_id` CHAR(36) NOT NULL,
|
|
`user_id` BIGINT UNSIGNED NOT NULL,
|
|
`channel` ENUM('WECHAT', 'ADMIN') NOT NULL,
|
|
`token_hash` CHAR(64) NOT NULL,
|
|
`expires_at` DATETIME(3) NOT NULL,
|
|
`last_used_at` DATETIME(3) NULL,
|
|
`revoked_at` DATETIME(3) NULL,
|
|
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
UNIQUE INDEX `auth_sessions_public_id_key`(`public_id`),
|
|
UNIQUE INDEX `auth_sessions_token_hash_key`(`token_hash`),
|
|
INDEX `auth_sessions_user_channel_status_idx`(`user_id`, `channel`, `revoked_at`, `expires_at`),
|
|
INDEX `auth_sessions_expires_at_idx`(`expires_at`),
|
|
PRIMARY KEY (`id`)
|
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE `roles` (
|
|
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`public_id` CHAR(36) NOT NULL,
|
|
`code` VARCHAR(64) NOT NULL,
|
|
`name` VARCHAR(100) NOT NULL,
|
|
`description` VARCHAR(255) NULL,
|
|
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
`updated_at` DATETIME(3) NOT NULL,
|
|
UNIQUE INDEX `roles_public_id_key`(`public_id`),
|
|
UNIQUE INDEX `roles_code_key`(`code`),
|
|
PRIMARY KEY (`id`)
|
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE `permissions` (
|
|
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`code` VARCHAR(100) NOT NULL,
|
|
`name` VARCHAR(100) NOT NULL,
|
|
`description` VARCHAR(255) NULL,
|
|
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
UNIQUE INDEX `permissions_code_key`(`code`),
|
|
PRIMARY KEY (`id`)
|
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE `user_roles` (
|
|
`user_id` BIGINT UNSIGNED NOT NULL,
|
|
`role_id` BIGINT UNSIGNED NOT NULL,
|
|
`assigned_by` BIGINT UNSIGNED NULL,
|
|
`assigned_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
INDEX `user_roles_role_id_idx`(`role_id`),
|
|
INDEX `user_roles_assigned_by_idx`(`assigned_by`),
|
|
PRIMARY KEY (`user_id`, `role_id`)
|
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE `role_permissions` (
|
|
`role_id` BIGINT UNSIGNED NOT NULL,
|
|
`permission_id` BIGINT UNSIGNED NOT NULL,
|
|
INDEX `role_permissions_permission_id_idx`(`permission_id`),
|
|
PRIMARY KEY (`role_id`, `permission_id`)
|
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE `audit_logs` (
|
|
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`request_id` CHAR(36) NOT NULL,
|
|
`actor_user_id` BIGINT UNSIGNED NULL,
|
|
`actor_role` VARCHAR(64) NULL,
|
|
`action` VARCHAR(100) NOT NULL,
|
|
`resource_type` VARCHAR(100) NULL,
|
|
`resource_public_id` VARCHAR(100) NULL,
|
|
`result` ENUM('SUCCESS', 'FAILURE') NOT NULL,
|
|
`metadata_json` JSON NULL,
|
|
`ip_hash` CHAR(64) NULL,
|
|
`user_agent_summary` VARCHAR(255) NULL,
|
|
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
INDEX `audit_logs_actor_created_at_idx`(`actor_user_id`, `created_at`),
|
|
INDEX `audit_logs_resource_created_at_idx`(`resource_type`, `resource_public_id`, `created_at`),
|
|
INDEX `audit_logs_action_created_at_idx`(`action`, `created_at`),
|
|
PRIMARY KEY (`id`)
|
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
|
|
ALTER TABLE `wechat_identities` ADD CONSTRAINT `wechat_identities_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
ALTER TABLE `staff_profiles` ADD CONSTRAINT `staff_profiles_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
ALTER TABLE `admin_credentials` ADD CONSTRAINT `admin_credentials_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
ALTER TABLE `auth_sessions` ADD CONSTRAINT `auth_sessions_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
ALTER TABLE `user_roles` ADD CONSTRAINT `user_roles_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
ALTER TABLE `user_roles` ADD CONSTRAINT `user_roles_role_id_fkey` FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
ALTER TABLE `user_roles` ADD CONSTRAINT `user_roles_assigned_by_fkey` FOREIGN KEY (`assigned_by`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
ALTER TABLE `role_permissions` ADD CONSTRAINT `role_permissions_role_id_fkey` FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
ALTER TABLE `role_permissions` ADD CONSTRAINT `role_permissions_permission_id_fkey` FOREIGN KEY (`permission_id`) REFERENCES `permissions`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
ALTER TABLE `audit_logs` ADD CONSTRAINT `audit_logs_actor_user_id_fkey` FOREIGN KEY (`actor_user_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
|
|
INSERT INTO `roles` (`public_id`, `code`, `name`, `description`, `updated_at`) VALUES
|
|
('9fc73dca-5e75-4ce6-b8ad-d270bd020001', 'VOLUNTEER', '志愿者', '仅访问本人被分配的最小必要任务信息', CURRENT_TIMESTAMP(3)),
|
|
('9fc73dca-5e75-4ce6-b8ad-d270bd020002', 'STAFF', '工作人员', '按负责范围处理公益服务', CURRENT_TIMESTAMP(3)),
|
|
('9fc73dca-5e75-4ce6-b8ad-d270bd020003', 'PROJECT_MANAGER', '项目负责人', '按项目范围管理服务', CURRENT_TIMESTAMP(3)),
|
|
('9fc73dca-5e75-4ce6-b8ad-d270bd020004', 'ADMIN', '管理员', '跨项目业务管理', CURRENT_TIMESTAMP(3)),
|
|
('9fc73dca-5e75-4ce6-b8ad-d270bd020005', 'SUPER_ADMIN', '超级管理员', '系统级配置维护,日常不使用', CURRENT_TIMESTAMP(3));
|
|
|
|
INSERT INTO `permissions` (`code`, `name`, `description`) VALUES
|
|
('admin:access', '访问管理后台', '允许进入管理后台'),
|
|
('users:read', '查看用户', '按授权范围查看用户基础信息'),
|
|
('users:manage', '管理用户', '管理用户状态与基础信息'),
|
|
('roles:manage', '管理角色权限', '分配角色和维护权限'),
|
|
('audit:read', '查看审计日志', '按权限查看审计记录'),
|
|
('system:manage', '管理系统配置', '维护系统级配置'),
|
|
('sensitive:read', '查看敏感信息', '经审计查看必要敏感信息'),
|
|
('sensitive:export', '导出敏感信息', '受控导出敏感信息'),
|
|
('resources:access_all', '跨范围访问资源', '按角色范围访问非本人资源');
|
|
|
|
INSERT INTO `role_permissions` (`role_id`, `permission_id`)
|
|
SELECT r.id, p.id FROM roles r CROSS JOIN permissions p
|
|
WHERE r.code = 'STAFF' AND p.code IN ('admin:access', 'users:read');
|
|
|
|
INSERT INTO `role_permissions` (`role_id`, `permission_id`)
|
|
SELECT r.id, p.id FROM roles r CROSS JOIN permissions p
|
|
WHERE r.code = 'PROJECT_MANAGER' AND p.code IN ('admin:access', 'users:read', 'resources:access_all');
|
|
|
|
INSERT INTO `role_permissions` (`role_id`, `permission_id`)
|
|
SELECT r.id, p.id FROM roles r CROSS JOIN permissions p
|
|
WHERE r.code = 'ADMIN' AND p.code IN ('admin:access', 'users:read', 'users:manage', 'roles:manage', 'audit:read', 'sensitive:read', 'resources:access_all');
|
|
|
|
INSERT INTO `role_permissions` (`role_id`, `permission_id`)
|
|
SELECT r.id, p.id FROM roles r CROSS JOIN permissions p
|
|
WHERE r.code = 'SUPER_ADMIN';
|