package service import ( "encoding/json" "github.com/jinzhu/gorm" "io/ioutil" "net/http" "net/url" "strconv" "time" "Xcx_New/models" "Xcx_New/utils" "fmt" "github.com/astaxie/beego" ) type AdminUserInfo struct { AdminUser *models.AdminUser `json:"user"` CurrentOrgId int64 `json:"current_org_id"` CurrentAppId int64 `json:"current_app_id"` OrgIds []int64 `json:"org_ids"` Orgs map[int64]*models.Org `json:"orgs"` OrgAppIds map[int64][]int64 `json:"org_app_ids"` OrgApps map[int64](map[int64]*models.OrgApp) `json:"org_apps"` App2OrgIds map[int64]int64 `json:"app_to_org_ids"` AppRoles map[int64]*models.App_Role `json:"app_roles"` AppPurviews map[int64][]*models.Purview `json:"app_purviews"` AppUrlfors map[int64][]string `json:"app_urlfors"` Subscibes map[int64]*models.ServeSubscibe `json:"org_subscibes"` } type verifyTokenError struct { Msg string } func (e *verifyTokenError) Error() string { return e.Msg } // 验证 token 成功后返回的管理员用户的所有信息,包括:基本用户信息,所属的所有机构,机构下的所有应用,应用的用户权限 // map 的数据格式为 /* "admin_user": { AdminUser's json }, current_org_id: 1, current_app_id: 11, "org_ids": [1, 2, 3], "orgs": { (org_id: Org_Obj) 1: { Org's json }, 2: { Org's json }, }, "org_app_ids": { (org_id: org_app_ids) 1: [11, 12, 13], 2: [21, 22, 23], }, "org_apps": { (org_id: {app_id: OrgApp_Obj}) 1: { 11: { OrgApp's json }, 12: { OrgApp's json }, }, 2: { 21: { OrgApp's json }, 22: { OrgApp's json }, }, }, "app_to_org_ids": { (app_id: org_id) 11: 1, 12: 1, 21: 2, 22: 2, }, "app_roles": { (app_id: App_Role Obj) 11: {App_Role's json}, 12: {App_Role's json}, 21: {App_Role's json}, }, "purviews": { (app_id: [processed Purviews' json]) 11: [ {Purview's json .childs[ {Purview's json}, {Purview's json}, ]}, {Purview's json}, ], 12: [ {Purview's json}, {Purview's json}, ], }, "purview_urlfors": { (app_id: [url_for]) 11: [ "Controller1.Action1", "Controller1.Action2", "Controller2.Action1", "Controller2.Action2", ], } 应当注意的是,屈服于 Golang 令人恶心的类型机制,这里将所有数值型的 key 或 value 全部转成了 string */ // 解析用户信息,并返回 func VerifyToken(token string, ip string, sessionID string) (*AdminUserInfo, error, int) { // if len(sessionID) == 0 { // return nil, &verifyTokenError{"sessionID 为空"} // } ssoDomain := beego.AppConfig.String("sso_domain") api := ssoDomain + "/verifytoken" values := make(url.Values) values.Set("token", token) values.Set("app_type", "3") values.Set("ip", ip) values.Set("session_id", sessionID) resp, requestErr := http.PostForm(api, values) if requestErr != nil { utils.ErrorLog("请求验证 sso token 接口失败: %v", requestErr) return nil, requestErr, 0 } defer resp.Body.Close() body, ioErr := ioutil.ReadAll(resp.Body) if ioErr != nil { utils.ErrorLog("验证 sso token 接口返回数据读取失败: %v", ioErr) return nil, ioErr, 0 } var respJSON map[string]interface{} if err := json.Unmarshal([]byte(string(body)), &respJSON); err != nil { utils.ErrorLog("验证 sso token 接口返回数据解析JSON失败: %v", err) return nil, err, 0 } if respJSON["state"].(float64) != 1 { msg := respJSON["msg"].(string) utils.ErrorLog("验证 sso token 接口请求失败: %v", msg) return nil, &verifyTokenError{"验证 sso token 接口请求失败"}, int(respJSON["code"].(float64)) } else { utils.SuccessLog("验证 sso token 成功") return processAdminUserInfo(respJSON["data"].(map[string]interface{})), nil, 0 } } func processAdminUserInfo(data map[string]interface{}) *AdminUserInfo { adminUser := processAdminUser(data) currentOrgId, currentAppId := processCurrentOrgIDAndAppID(data) orgIds := processOrgIds(data) orgs := processOrgs(data) orgAppIds := processOrgAppIds(data) orgApps := processOrgApps(data) //app2OrgIds := processApp2OrgIds(data) appRoles := processAppRoles(data) appPurviews := processPurviews(data) appUrlfors := processPurviewUrlfors(data) //orgSubscibes := processOrgSubscibes(data) sessionAdminUserInfo := &AdminUserInfo{ AdminUser: adminUser, CurrentOrgId: currentOrgId, CurrentAppId: currentAppId, OrgIds: orgIds, Orgs: orgs, OrgAppIds: orgAppIds, OrgApps: orgApps, //App2OrgIds: app2OrgIds, AppRoles: appRoles, AppPurviews: appPurviews, AppUrlfors: appUrlfors, //Subscibes: orgSubscibes, } return sessionAdminUserInfo } // "admin_user": { AdminUser's json }, func processAdminUser(data map[string]interface{}) *models.AdminUser { userJSONStr := data["admin_user"].(string) var adminUser models.AdminUser if err := json.Unmarshal([]byte(userJSONStr), &adminUser); err != nil { utils.ErrorLog("解析用户信息失败:%v", err) return nil } else { return &adminUser } } // current_org_id: 1, // current_app_id: 11, func processCurrentOrgIDAndAppID(data map[string]interface{}) (int64, int64) { orgIDStr := data["current_org_id"].(string) appIDStr := data["current_app_id"].(string) orgID, _ := strconv.Atoi(orgIDStr) appID, _ := strconv.Atoi(appIDStr) return int64(orgID), int64(appID) } // "org_ids": [1, 2, 3], func processOrgIds(data map[string]interface{}) []int64 { orgIdStrs := data["org_ids"].([]interface{}) orgIds := make([]int64, 0, len(orgIdStrs)) for _, idstr := range orgIdStrs { id, _ := strconv.Atoi(idstr.(string)) orgIds = append(orgIds, int64(id)) } return orgIds } // "orgs": { (org_id: Org_Obj) // 1: { Org's json }, // 2: { Org's json }, // }, func processOrgs(data map[string]interface{}) map[int64]*models.Org { orgJSONs := data["orgs"].(map[string]interface{}) orgs := make(map[int64]*models.Org) for orgIdStr, orgJSON := range orgJSONs { orgId, _ := strconv.Atoi(orgIdStr) var org models.Org json.Unmarshal([]byte(orgJSON.(string)), &org) orgs[int64(orgId)] = &org } return orgs } // "org_app_ids": { (org_id: org_app_ids) // 1: [11, 12, 13], // 2: [21, 22, 23], // }, func processOrgAppIds(data map[string]interface{}) map[int64][]int64 { orgAppIdStrs := data["org_app_ids"].(map[string]interface{}) orgAppIds := make(map[int64][]int64) for orgIdStr, appIdStrs := range orgAppIdStrs { orgId, _ := strconv.Atoi(orgIdStr) appIds := make([]int64, 0, len(appIdStrs.([]interface{}))) for _, appIdStr := range appIdStrs.([]interface{}) { appId, _ := strconv.Atoi(appIdStr.(string)) appIds = append(appIds, int64(appId)) } orgAppIds[int64(orgId)] = appIds } return orgAppIds } // "org_apps": { (org_id: {app_id: OrgApp_Obj}) // 1: { // 11: { OrgApp's json }, // 12: { OrgApp's json }, // }, // 2: { // 21: { OrgApp's json }, // 22: { OrgApp's json }, // }, // }, func processOrgApps(data map[string]interface{}) map[int64]map[int64]*models.OrgApp { orgAppJSONs := data["org_apps"].(map[string]interface{}) orgApps := make(map[int64]map[int64]*models.OrgApp) for orgIdStr, appJSONStrMap := range orgAppJSONs { orgId, _ := strconv.Atoi(orgIdStr) apps := make(map[int64]*models.OrgApp) for appIdStr, appJSONStr := range appJSONStrMap.(map[string]interface{}) { appId, _ := strconv.Atoi(appIdStr) var app models.OrgApp json.Unmarshal([]byte(appJSONStr.(string)), &app) apps[int64(appId)] = &app } orgApps[int64(orgId)] = apps } return orgApps } // "app_to_org_ids": { (app_id: org_id) // 11: 1, // 12: 1, // 21: 2, // 22: 2, // }, func processApp2OrgIds(data map[string]interface{}) map[int64]int64 { app2OrgIdStrs := data["app_to_org_ids"].(map[string]interface{}) app2OrgIds := make(map[int64]int64) for appIdStr, orgIdStr := range app2OrgIdStrs { orgId, _ := strconv.Atoi(orgIdStr.(string)) appId, _ := strconv.Atoi(appIdStr) app2OrgIds[int64(appId)] = int64(orgId) } return app2OrgIds } // "app_roles": { (app_id: App_Role Obj) // 11: {App_Role's json}, // 12: {App_Role's json}, // 21: {App_Role's json}, // }, func processAppRoles(data map[string]interface{}) map[int64]*models.App_Role { appRoleJSONs := data["app_roles"].(map[string]interface{}) appRoles := make(map[int64]*models.App_Role) for appIDStr, appRoleJSON := range appRoleJSONs { appID, _ := strconv.Atoi(appIDStr) var appRole models.App_Role json.Unmarshal([]byte(appRoleJSON.(string)), &appRole) appRoles[int64(appID)] = &appRole } return appRoles } // "purviews": { (app_id: [processed Purviews' json]) // 11: [ // {Purview's json .childs[ // {Purview's json}, // {Purview's json}, // ]}, // {Purview's json}, // ], // 12: [ // {Purview's json}, // {Purview's json}, // ], // }, func processPurviews(data map[string]interface{}) map[int64][]*models.Purview { appPurviewJSONsStrs := data["purviews"].(map[string]interface{}) appPurviews := make(map[int64][]*models.Purview) for appIdStr, purviewJSONsStr := range appPurviewJSONsStrs { appId, _ := strconv.Atoi(appIdStr) var purviews []*models.Purview json.Unmarshal([]byte(purviewJSONsStr.(string)), &purviews) // setLinkForPurviews(purviews) appPurviews[int64(appId)] = purviews } return appPurviews } // func setLinkForPurviews(purviews []*models.Purview) { // for _, purview := range purviews { // if len(purview.Urlfor) == 0 { // purview.Link = "" // } else { // purview.Link = beego.URLFor(purview.Urlfor) // } // if purview.Childs == nil { // purview.Childs = make([]*models.Purview, 0) // } else { // setLinkForPurviews(purview.Childs) // } // // utils.TraceLog("%+v", purview) // } // } // "purview_urlfors": { (app_id: [url_for]) // 11: [ // "Controller1.Action1", // "Controller1.Action2", // "Controller2.Action1", // "Controller2.Action2", // ], // } func processPurviewUrlfors(data map[string]interface{}) map[int64][]string { appUrlforsStrs := data["purview_urlfors"].(map[string]interface{}) appUrlfors := make(map[int64][]string) for appIdStr, urlforsStr := range appUrlforsStrs { appId, _ := strconv.Atoi(appIdStr) var urlfors []string json.Unmarshal([]byte(urlforsStr.(string)), &urlfors) appUrlfors[int64(appId)] = urlfors } return appUrlfors } // "org_subscibes": { (org_id: ServeSubscibe) // 11: {ServeSubscibe's json} // }, func processOrgSubscibes(data map[string]interface{}) map[int64]*models.ServeSubscibe { subscibeJSONs := data["org_subscibes"].(map[string]interface{}) subscibes := make(map[int64]*models.ServeSubscibe) for orgIDStr, subscibeJSON := range subscibeJSONs { orgID, _ := strconv.Atoi(orgIDStr) var subscibe models.ServeSubscibe json.Unmarshal([]byte(subscibeJSON.(string)), &subscibe) subscibes[int64(orgID)] = &subscibe } return subscibes } func ModifyPassword(adminID int64, password string) error { err := writeUserDb.Model(&models.AdminUser{}).Where("id = ? AND status = 1", adminID).Updates(map[string]interface{}{"password": password, "mtime": time.Now().Unix()}).Error return err } func GetPurviewById(ids string) ([]*models.Purview, error) { var originPurviews []*models.Purview getPurviewErr := readUserDb.Model(&models.Purview{}).Where(fmt.Sprintf("id in (%v) and status = 1", ids)).Order("listorder asc").Order("id asc").Find(&originPurviews).Error return originPurviews, getPurviewErr } func FindAdminUserIDA(id int64) (role models.App_Role, err error) { err = readUserDb.Model(&models.App_Role{}).Where("id = ?", id).First(&role).Error return } func GetSuperAdminUsersPurviewTreeAndUrlfors(appType int) ([]string, []*models.Purview, error) { originPurviews, getPurviewErr := getAllOriginPurviews(appType) if getPurviewErr != nil { return nil, nil, getPurviewErr } urlfors, processedPurviews := getUrlforsAndProcessPurviews2Tree(originPurviews) return urlfors, processedPurviews, nil } // 加工这些规则:树形化;以及从中取出不为空的 urlfor // 正确结果的前提是 originPurviews 以 parentid asc 排好序了的 func getUrlforsAndProcessPurviews2Tree(originPurviews []*models.Purview) ([]string, []*models.Purview) { processedPurviews := make([]*models.Purview, 0) pid_childs := make(map[int][]*models.Purview) urlfors := make([]string, 0, len(originPurviews)) for _, purview := range originPurviews { if len(purview.Urlfor) != 0 { urlfors = append(urlfors, purview.Urlfor) } // warning:下面这个算法只适用最多两层树形结构的菜单,对于两层以上的会丢失掉第三层及其以下的节点 // 因为取出 originPurviews 的时候已经排过序了,所以顶级节点肯定最先处理,不需要担心子节点比父节点先处理 if purview.Parentid == 0 { processedPurviews = append(processedPurviews, purview) } else { childs := pid_childs[int(purview.Parentid)] if pid_childs[int(purview.Parentid)] == nil { childs = make([]*models.Purview, 0) } childs = append(childs, purview) pid_childs[int(purview.Parentid)] = childs } } for _, proPurview := range processedPurviews { proPurview.Childs = pid_childs[int(proPurview.Id)] } return urlfors, processedPurviews } func getAllOriginPurviews(appType int) ([]*models.Purview, error) { var purviews []*models.Purview getPurviewErr := readUserDb.Model(models.Purview{}).Where("module = ? AND status = 1", appType).Order("listorder asc").Order("id asc").Find(&purviews).Error if getPurviewErr != nil { if getPurviewErr == gorm.ErrRecordNotFound { return nil, nil } else { return nil, getPurviewErr } } return purviews, nil }