feat(auth): 微信登录自动分配 patient 角色 + 创建患者档案
- 新增迁移 m20260510_000133:为所有租户创建 patient 角色并分配 19 个权限 - wechat_service: bind_phone 自动 assign_patient_role + ensure_patient_record - find_or_create_user_by_phone 新用户自动获得 patient 角色和患者档案 - 小程序 auth store: bindPhone 抛出异常而非静默返回 false - 小程序登录页: 捕获绑定错误并显示可操作的对话框
This commit is contained in:
@@ -134,6 +134,7 @@ mod m20260507_000129_fix_nurse_operator_points_permissions;
|
||||
mod m20260508_000130_fix_operator_permissions_and_nurse_devices;
|
||||
mod m20260508_000131_fix_all_role_permissions;
|
||||
mod m20260508_000132_fix_doctor_permissions_restore;
|
||||
mod m20260510_000133_create_patient_role;
|
||||
|
||||
pub struct Migrator;
|
||||
|
||||
@@ -275,6 +276,7 @@ impl MigratorTrait for Migrator {
|
||||
Box::new(m20260508_000130_fix_operator_permissions_and_nurse_devices::Migration),
|
||||
Box::new(m20260508_000131_fix_all_role_permissions::Migration),
|
||||
Box::new(m20260508_000132_fix_doctor_permissions_restore::Migration),
|
||||
Box::new(m20260510_000133_create_patient_role::Migration),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
use sea_orm_migration::prelude::*;
|
||||
|
||||
#[derive(DeriveMigrationName)]
|
||||
pub struct Migration;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl MigrationTrait for Migration {
|
||||
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
let db = manager.get_connection();
|
||||
let sys = "00000000-0000-0000-0000-000000000000";
|
||||
|
||||
// Part 1: 为所有租户创建 patient 角色(幂等)
|
||||
db.execute_unprepared(&format!(
|
||||
"INSERT INTO roles (id, tenant_id, name, code, description, is_system, created_at, updated_at, created_by, updated_by, deleted_at, version) \
|
||||
SELECT gen_random_uuid(), t.id, '患者', 'patient', '小程序患者用户,可查看自身健康数据、积分、咨询等', false, NOW(), NOW(), '{sys}', '{sys}', NULL, 1 \
|
||||
FROM tenant t \
|
||||
WHERE NOT EXISTS (SELECT 1 FROM roles r WHERE r.tenant_id = t.id AND r.code = 'patient' AND r.deleted_at IS NULL)"
|
||||
)).await?;
|
||||
|
||||
// Part 2: 为 patient 角色分配小程序所需权限
|
||||
let patient_perms: &[&str] = &[
|
||||
// 健康数据
|
||||
"health.health-data.list",
|
||||
// 患者自身
|
||||
"health.patient.list",
|
||||
// 预约
|
||||
"health.appointment.list",
|
||||
// 随访
|
||||
"health.follow-up.list",
|
||||
// 咨询
|
||||
"health.consultation.list",
|
||||
// 积分
|
||||
"health.points.list",
|
||||
// 文章
|
||||
"health.articles.list",
|
||||
// 告警(自身)
|
||||
"health.alerts.list",
|
||||
// 日常监测
|
||||
"health.daily-monitoring.list",
|
||||
// 设备数据
|
||||
"health.device-readings.list",
|
||||
// 设备绑定
|
||||
"health.devices.list",
|
||||
// 知情同意
|
||||
"health.consent.list",
|
||||
// 用药记录
|
||||
"health.medication-records.list",
|
||||
// 药物提醒
|
||||
"health.medication-reminders.list",
|
||||
// 护理计划
|
||||
"health.care-plan.list",
|
||||
// AI 建议
|
||||
"ai.suggestion.list",
|
||||
// 消息
|
||||
"message.list",
|
||||
// 透析
|
||||
"health.dialysis.list",
|
||||
];
|
||||
|
||||
assign_perms_by_codes(db, "patient", patient_perms).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
let db = manager.get_connection();
|
||||
|
||||
// 删除 patient 角色的权限关联
|
||||
db.execute_unprepared(
|
||||
"DELETE FROM role_permissions WHERE role_id IN (SELECT id FROM roles WHERE code = 'patient')"
|
||||
).await?;
|
||||
|
||||
// 软删除 patient 角色
|
||||
db.execute_unprepared(
|
||||
"UPDATE roles SET deleted_at = NOW() WHERE code = 'patient' AND deleted_at IS NULL",
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
async fn assign_perms_by_codes(
|
||||
db: &sea_orm_migration::prelude::SchemaManagerConnection<'_>,
|
||||
role_code: &str,
|
||||
perm_codes: &[&str],
|
||||
) -> Result<(), DbErr> {
|
||||
let codes_csv: String = perm_codes
|
||||
.iter()
|
||||
.map(|c| format!("'{}'", c))
|
||||
.collect::<Vec<_>>()
|
||||
.join(",");
|
||||
|
||||
db.execute_unprepared(&format!(
|
||||
"INSERT INTO role_permissions (role_id, permission_id, tenant_id, data_scope, created_at, updated_at, created_by, updated_by, deleted_at, version) \
|
||||
SELECT r.id, p.id, r.tenant_id, 'self', NOW(), NOW(), r.id, r.id, NULL, 1 \
|
||||
FROM roles r \
|
||||
JOIN permissions p ON p.tenant_id = r.tenant_id AND p.code IN ({codes_csv}) AND p.deleted_at IS NULL \
|
||||
WHERE r.code = '{role_code}' AND r.deleted_at IS NULL \
|
||||
ON CONFLICT (role_id, permission_id) WHERE deleted_at IS NULL \
|
||||
DO UPDATE SET deleted_at = NULL, version = role_permissions.version + 1, updated_at = NOW()"
|
||||
)).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user