// Package auth 统一认证中心(UAC)业务层。 // // 认证中心只负责「你是谁、你能进哪些企业、你能用哪些应用」, // 菜单/按钮/数据权限仍由各业务端自治。 package auth import ( "strings" "github.com/beego/beego/v2/client/orm" "server/models" ) // TenantOption 登录后可选择进入的企业(一人可在多家企业任职) type TenantOption struct { Tid uint64 `json:"tid"` TenantName string `json:"tenant_name"` Name string `json:"name"` GroupID uint64 `json:"group_id"` OrgID uint64 `json:"org_id"` IsDefault bool `json:"is_default"` } // IdentityProfile 认证中心视角的身份概要 type IdentityProfile struct { ID uint64 `json:"id"` UnionID string `json:"union_id"` Mobile string `json:"mobile"` Email string `json:"email"` Nickname string `json:"nickname"` Avatar string `json:"avatar"` Status int8 `json:"status"` MfaOn bool `json:"mfa_enabled"` Tenants []TenantOption `json:"tenants"` } // FindIdentityByAccount 按登录账号查找身份。 // 匹配顺序:手机号 → 邮箱 → 企业内账号(先查绑定再回查身份)。 func FindIdentityByAccount(account string) (*models.AuthIdentity, error) { account = strings.TrimSpace(account) if account == "" { return nil, orm.ErrNoRows } base := models.Orm.QueryTable(new(models.AuthIdentity)).Filter("delete_time__isnull", true) for _, field := range []string{"mobile", "email"} { m := &models.AuthIdentity{} if err := base.Filter(field, account).One(m); err == nil { return m, nil } } // 企业内账号:yz_auth_tenant_user.account → identity_id var bind models.AuthTenantUser if err := models.Orm.QueryTable(new(models.AuthTenantUser)). Filter("account", account). Filter("delete_time__isnull", true). OrderBy("-is_default", "id"). One(&bind); err == nil { m := &models.AuthIdentity{} if err := models.Orm.QueryTable(new(models.AuthIdentity)).Filter("id", bind.IdentityID).One(m); err == nil { return m, nil } } return nil, orm.ErrNoRows } // ListTenantOptions 列出该身份可登录的企业(过滤企业停用与绑定停用)。 func ListTenantOptions(identityID uint64) ([]TenantOption, error) { var binds []models.AuthTenantUser if _, err := models.Orm.QueryTable(new(models.AuthTenantUser)). Filter("identity_id", identityID). Filter("status", 1). Filter("delete_time__isnull", true). OrderBy("-is_default", "id"). All(&binds); err != nil { return nil, err } out := make([]TenantOption, 0, len(binds)) for _, b := range binds { var tenant models.SystemTenant if err := models.Orm.QueryTable(new(models.SystemTenant)). Filter("id", b.Tid). Filter("delete_time__isnull", true). One(&tenant); err != nil { continue // 租户不存在或已删除 } if tenant.Status != 1 { continue // 租户停用 } opt := TenantOption{ Tid: b.Tid, TenantName: strings.TrimSpace(tenant.TenantName), GroupID: b.GroupID, OrgID: b.OrgID, IsDefault: b.IsDefault == 1, } if b.Name != nil { opt.Name = strings.TrimSpace(*b.Name) } out = append(out, opt) } return out, nil } // GetTenantUser 获取身份在指定企业的绑定关系 func GetTenantUser(identityID, tid uint64) (*models.AuthTenantUser, error) { var bind models.AuthTenantUser err := models.Orm.QueryTable(new(models.AuthTenantUser)). Filter("identity_id", identityID). Filter("tid", tid). Filter("delete_time__isnull", true). One(&bind) if err != nil { return nil, err } return &bind, nil } // BuildProfile 组装身份概要(含可选企业列表) func BuildProfile(m *models.AuthIdentity) (*IdentityProfile, error) { tenants, err := ListTenantOptions(m.ID) if err != nil { return nil, err } p := &IdentityProfile{ ID: m.ID, UnionID: m.UnionID, Status: m.Status, MfaOn: m.MfaEnabled == 1, Tenants: tenants, } if m.Mobile != nil { p.Mobile = *m.Mobile } if m.Email != nil { p.Email = *m.Email } if m.Nickname != nil { p.Nickname = *m.Nickname } if m.Avatar != nil { p.Avatar = *m.Avatar } return p, nil }