zjxpcyc 6 anni fa
parent
commit
93a8f39d8f
10 ha cambiato i file con 329 aggiunte e 57 eliminazioni
  1. 4
    0
      conf/log.conf
  2. 117
    35
      controllers/auth.go
  3. 3
    0
      controllers/session.go
  4. 1
    1
      controllers/types.go
  5. 0
    0
      log/common.log
  6. 13
    0
      models/constant.go
  7. 65
    15
      models/sys.go
  8. 35
    2
      service/sys.go
  9. 68
    4
      utils/log.go
  10. 23
    0
      utils/wechat.go

+ 4
- 0
conf/log.conf Vedi File

1
+[common]
2
+filename="E:\\GoProjects\\src\\spaceofcheng\\services\\log\\common.log"
3
+# log level "emergency", "alert", "critical", "error", "warning", "notice", "info", "debug"
4
+level="debug"

+ 117
- 35
controllers/auth.go Vedi File

3
 import (
3
 import (
4
 	"errors"
4
 	"errors"
5
 	"net/http"
5
 	"net/http"
6
+	"spaceofcheng/services/models/model"
6
 	"spaceofcheng/services/service"
7
 	"spaceofcheng/services/service"
7
 	"spaceofcheng/services/utils"
8
 	"spaceofcheng/services/utils"
8
 	"strings"
9
 	"strings"
12
 
13
 
13
 // Authenticate 权限验证
14
 // Authenticate 权限验证
14
 func (c *BaseController) authenticate() {
15
 func (c *BaseController) authenticate() {
15
-	if !c.needAuth() {
16
-		return
17
-	}
18
-
19
 	// 默认 service
16
 	// 默认 service
20
 	serv := service.NewSysServ(c.Context)
17
 	serv := service.NewSysServ(c.Context)
21
 
18
 
19
+	// 客户端类型
20
+	clientType := utils.GetClientType(c.Ctx.Request)
21
+
22
 	// 用户类型, 此处与数据库定义的不是一个概念
22
 	// 用户类型, 此处与数据库定义的不是一个概念
23
 	// 此处主要用来区分是 系统用户, 还是 系统客户
23
 	// 此处主要用来区分是 系统用户, 还是 系统客户
24
-	userType := c.GetSession(SNUserType).(string)
24
+	userType := UserGuest
25
+	userTypeRaw := c.GetSession(SNUserType)
26
+	if userTypeRaw != nil {
27
+		userType = userTypeRaw.(string)
28
+	}
29
+
30
+	// 用户类型不同, 此处ID代表的内容也是不一样的
31
+	userID := ""
32
+	userIDRaw := c.GetSession(SNUserID)
33
+	if userIDRaw != nil {
34
+		userID = userIDRaw.(string)
35
+	}
36
+
37
+	// 用户映射表
38
+	var userMap *model.TaUserMapping
39
+
40
+	if clientType == utils.ClientWechat && userID == "" {
41
+		var err error
42
+		userMap, err = c.checkWechat(serv)
43
+		if err != nil {
44
+			utils.LogError("获取并校验微信信息失败: " + err.Error())
45
+		}
46
+
47
+		c.SetSession("openid", userMap.Openid)
48
+	}
49
+
50
+	if !c.needAuth() {
51
+		return
52
+	}
25
 
53
 
26
 	// 如果是普通游客, 暂时没有任何设置
54
 	// 如果是普通游客, 暂时没有任何设置
27
 	if userType == UserGuest {
55
 	if userType == UserGuest {
28
 		return
56
 		return
29
 	}
57
 	}
30
 
58
 
31
-	// 客户端类型
32
-	clientType := utils.GetClientType(c.Ctx.Request)
33
-
34
-	// 用户类型不同, 此处ID代表的内容也是不一样的
35
-	userID, _ := c.GetSession(SNUserID).(string)
59
+	// 如果存在用户映射
60
+	mapUserID := c.getUserIDByUserMap(userMap, userID, userType)
61
+	if mapUserID != "" {
62
+		userID = mapUserID
63
+	}
36
 
64
 
37
 	// 未登录状态
65
 	// 未登录状态
38
 	if userID == "" {
66
 	if userID == "" {
39
 		if clientType == utils.ClientWechat {
67
 		if clientType == utils.ClientWechat {
40
-			if err := c.getWechatInfo(); err != nil {
41
-				wxConf, ok := c.Configer[WeChatConf]
42
-				if ok {
43
-					utils.LogError("获取微信信息失败: " + err.Error())
44
-
45
-					c.ResponseData(
46
-						map[string]interface{}{
47
-							"appid": wxConf.String("appid"),
48
-						},
49
-						errors.New("用户未登录"),
50
-						http.StatusUnauthorized,
51
-					)
52
-				} else {
53
-					c.ResponseError(
54
-						errors.New("用户未登录"),
55
-						http.StatusUnauthorized,
56
-					)
57
-				}
68
+			wxConf, ok := c.Configer[WeChatConf]
69
+			if ok {
70
+				c.ResponseData(
71
+					map[string]interface{}{
72
+						"appid": wxConf.String("appid"),
73
+					},
74
+					errors.New("用户未登录"),
75
+					http.StatusUnauthorized,
76
+				)
77
+			} else {
78
+				c.ResponseError(
79
+					errors.New("用户未登录"),
80
+					http.StatusUnauthorized,
81
+				)
58
 			}
82
 			}
59
 		} else {
83
 		} else {
60
 			c.ResponseError(
84
 			c.ResponseError(
64
 		}
88
 		}
65
 	}
89
 	}
66
 
90
 
91
+	// 设置 Session
92
+	c.SetSession(SNUserID, userID)
93
+	c.SetSession(SNUserType, userType)
94
+
67
 	var err error
95
 	var err error
68
-	if clientType == utils.ClientAdmin {
96
+
97
+	// 设置 Context
98
+	// 放到 serv 的方法里面了
99
+	if userType == UserAdmin {
100
+		// 普通管理人员
69
 		err = serv.SetUserProfile(userID)
101
 		err = serv.SetUserProfile(userID)
102
+
70
 	} else {
103
 	} else {
104
+		// 系统客户
71
 		err = serv.SetCustomer(userID)
105
 		err = serv.SetCustomer(userID)
72
 	}
106
 	}
73
 
107
 
88
 	return true
122
 	return true
89
 }
123
 }
90
 
124
 
91
-func (c *BaseController) getWechatInfo() error {
92
-	// code := c.GetString("code")
93
-	return nil
94
-}
125
+func (c *BaseController) checkWechat(serv *service.SysServ) (*model.TaUserMapping, error) {
126
+	// 确定客户端类型
127
+	adminClient := c.GetString("admin")
128
+	userType := service.USERTYPE_CUSTOMER
129
+	if adminClient != "" {
130
+		userType = service.USERTYPE_USER
131
+	}
132
+
133
+	openIDRaw := c.GetSession("openid")
134
+	if openIDRaw != nil {
135
+		openID := openIDRaw.(string)
136
+		wxUser := map[string]interface{}{
137
+			"openid": openID,
138
+		}
139
+		return serv.CheckWechatUserMapping(wxUser, userType)
140
+	}
95
 
141
 
96
-func (c *BaseController) getSysUserInfo(userID string) error {
142
+	// 微信 code
143
+	code := c.GetString("code")
144
+	if code == "" {
145
+		return nil, errors.New("没有微信 code")
146
+	}
97
 
147
 
148
+	// 获取微信信息
149
+	wxUser, err := utils.GetWxUserInfo(code)
150
+	if err != nil {
151
+		return nil, err
152
+	}
153
+
154
+	return serv.CheckWechatUserMapping(wxUser, userType)
98
 }
155
 }
99
 
156
 
100
-func (c *BaseController) getCustomer(customerID string) error {
157
+// getUserIDByUserMap 校验用户映射是否与 Session 一致
158
+func (c *BaseController) getUserIDByUserMap(user *model.TaUserMapping, userID, userType string) string {
159
+	// 如果映射信息不存在
160
+	if user == nil {
161
+		return ""
162
+	}
163
+
164
+	// 如果 session 数据存在, 以 session 为准
165
+	if userID != "" {
166
+		return ""
167
+	}
168
+
169
+	// 如果是系统内置用户
170
+	if user.UserType == service.USERTYPE_USER {
171
+		if userType != UserAdmin {
172
+			return ""
173
+		}
174
+	}
175
+
176
+	// 如果是普通客户
177
+	if user.UserType == service.USERTYPE_CUSTOMER {
178
+		if userType != UserCustomer {
179
+			return ""
180
+		}
181
+	}
101
 
182
 
183
+	return user.UserId
102
 }
184
 }

+ 3
- 0
controllers/session.go Vedi File

6
 	SNUserID = "userid"
6
 	SNUserID = "userid"
7
 	// 用户类型
7
 	// 用户类型
8
 	SNUserType = "userType"
8
 	SNUserType = "userType"
9
+
10
+	// 内置 openid
11
+	// 请勿使用 openid 作为 session 的key
9
 )
12
 )

+ 1
- 1
controllers/types.go Vedi File

3
 // 用户类型列表
3
 // 用户类型列表
4
 const (
4
 const (
5
 	UserGuest    = "guest"
5
 	UserGuest    = "guest"
6
-	UserCommon   = "common"
6
+	UserAdmin    = "admin"
7
 	UserCustomer = "customer"
7
 	UserCustomer = "customer"
8
 )
8
 )
9
 
9
 

+ 0
- 0
log/common.log Vedi File


+ 13
- 0
models/constant.go Vedi File

1
 package models
1
 package models
2
 
2
 
3
+// 状态列表
3
 const (
4
 const (
4
 	STATUS_NORMAL = 1
5
 	STATUS_NORMAL = 1
5
 	STATUS_DEL    = -1
6
 	STATUS_DEL    = -1
6
 )
7
 )
8
+
9
+// 映射数据库的布尔型
10
+const (
11
+	BOOL_FALSE = 0
12
+	BOOL_TRUE  = 1
13
+)
14
+
15
+// 映射表账户类型
16
+const (
17
+	ACCMAP_WECHAT = "wechat"
18
+	ACCMAP_MINI   = "mini"
19
+)

+ 65
- 15
models/sys.go Vedi File

5
 	"spaceofcheng/services/models/model"
5
 	"spaceofcheng/services/models/model"
6
 	"spaceofcheng/services/utils"
6
 	"spaceofcheng/services/utils"
7
 
7
 
8
+	"github.com/yl10/kit/guid"
9
+
8
 	"github.com/go-xorm/xorm"
10
 	"github.com/go-xorm/xorm"
9
 )
11
 )
