package handler import ( "encoding/json" "fmt" "net/http" "strconv" "aijianzhan/platform/internal/authx" "aijianzhan/platform/internal/logic/applogic" "aijianzhan/platform/internal/svc" "aijianzhan/platform/internal/userstore" "github.com/zeromicro/go-zero/rest/httpx" "github.com/zeromicro/go-zero/rest/pathvar" ) func platformListTenantsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx)) list, err := l.ListTenants() if err != nil { authx.WriteError(w, http.StatusForbidden, err.Error()) return } httpx.OkJson(w, map[string]any{"items": list}) } } func platformCreateTenantHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var body struct { Name string `json:"name"` Slug string `json:"slug"` AdminPhone string `json:"admin_phone"` WithAdminInvite *bool `json:"with_admin_invite"` } if err := json.NewDecoder(r.Body).Decode(&body); err != nil { authx.WriteError(w, http.StatusBadRequest, err.Error()) return } withInvite := false if body.WithAdminInvite != nil { withInvite = *body.WithAdminInvite } l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx)) res, err := l.CreateTenant(body.Name, body.Slug, withInvite, body.AdminPhone) if err != nil { authx.WriteError(w, http.StatusBadRequest, err.Error()) return } httpx.OkJson(w, res) } } func platformUpdateTenantHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64) var body struct { Name string `json:"name"` Slug string `json:"slug"` } if err := json.NewDecoder(r.Body).Decode(&body); err != nil { authx.WriteError(w, http.StatusBadRequest, err.Error()) return } l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx)) t, err := l.UpdateTenant(id, body.Name, body.Slug) if err != nil { authx.WriteError(w, http.StatusBadRequest, err.Error()) return } httpx.OkJson(w, t) } } func platformAdminInviteHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64) l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx)) inv, err := l.IssueAdminInvite(id) if err != nil { authx.WriteError(w, http.StatusBadRequest, err.Error()) return } httpx.OkJson(w, inv) } } func platformAdminAccountHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64) var body struct { Phone string `json:"phone"` } _ = json.NewDecoder(r.Body).Decode(&body) l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx)) acc, err := l.IssueAdminAccount(id, body.Phone) if err != nil { authx.WriteError(w, http.StatusBadRequest, err.Error()) return } _ = svcCtx.Audit.Log(r.Context(), id, authx.UserID(r.Context()), "platform.admin_account", acc.Username) httpx.OkJson(w, map[string]any{"admin_account": acc}) } } func platformListAdminsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64) l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx)) items, err := l.ListCompanyAdmins(id) if err != nil { authx.WriteError(w, http.StatusBadRequest, err.Error()) return } httpx.OkJson(w, map[string]any{"items": items}) } } func platformUpdateAdminHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { tid, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64) uid, _ := strconv.ParseInt(pathvar.Vars(r)["uid"], 10, 64) var body struct { ResetPassword *bool `json:"reset_password"` Password string `json:"password"` Phone *string `json:"phone"` DisableUsernameLogin *bool `json:"disable_username_login"` } if err := json.NewDecoder(r.Body).Decode(&body); err != nil { authx.WriteError(w, http.StatusBadRequest, err.Error()) return } reset := body.ResetPassword != nil && *body.ResetPassword if !reset && body.Phone == nil && body.DisableUsernameLogin == nil { authx.WriteError(w, http.StatusBadRequest, "请指定重置密码、更新手机号或禁用用户名登录") return } l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx)) acc, err := l.UpdateCompanyAdmin(tid, uid, reset, body.Password, body.Phone, body.DisableUsernameLogin) if err != nil { authx.WriteError(w, http.StatusBadRequest, err.Error()) return } _ = svcCtx.Audit.Log(r.Context(), tid, authx.UserID(r.Context()), "platform.update_admin", acc.Username) httpx.OkJson(w, map[string]any{"admin_account": acc}) } } func platformEnterTenantHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64) l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx)) resp, err := l.EnterTenant(id) if err != nil { authx.WriteError(w, http.StatusBadRequest, err.Error()) return } _ = svcCtx.Audit.Log(r.Context(), id, resp.UserID, "platform.enter_tenant", resp.Message) httpx.OkJson(w, resp) } } func platformExitTenantHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx)) resp, err := l.ExitTenant() if err != nil { authx.WriteError(w, http.StatusBadRequest, err.Error()) return } _ = svcCtx.Audit.Log(r.Context(), 0, resp.UserID, "platform.exit_tenant", resp.Message) httpx.OkJson(w, resp) } } func platformPermModulesHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if !authx.IsPlatformAdmin(authx.Role(r.Context())) { authx.WriteError(w, http.StatusForbidden, "需要超级管理员") return } httpx.OkJson(w, map[string]any{ "modules": authx.PermModules(), "catalog": authx.CompanyPermCatalog(), "platform": []string{authx.Perm管理租户}, }) } } func platformGetTenantPermsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64) l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx)) perms, err := l.GetTenantPerms(id) if err != nil { authx.WriteError(w, http.StatusBadRequest, err.Error()) return } httpx.OkJson(w, map[string]any{"tenant_id": id, "permissions": perms, "total": len(authx.CompanyPermCatalog())}) } } func platformSetTenantPermsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64) var body struct { Permissions []string `json:"permissions"` } if err := json.NewDecoder(r.Body).Decode(&body); err != nil { authx.WriteError(w, http.StatusBadRequest, err.Error()) return } l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx)) perms, err := l.SetTenantPerms(id, body.Permissions) if err != nil { authx.WriteError(w, http.StatusBadRequest, err.Error()) return } httpx.OkJson(w, map[string]any{"tenant_id": id, "permissions": perms, "total": len(authx.CompanyPermCatalog())}) } } func companyEntitlementsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { l := applogic.NewAuthLogic(r.Context(), svcCtx) perms, modules, err := l.CompanyEntitlements() if err != nil { authx.WriteError(w, http.StatusForbidden, err.Error()) return } httpx.OkJson(w, map[string]any{"permissions": perms, "modules": modules}) } } func memberListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { l := applogic.NewMemberLogic(applogic.NewAuthLogic(r.Context(), svcCtx)) list, err := l.List() if err != nil { authx.WriteError(w, http.StatusBadRequest, err.Error()) return } items := make([]map[string]any, 0, len(list)) for _, u := range list { items = append(items, map[string]any{ "user_id": u.UserID, "username": u.Username, "phone": u.Phone, "display_name": u.DisplayName, "role": u.Role, "org_unit_id": u.OrgUnitID, "status": u.Status, "created_at": u.CreatedAt, }) } httpx.OkJson(w, map[string]any{"items": items}) } } func memberCreateHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var body struct { Password string `json:"password"` DisplayName string `json:"display_name"` Role string `json:"role"` OrgUnitID int64 `json:"org_unit_id"` } if err := json.NewDecoder(r.Body).Decode(&body); err != nil { authx.WriteError(w, http.StatusBadRequest, err.Error()) return } l := applogic.NewMemberLogic(applogic.NewAuthLogic(r.Context(), svcCtx)) u, plain, err := l.Create(body.Password, body.DisplayName, body.Role, body.OrgUnitID) if err != nil { authx.WriteError(w, http.StatusBadRequest, err.Error()) return } _ = svcCtx.Audit.Log(r.Context(), authx.TenantID(r.Context()), authx.UserID(r.Context()), "member.create", "创建成员 "+u.Username) httpx.OkJson(w, map[string]any{ "user_id": u.UserID, "username": u.Username, "display_name": u.DisplayName, "role": u.Role, "org_unit_id": u.OrgUnitID, "status": u.Status, "password": plain, }) } } func memberUpdateHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64) var body struct { Role string `json:"role"` OrgUnitID int64 `json:"org_unit_id"` Status string `json:"status"` Phone *string `json:"phone"` // 传则绑定/更换;传 "" 解绑 } if err := json.NewDecoder(r.Body).Decode(&body); err != nil { authx.WriteError(w, http.StatusBadRequest, err.Error()) return } l := applogic.NewMemberLogic(applogic.NewAuthLogic(r.Context(), svcCtx)) var u *userstore.User var err error if body.Phone != nil { u, err = l.SetPhone(id, *body.Phone) if err != nil { authx.WriteError(w, http.StatusBadRequest, err.Error()) return } _ = svcCtx.Audit.Log(r.Context(), authx.TenantID(r.Context()), authx.UserID(r.Context()), "member.bind_phone", fmt.Sprintf("成员 #%d phone=%s", id, u.Phone)) } // 仅改手机时不必强制带 role/status;若其它字段有值则再 Update if body.Role != "" || body.Status != "" || body.OrgUnitID != 0 || body.Phone == nil { u, err = l.Update(id, body.Role, body.OrgUnitID, body.Status) if err != nil { authx.WriteError(w, http.StatusBadRequest, err.Error()) return } } if u == nil { authx.WriteError(w, http.StatusBadRequest, "nothing to update") return } httpx.OkJson(w, map[string]any{ "user_id": u.UserID, "username": u.Username, "phone": u.Phone, "display_name": u.DisplayName, "role": u.Role, "org_unit_id": u.OrgUnitID, "status": u.Status, }) } }