package bo import ( "crypto/md5" "errors" "fmt" "log" "regexp" "rtzh_elec_temperature/enum" "rtzh_elec_temperature/global" "rtzh_elec_temperature/logger" "rtzh_elec_temperature/tools" "strconv" "strings" "sync" "time" "github.com/astaxie/beego/orm" _ "github.com/astaxie/beego/orm" ) type T_data_usersession struct { Sessionid string `orm:"pk"` Userid int Lastdt int64 } type T_data_role_func struct { Id int `orm:"pk"` Roleid int Funccodeid int } func init() { orm.RegisterModel(new(T_data_usersession)) orm.RegisterModel(new(T_data_role_func)) } var tokenSync sync.RWMutex //缓存token对应的用户信息 var CacheUserByToken = map[string]interface{}{} //登录信息记录 var LoginInfo = sync.Map{} //保存角色-功能 func SaveRoleFunc(roleid int, funclist []string, userinfo map[string]interface{}) error { o := orm.NewOrm() sql := "delete from t_data_role_func where roleid=?" _, err := o.Raw(sql, roleid).Exec() if err != nil { log.Println(err) return err } for _, item := range funclist { intitem, _ := strconv.Atoi(item) obj := T_data_role_func{Roleid: roleid, Funccodeid: intitem} _, err = o.Insert(&obj) if err != nil { log.Println(err) } } dblog := new(SystemLog) dblog.UserInfo = userinfo dblog.Audittype = enum.AuditType_admin_system_userrole dblog.Logtype = enum.LogType_bind dblog.Eventtype = enum.OptEventType_Bus dblog.Eventlevel = enum.OptEventLevel_Hight if err != nil { dblog.Description = fmt.Sprintf("角色%d权限分配失败:%s", roleid, err.Error()) dblog.Fail2() return err } dblog.Description = fmt.Sprintf("角色%d权限分配成功", roleid) dblog.Success2() return nil } func GetRoleFunc(roleid int) (data []orm.Params, err error) { o := orm.NewOrm() lst := []orm.Params{} sql := "select a.*,b.code,b.name,b.parentcode from t_data_role_func a,global_const_code b where a.funccodeid=b.id and a.roleid=?" _, err = o.Raw(sql, roleid).Values(&lst) return lst, err } func GetUserFunc(userid int) (data interface{}, err error) { o := orm.NewOrm() lst := []orm.Params{} checkSuperSql := "select 1 from t_data_user where id=? and role=(select id from global_const_code where code='role_superadmin')" _, err = o.Raw(checkSuperSql, userid).Values(&lst) if len(lst) > 0 { //超级管理员,返回所有功能菜单 para := map[string]interface{}{"code": "all"} return []interface{}{para}, nil } sql := "select b.code,b.name,case when substr(b.code,1,8)='pl_menu_' then (select code from global_const_code where parentcode=b.code and name='url') else '' end url from t_data_role_func a,global_const_code b,t_data_user c where a.roleid=c.role and a.funccodeid=b.id and c.id=?" _, err = o.Raw(sql, userid).Values(&lst) return lst, err } func GetSessionInfo(sessionid string) (userinfo T_data_usersession, err error) { o := orm.NewOrm() obj := T_data_usersession{Sessionid: sessionid} err = o.Read(&obj) if err != nil { return T_data_usersession{}, err } userinfo.Sessionid = obj.Sessionid userinfo.Userid = obj.Userid userinfo.Lastdt = obj.Lastdt return obj, nil } func RemoveSession(sessionid string) error { if sessionid == "" { return nil } o := orm.NewOrm() obj := T_data_usersession{Sessionid: sessionid} _, err := o.Delete(&obj) global.GoCahce.Delete(sessionid) return err } //session续期。超时10分钟则自动过期,需要重新登录认证 func UpdateSession(sessionid string) error { if _, has := global.GoCahce.Get(sessionid); has { return nil } uinfo, err := GetSessionInfo(sessionid) if err != nil { return err } lastdt := uinfo.Lastdt //fmt.Println(uinfo) //fmt.Println(time.Now().Unix()) if global.SessionTimeout > 0 { if (time.Now().Unix() - lastdt) > int64(global.SessionTimeout) { return errors.New("session超时") } } global.GoCahce.Set(sessionid, uinfo, 30*time.Second) uid := uinfo.Userid return SetSession(sessionid, strconv.Itoa(uid)) } func SetSession(sessionid string, userid string) error { o := orm.NewOrm() uid, _ := strconv.Atoi(userid) obj := T_data_usersession{Sessionid: sessionid, Userid: uid, Lastdt: time.Now().Unix()} u, er := GetSessionInfo(sessionid) if er != nil && er != orm.ErrNoRows { return er } if u.Sessionid != "" { _, er = o.Update(&obj) } else { _, er = o.Insert(&obj) } return nil } //根据token返回当前登录用户信息 func GetUserInfoByToken(token string) (info map[string]interface{}, err error) { tokenSync.Lock() if v, ok := CacheUserByToken[token]; ok { tokenSync.Unlock() return v.(map[string]interface{}), nil } tokenSync.Unlock() o := orm.NewOrm() sql := "select a.*,b.name,b.account,b.role from t_data_usersession a,t_data_user b where a.userid=b.id and a.sessionid=?" obj := []orm.Params{} _, dberr := o.Raw(sql, token).Values(&obj) if dberr != nil { return nil, dberr } if len(obj) == 0 { return nil, nil } returninfo := make(map[string]interface{}) for k, v := range obj[0] { returninfo[k] = v } tokenSync.Lock() //检查缓存长度,key过大则清除一次 if len(CacheUserByToken) > 1000 { CacheUserByToken = make(map[string]interface{}) } CacheUserByToken[token] = returninfo tokenSync.Unlock() return returninfo, nil } func CacheLoginFialInfo(key string) { if info, ok := LoginInfo.Load(key); ok { //失败次数 info2 := info.(map[string]interface{}) failcount := info2["count"].(int) info2["count"] = failcount + 1 info2["lasttime"] = time.Now().Unix() } else { LoginInfo.Store(key, map[string]interface{}{"count": 1, "lasttime": time.Now().Unix()}) } } //加载全局参数 func LoadGlobalParam() { v, err := GetSysParamValue("session_timeout", "600") if err != nil { tools.Log("加载Session超时时长参数失败:" + err.Error()) return } global.SessionTimeout, _ = strconv.Atoi(v) } //加载并检查系统管理员帐号 func CheckSystemUser() (exists bool, err error) { o := orm.NewOrm() data := []orm.Params{} result := false sqlCommandText := "select 1 from t_data_user where account=?;" _, dbError := o.Raw(sqlCommandText, "Administrator").Values(&data) if dbError == nil { if len(data) == 0 { parameter := map[string]interface{}{} parameter["userid"] = "0" parameter["username"] = "Administrator" parameter["account"] = "Administrator" parameter["password"] = "administrator@123" parameter["role"] = 1 parameter["memo"] = "系统超级管理员" result, dbError = CreateUser(parameter) if dbError != nil { return false, dbError } else { result = true } } else { result = true } } return result, dbError } func UserLogin(account string, pwd string) (userinfo map[string]interface{}, err error) { o := orm.NewOrm() data := []orm.Params{} var result = map[string]interface{}{} has := md5.Sum([]byte(pwd)) pwd = fmt.Sprintf("%x", has) sqlCommandText := "select a.*,b.name userrole,b.code rolecode from t_data_user a left join global_const_code b on a.role=b.id where a.account=? and a.pwd=?" _, dbError := o.Raw(sqlCommandText, account, pwd).Values(&data) if dbError == nil { if len(data) > 0 { //判断密码是否过期 pwd_expire := tools.IsEmpty(data[0]["pwd_expire"]) if tools.IsEmpty(data[0]["rolecode"]) != "role_superadmin" && pwd_expire != "" && pwd_expire != "1970-01-01 00:00:00" { //判断是否过期 expireDate, _ := time.Parse("2006-01-02 15:04:05", pwd_expire) if expireDate.Unix() < time.Now().Unix() { logger.Logger.Debug(data) return result, errors.New("您的密码已过期,请联系管理员更新后重试!") } } LoginInfo.Store(account, map[string]interface{}{"count": 1, "lasttime": time.Now().Unix()}) result["userid"] = tools.IsEmpty(data[0]["id"]) result["name"] = tools.IsEmpty(data[0]["name"]) result["role"] = tools.IsEmpty(data[0]["role"]) result["bind_ips"] = tools.IsEmpty(data[0]["bind_ips"]) result["datelimit_start"] = tools.IsEmpty(data[0]["datelimit_start"]) result["datelimit_end"] = tools.IsEmpty(data[0]["datelimit_end"]) result["rolename"] = tools.IsEmpty(data[0]["userrole"]) return result, nil } else { CacheLoginFialInfo(account) return result, errors.New("用户帐号或密码错误!") } } else { return result, dbError } } //创建用户信息 func CreateUser(parameter map[string]interface{}, userinfo ...map[string]interface{}) (status bool, errs error) { userData := T_data_user{} o := orm.NewOrm() var paramvalues = []interface{}{} var userid int var Account string var modify_password = true //sqlCommandText := "" if userId, ok2 := parameter["userid"]; ok2 && tools.IsEmpty(userId) != "" { userid, _ = strconv.Atoi(userId.(string)) userData.Id = userid o.Read(&userData) } dblog := new(SystemLog) dblog.Audittype = enum.AuditType_admin_system_user dblog.Logtype = enum.LogType_Insert dblog.Eventtype = enum.OptEventType_Bus dblog.Eventlevel = enum.OptEventLevel_Hight if len(userinfo) > 0 { dblog.UserInfo = userinfo[0] userData.Createuser, _ = strconv.Atoi(tools.IsEmpty(userinfo[0]["userid"])) } else { dblog.UserInfo = map[string]interface{}{"name": "", "ip": "127.0.0.1"} } if username, ok2 := parameter["username"]; ok2 { if tools.IsEmpty(username) != "" { paramvalues = append(paramvalues, username) } else { dblog.Description = fmt.Sprintf("保存用户信息失败|%s,错误:%s", "", "用户姓名为空") dblog.Fail2() return false, errors.New("用户姓名字段不允许为空!") } userData.Name = tools.IsEmpty(username) } else { return false, errors.New("请传入用户姓名参数!") } if account, ok2 := parameter["account"]; ok2 { if tools.IsEmpty(account) != "" { paramvalues = append(paramvalues, account) } else { dblog.Description = fmt.Sprintf("保存用户信息失败|%s,错误:%s", parameter["username"], "用户帐号为空") dblog.Fail2() return false, errors.New("用户帐号字段不允许为空!") } userData.Account = tools.IsEmpty(account) } else { dblog.Description = fmt.Sprintf("保存用户信息失败|%s,错误:%s", parameter["username"], "未设置用户帐号") dblog.Fail2() return false, errors.New("请传入用户帐号参数!") } if password, ok2 := parameter["password"]; ok2 { passwordStr := tools.IsEmpty(password) if passwordStr != "" { if len(passwordStr) > 20 { password = tools.OriginalCode(password) } //密码规则校验 rule, _ := GetSysParamValue("user_pwd_rule", "simple") if rule == "simple" { if len(passwordStr) < 6 || len(passwordStr) > 32 { dblog.Description = fmt.Sprintf("保存用户信息失败|%s,错误:%s", parameter["username"], "用户帐号密码长度只能为6-32位字符") dblog.Fail2() return false, errors.New("用户帐号密码长度只能为6-32位字符!") } } else { if len(passwordStr) < 8 || len(passwordStr) > 32 { dblog.Description = fmt.Sprintf("保存用户信息失败|%s,错误:%s", parameter["username"], "用户帐号密码长度只能为8-32位字符") dblog.Fail2() return false, errors.New("用户帐号密码长度只能为8-32位字符!") } reg1, _ := regexp.Compile("[A-Z]") reg2, _ := regexp.Compile("[a-z]") reg3, _ := regexp.Compile("[0-9]") reg4, _ := regexp.Compile(`[~!@#$%^&*()_\-+=<>?:"{}|,.\/;'\\[\]·~!@#¥%&*]`) if !reg1.MatchString(passwordStr) || !reg2.MatchString(passwordStr) || !reg3.MatchString(passwordStr) || !reg4.MatchString(passwordStr) { dblog.Description = fmt.Sprintf("保存用户信息失败|%s,错误:%s", parameter["username"], "用户帐号密码长度只能为8-32位字符且由大小写字母、数字和特殊字符组成") dblog.Fail2() return false, errors.New("用户帐号密码长度只能为8-32位字符且由大小写字母、数字和特殊字符组成!") } } has := md5.Sum([]byte(passwordStr)) password = fmt.Sprintf("%x", has) paramvalues = append(paramvalues, password) modify_password = true userData.Pwd = tools.IsEmpty(password) } else if userid == 0 { dblog.Description = fmt.Sprintf("保存用户信息失败|%s,错误:%s", parameter["username"], "帐号密码为空") dblog.Fail2() return false, errors.New("用户帐号密码不允许为空!") } else { modify_password = false } } else { dblog.Description = fmt.Sprintf("保存用户信息失败|%s,错误:%s", parameter["username"], "未设置帐号密码") dblog.Fail2() return false, errors.New("请传入用户密码参数!") } if memo, ok2 := parameter["memo"]; ok2 { paramvalues = append(paramvalues, memo) userData.Memo = tools.IsEmpty(memo) } else { paramvalues = append(paramvalues, "") } if role, ok2 := parameter["role"]; ok2 { paramvalues = append(paramvalues, role) userData.Role, _ = strconv.Atoi(tools.IsEmpty(role)) } else { paramvalues = append(paramvalues, 0) } if mbphone, ok2 := parameter["mobilephone"]; ok2 { paramvalues = append(paramvalues, mbphone) userData.Mobilephone = tools.IsEmpty(mbphone) } else { paramvalues = append(paramvalues, "") } if ips, ok2 := parameter["bind_ips"]; ok2 { paramvalues = append(paramvalues, ips) userData.BindIps = tools.IsEmpty(ips) } else { paramvalues = append(paramvalues, "") } //判断用户是否存在 message := existsUser(userid, Account) if message != nil { dblog.Description = fmt.Sprintf("保存用户信息失败|%s,错误:%s", parameter["username"], message) dblog.Fail2() return false, message } if modify_password { //密码过期时间:单位天 pwd_expire_day, _ := GetSysParamValue("user_pwd_expire_day", "60") pwd_expire_date := "" if pwd_expire_day == "0" { //永不过期 pwd_expire_date = "1970-01-01 00:00:00" } else { pwd_expire_dayInt, _ := strconv.Atoi(pwd_expire_day) pwd_expire_dayInt = pwd_expire_dayInt * 24 d, _ := time.ParseDuration(strconv.Itoa(pwd_expire_dayInt) + "h") pwd_expire_date = time.Now().Add(d).Format("2006-01-02 15:04:05") } paramvalues = append(paramvalues, pwd_expire_date) userData.PwdExpire = pwd_expire_date } if v, ok2 := parameter["datelimit_start"]; ok2 { userData.DatelimitStart = tools.IsEmpty(v) } if v, ok2 := parameter["datelimit_end"]; ok2 { userData.DatelimitEnd = tools.IsEmpty(v) } var err error if userid > 0 { //判断修改用户信息时是否修改了密码 /*if modify_password { sqlCommandText = "update t_data_user set name=?,account=?,pwd=?,memo=?,role=?,mobilephone=?,bind_ips=?,pwd_expire=? where id=?" } else { sqlCommandText = "update t_data_user set name=?,account=?,memo=?,role=?,mobilephone=?,bind_ips=? where id=?" } paramvalues = append(paramvalues, userid) */ _, err = o.Update(&userData) } else { //sqlCommandText = "insert into t_data_user(name,account,pwd,memo,role,mobilephone,bind_ips,pwd_expire)values(?,?,?,?,?,?,?);" _, err = o.Insert(&userData) } //_, err := o.Raw(sqlCommandText, paramvalues).Exec() if err != nil { logger.Logger.Error(err) dblog.Description = fmt.Sprintf("保存用户信息失败|%s,错误:%s", parameter["username"], err.Error()) dblog.Fail2() return false, err } else { dblog.Description = fmt.Sprintf("保存用户信息成功|%s", parameter["username"]) dblog.Success2() return true, nil } } //初始化用户表 func InitUser() (status bool, errs error) { o := orm.NewOrm() sqlCommandText := "delete from t_data_user where name!=?" _, err := o.Raw(sqlCommandText, "Rtelec").Exec() if err != nil { return false, err } else { o.Raw("delete from t_data_usersession").Exec() return true, nil } } //删除用户 func DelUser(userId string, userinfo map[string]interface{}) (status bool, errs error) { dblog := new(SystemLog) dblog.UserInfo = userinfo dblog.Audittype = enum.AuditType_admin_system_user dblog.Logtype = enum.LogType_Delete dblog.Eventtype = enum.OptEventType_Bus dblog.Eventlevel = enum.OptEventLevel_Hight o := orm.NewOrm() sqlCommandText := "delete from t_data_user where id=?" _, err := o.Raw(sqlCommandText, userId).Exec() if err != nil { dblog.Description = fmt.Sprintf("删除用户%s失败,错误:%s", userId, err.Error()) dblog.Fail2() return false, err } else { //删除该用户的关联区域信息 usArea := new(UserAreaRelationObject) usArea.UserInfo = userinfo usArea.Model.Userid, _ = strconv.Atoi(userId) usArea.Delete() dblog.Description = fmt.Sprintf("删除用户%s成功", userId) dblog.Success2() return true, nil } } func existsUser(userId int, account string) error { ts := []orm.Params{} o := orm.NewOrm() var parameter = []interface{}{} sqlCommandText := "" if userId > 0 { sqlCommandText = "select 1 from t_data_user where account=? and id!=?" parameter = append(parameter, account, userId) } else { sqlCommandText = "select 1 from t_data_user where account=? " parameter = append(parameter, account) } _, err := o.Raw(sqlCommandText, parameter).Values(&ts) if err != nil { return err } if len(ts) > 0 { return errors.New("已存在用户帐号:" + account) } else { return nil } } func SearchUserInfo(area_id, name, role_id string, pageIndex, pageSize int, userinfo map[string]interface{}) ([]orm.Params, int, error) { dblog := new(SystemLog) dblog.UserInfo = userinfo dblog.Audittype = enum.AuditType_admin_system_user dblog.Logtype = enum.LogType_Query dblog.Eventtype = enum.OptEventType_Bus dblog.Eventlevel = enum.OptEventLevel_Low o := orm.NewOrm() var sqlCommandText, totalSql string sqlCommandText = "select a.*,b.name rolename,b.code rolecode,(select ifnull(count(1),0) from t_relation_user_area where userid=a.id and areaid>0)area_count from t_data_user a left join global_const_code b on a.role=b.id where " sqlWhere := []string{"1=1"} sqlParamer := []interface{}{} sqlWhere = append(sqlWhere, " not EXISTS (select 1 from global_const_code where a.role=id and code='role_superadmin')") var limit = " limit " + strconv.Itoa((pageIndex-1)*pageSize) + "," + strconv.Itoa(pageSize) if role_id != "" { sqlWhere = append(sqlWhere, " a.role=?") sqlParamer = append(sqlParamer, role_id) } if name != "" { sqlWhere = append(sqlWhere, " a.name like ?") sqlParamer = append(sqlParamer, "%"+name+"%") } if area_id != "" { sqlWhere = append(sqlWhere, " EXISTS(select 1 from t_relation_user_area ua where a.id=ua.userid and ua.areaid=?)") sqlParamer = append(sqlParamer, area_id) } sqlCommandText += strings.Join(sqlWhere, " and ") sqlCommandText += " order by a.id desc " + limit totalSql = "select count(1) number from t_data_user a where " + strings.Join(sqlWhere, " and ") var tableData []orm.Params var number int _, err := o.Raw(sqlCommandText, sqlParamer).Values(&tableData) dblog.Description = fmt.Sprintf("SQL:%s,参数:%+v", sqlCommandText, sqlParamer) if err == nil { dblog.Success2() var totalData []orm.Params _, err = o.Raw(totalSql, sqlParamer).Values(&totalData) if err == nil { number, _ = strconv.Atoi(totalData[0]["number"].(string)) } } else { logger.Logger.Error(err, dblog.Description) dblog.Fail2() } return tableData, number, err }