10
 
12
 
35
 		return nil, errors.New("没有查询到 ID (" + id + ") 对应的用户")
37
 		return nil, errors.New("没有查询到 ID (" + id + ") 对应的用户")
36
 	}
38
 	}
37
 
39
 
38
-	if user.Status != STATUS_NOMAIL {
40
+	if user.Status != STATUS_NORMAL {
39
 		return nil, errors.New("用户状态不正确")
41
 		return nil, errors.New("用户状态不正确")
40
 	}
42
 	}
41
 
43
 
54
 	`
56
 	`
55
 
57
 
56
 	var menus []model.SysMenu
58
 	var menus []model.SysMenu
57
-	if err := m.db.SQL(query, userID, STATUS_NOMAIL).Find(&menus); err != nil {
59
+	if err := m.db.SQL(query, userID, STATUS_NORMAL).Find(&menus); err != nil {
58
 		return nil, err
60
 		return nil, err
59
 	}
61
 	}
60
 
62
 
71
 	`
73
 	`
72
 
74
 
73
 	var cases []model.SysUserCase
75
 	var cases []model.SysUserCase
74
-	if err := m.db.SQL(query, userID, STATUS_NOMAIL).Find(&cases); err != nil {
76
+	if err := m.db.SQL(query, userID, STATUS_NORMAL).Find(&cases); err != nil {
75
 		return nil, err
77
 		return nil, err
76
 	}
78
 	}
