168 lines
4.8 KiB
Go
168 lines
4.8 KiB
Go
// 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
|
|
}
|
|
|
|
// FindIdentityIDByAccount 按「企业 + 账号」查找认证中心身份ID。
|
|
// 账号可以是企业内账号、手机号或邮箱(老登录入口按账号登录时使用)。
|
|
func FindIdentityIDByAccount(tid uint64, account string) uint64 {
|
|
account = strings.TrimSpace(account)
|
|
if tid == 0 || account == "" {
|
|
return 0
|
|
}
|
|
base := models.Orm.QueryTable(new(models.AuthTenantUser)).
|
|
Filter("tid", tid).
|
|
Filter("delete_time__isnull", true)
|
|
var bind models.AuthTenantUser
|
|
for _, field := range []string{"account", "phone", "email"} {
|
|
if err := base.Filter(field, account).One(&bind); err == nil {
|
|
return bind.IdentityID
|
|
}
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// 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
|
|
}
|