77
 
79
 
78
 	return cases, nil
80
 	return cases, nil
79
 }
81
 }
80
 
82
 
81
-// GetUserOrg 获取人员机构信息
82
-func (m *SysDAO) GetUserOrg(userID string) (*model.SysOrg, error) {
83
-	query := `
84
-		SELECT t.*
85
-		FROM sys_org t
86
-		JOIN sys_user s USING (org_id)
87
-		WHERE s.user_id = ?
88
-		AND t.status = ?
89
-	`
90
-
83
+// GetOrg 获取机构信息
84
+func (m *SysDAO) GetOrg(orgID string) (*model.SysOrg, error) {
91
 	var org model.SysOrg
85
 	var org model.SysOrg
92
-	has, err := m.db.SQL(query, userID, STATUS_NOMAIL).Get(&org)
86
+	has, err := m.db.Where("org_id=?", orgID).And("status=?", STATUS_NORMAL).Get(&org)
93
 	if err != nil {
87
 	if err != nil {
94
 		return nil, err
88
 		return nil, err
95
 	}
89
 	}
106
 func (m *SysDAO) GetCustomer(custID string) (*model.TaCustomer, error) {
100
 func (m *SysDAO) GetCustomer(custID string) (*model.TaCustomer, error) {
107
 	var cust model.TaCustomer
101
 	var cust model.TaCustomer
108
 
102
 
109
-	has, err := m.db.Where("customer_id=?", custID).And("status=?", STATUS_NOMAIL).Get(&cust)
103
+	has, err := m.db.Where("customer_id=?", custID).And("status=?", STATUS_NORMAL).Get(&cust)
110
 	if err != nil {
104
 	if err != nil {
111
 		return nil, err
105
 		return nil, err
112
 	}
106
 	}
117
 
111
 
118
 	return &cust, nil
112
 	return &cust, nil
119
 }
113
 }
114
+
115
+// CheckUserMappingByOpenID 校验并更新客户信息
116
+// 如果不存在, 则插入新数据
117
+func (m *SysDAO) CheckUserMappingByOpenID(user *model.TaUserMapping) error {
118
+	var innerUsers []model.TaUserMapping
119
+
120
+	if err := m.db.Where("account_type=?", user.AccountType).
121
+		And("openid=?", user.Openid).
122
+		Find(&innerUsers); err != nil {
123
+		return err
124
+	}
125
+
126
+	// 如果没有, 则插入新数据
127
+	if len(innerUsers) == 0 {
128
+		user.MappingId = guid.NewGUIDString()
129
+		_, err := m.db.Insert(&user)
130
+		return err
131
+	}
132
+
133
+	// 如果 userid 是空, 则需要找到数据的正常映射
134
+	if user.UserId == "" {
135
+		for _, u := range innerUsers {
136
+			if u.UserId != "" && u.UserType == user.UserType {
137
+				user.UserId = u.UserId
138
+				user.MappingId = u.MappingId
139
+			}
140
+		}
141
+	}
142
+
143
+	// 否则更新数据
144
+	if user.AccountInfo == "" {
145
+		return nil
146
+	}
147
+
148
+	cols := []string{
149
+		"account_info",
150
+	}
151
+
152
+	_, err := m.db.Cols(cols...).
153
+		Where("account_type=?", user.AccountType).
154
+		And("openid=?", user.Openid).
155
+		Update(&user)
156
+	return err
157
+}
158
+
159
+// GetUserMappingByOpenID 获取用户映射信息
160
+func (m *SysDAO) GetUserMappingByOpenID(openID, userType, accType string) (*model.TaUserMapping, error) {
161
+	user := model.TaUserMapping{}
162
+
163
+	_, err := m.db.Where("user_type=?", userType).
164
+		And("account_type=?", accType).
165
+		And("openid=?", openID).
166
+		Get(&user)
167
+
168
+	return &user, err
169
+}

+ 35
- 2
service/sys.go Vedi File

1
 package service
1
 package service
2
 
2
 
3
 import (
3
 import (
4
+	"encoding/json"
4
 	"spaceofcheng/services/models"
5
 	"spaceofcheng/services/models"
6
+	"spaceofcheng/services/models/model"
5
 	"spaceofcheng/services/utils"
7
 	"spaceofcheng/services/utils"
6
 )
8
 )
7
 
9
 
39
 
41
 
40
 	found := false
42
 	found := false
41
 	for _, cs := range cases {
43
 	for _, cs := range cases {
42
-		if cs.IsBelong == 1 {
44
+		if cs.IsBelong == models.BOOL_TRUE {
43
 			found = true
45
 			found = true
44
 			s.ctx.Set("currentCase", cs)
46
 			s.ctx.Set("currentCase", cs)
45
 		}
47
 		}
49
 		return utils.LogError("用户没有设置默认案场")
51
 		return utils.LogError("用户没有设置默认案场")
50
 	}
52
 	}
51
 
53
 
52
-	org, err := s.dao.GetUserOrg(org)
54
+	org, err := s.dao.GetOrg(user.OrgId)
53
 	if err != nil {
55
 	if err != nil {
54
 		return utils.LogError("获取用户组织信息失败: " + err.Error())
56
 		return utils.LogError("获取用户组织信息失败: " + err.Error())
55
 	}
57
 	}
68
 	s.ctx.Set("customer", *cust)
70
 	s.ctx.Set("customer", *cust)
69
 	return nil
71
 	return nil
70
 }
72
 }
73
+
74
+// CheckWechatUserMapping 校验并更新客户信息
75
+// 如果不存在, 则插入新数据
76
+func (s *SysServ) CheckWechatUserMapping(user map[string]interface{}, userType string) (*model.TaUserMapping, error) {
77
+	openID := user["openid"].(string)
78
+	uuID := ""
79
+	uuidRaw, ok := user["unionid"]
80
+	if ok {
81
+		uuID = uuidRaw.(string)
82
+	}
83
+
84
+	accountRaw, err := json.Marshal(user)
85
+	if err != nil {
86
+		return nil, err
87
+	}
88
+	account := string(accountRaw)
89
+
90
+	userMapping := model.TaUserMapping{
91
+		UserType:    userType,
92
+		AccountType: models.ACCMAP_WECHAT,
93
+		Openid:      openID,
94
+		Uuid:        uuID,
95
+		AccountInfo: account,
96
+	}
97
+
98
+	if err := s.dao.CheckUserMappingByOpenID(&userMapping); err != nil {
99
+		return nil, err
100
+	}
101
+
102
+	return &userMapping, nil
103
+}

+ 68
- 4
utils/log.go Vedi File

3
 import (
3
 import (
4
 	"errors"
4
 	"errors"
5
 
5
 
6
-	"github.com/astaxie/beego"
6
+	"github.com/astaxie/beego/config"
7
+	"github.com/astaxie/beego/logs"
7
 )
8
 )
8
 
9
 
10
+var defaultLogger *logs.BeeLogger
11
+var instances map[string]*logs.BeeLogger
12
+
13
+// NewLog 构造日志对象
14
+func NewLog(tp ...string) *logs.BeeLogger {
15
+	logType := "common"
16
+	if len(tp) > 0 {
17
+		if tp[0] != "" {
18
+			logType = tp[0]
19
+		}
20
+	}
21
+
22
+	if v, ok := instances[logType]; ok {
23
+		return v
24
+	}
25
+
26
+	log := logs.NewLogger()
27
+	instances[logType] = log
28
+
29
+	// 读取配置文件
30
+	conf, err := config.NewConfig("ini", "./conf/log.conf")
31
+	if err != nil {
32
+		log.SetLogger(logs.AdapterConsole)
33
+		return log
34
+	}
35
+
36
+	// 读文件存储位置
37
+	filename := conf.String(logType + "::filename")
38
+	// 输出级别
39
+	level := conf.String(logType + "::level")
40
+	if level == "" {
41
+		level = "error"
42
+	}
43
+
44
+	if filename == "" {
45
+		filename = "./" + logType + ".log"
46
+	}
47
+
48
+	log.Async()
49
+	log.SetLogger(logs.AdapterFile, `{"filename":"`+filename+`"}`)
50
+	return log
51
+}
52
+
9
 // LogError 错误日志
53
 // LogError 错误日志
10
 func LogError(v ...interface{}) error {
54
 func LogError(v ...interface{}) error {
11
-	beego.Error(v...)
55
+	log := instances["common"]
12
 
56
 
13
 	if len(v) > 0 {
57
 	if len(v) > 0 {
14
-		switch err := v[0].(type) {
58
+		firstV := v[0]
59
+		leftV := v[1:]
60
+
61
+		switch err := firstV.(type) {
15
 		case string:
62
 		case string:
63
+			log.Error(err, leftV...)
16
 			return errors.New(err)
64
 			return errors.New(err)
17
 		case error:
65
 		case error:
66
+			log.Error(err.Error(), leftV...)
18
 			return err
67
 			return err
19
 		default:
68
 		default:
20
-			return errors.New("Unknown error type")
69
+			msg := "Unknown error type"
70
+			log.Error(msg, leftV...)
71
+			return errors.New(msg)
21
 		}
72
 		}
22
 	}
73
 	}
23
 
74
 
24
 	return nil
75
 	return nil
25
 }
76
 }
77
+
78
+// GetDefaultLogger 获取默认 logger
79
+func GetDefaultLogger() *logs.BeeLogger {
80
+	log := instances["common"]
81
+	return log
82
+}
83
+
84
+func init() {
85
+	instances = make(map[string]*logs.BeeLogger)
86
+	NewLog()
87
+
88
+	defaultLogger = GetDefaultLogger()
89
+}

+ 23
- 0
utils/wechat.go Vedi File

1
+package utils
2
+
3
+import (
4
+	"github.com/zjxpcyc/wechat/wx"
5
+)
6
+
7
+var wxCli *wx.Client
8
+
9
+// InitWeChatClient 初始化
10
+func InitWeChatClient(cert map[string]string) {
11
+	wxCli = wx.NewClient(cert)
12
+	wx.SetLogInst(defaultLogger)
13
+}
14
+
15
+// GetWxUserInfo 微信获取用户信息
16
+func GetWxUserInfo(code string) (map[string]interface{}, error) {
17
+	return wxCli.GetUserInfo(code)
18
+}
19
+
20
+// WechatSignature 启用 Wechat 接口
21
+func WechatSignature(timestamp, nonce string) string {
22
+	return wxCli.Signature(timestamp, nonce)
23
+}