zjxpcyc 6 年之前
父節點
當前提交
93a8f39d8f
共有 10 個文件被更改,包括 329 次插入57 次删除
  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 查看文件

@@ -0,0 +1,4 @@
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 查看文件

@@ -3,6 +3,7 @@ package controllers
3 3
 import (
4 4
 	"errors"
5 5
 	"net/http"
6
+	"spaceofcheng/services/models/model"
6 7
 	"spaceofcheng/services/service"
7 8
 	"spaceofcheng/services/utils"
8 9
 	"strings"
@@ -12,49 +13,72 @@ import (
12 13
 
13 14
 // Authenticate 权限验证
14 15
 func (c *BaseController) authenticate() {
15
-	if !c.needAuth() {
16
-		return
17
-	}
18
-
19 16
 	// 默认 service
20 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 55
 	if userType == UserGuest {
28 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 66
 	if userID == "" {
39 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 83
 		} else {
60 84
 			c.ResponseError(
@@ -64,10 +88,20 @@ func (c *BaseController) authenticate() {
64 88
 		}
65 89
 	}
66 90
 
91
+	// 设置 Session
92
+	c.SetSession(SNUserID, userID)
93
+	c.SetSession(SNUserType, userType)
94
+
67 95
 	var err error
68
-	if clientType == utils.ClientAdmin {
96
+
97
+	// 设置 Context
98
+	// 放到 serv 的方法里面了
99
+	if userType == UserAdmin {
100
+		// 普通管理人员
69 101
 		err = serv.SetUserProfile(userID)
102
+
70 103
 	} else {
104
+		// 系统客户
71 105
 		err = serv.SetCustomer(userID)
72 106
 	}
73 107
 
@@ -88,15 +122,63 @@ func (c *BaseController) needAuth() bool {
88 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 查看文件

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

+ 1
- 1
controllers/types.go 查看文件

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

+ 0
- 0
log/common.log 查看文件


+ 13
- 0
models/constant.go 查看文件

@@ -1,6 +1,19 @@
1 1
 package models
2 2
 
3
+// 状态列表
3 4
 const (
4 5
 	STATUS_NORMAL = 1
5 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 查看文件

@@ -5,6 +5,8 @@ import (
5 5
 	"spaceofcheng/services/models/model"
6 6
 	"spaceofcheng/services/utils"
7 7
 
8
+	"github.com/yl10/kit/guid"
9
+
8 10
 	"github.com/go-xorm/xorm"
9 11
 )
10 12
 
@@ -35,7 +37,7 @@ func (m *SysDAO) GetPureUserInfo(id string) (*model.SysUser, error) {
35 37
 		return nil, errors.New("没有查询到 ID (" + id + ") 对应的用户")
36 38
 	}
37 39
 
38
-	if user.Status != STATUS_NOMAIL {
40
+	if user.Status != STATUS_NORMAL {
39 41
 		return nil, errors.New("用户状态不正确")
40 42
 	}
41 43
 
@@ -54,7 +56,7 @@ func (m *SysDAO) GetUserMenu(userID string) ([]model.SysMenu, error) {
54 56
 	`
55 57
 
56 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 60
 		return nil, err
59 61
 	}
60 62
 
@@ -71,25 +73,17 @@ func (m *SysDAO) GetUserCase(userID string) ([]model.SysUserCase, error) {
71 73
 	`
72 74
 
73 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 77
 		return nil, err
76 78
 	}
77 79
 
78 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 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 87
 	if err != nil {
94 88
 		return nil, err
95 89
 	}
@@ -106,7 +100,7 @@ func (m *SysDAO) GetUserOrg(userID string) (*model.SysOrg, error) {
106 100
 func (m *SysDAO) GetCustomer(custID string) (*model.TaCustomer, error) {
107 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 104
 	if err != nil {
111 105
 		return nil, err
112 106
 	}
@@ -117,3 +111,59 @@ func (m *SysDAO) GetCustomer(custID string) (*model.TaCustomer, error) {
117 111
 
118 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 查看文件

@@ -1,7 +1,9 @@
1 1
 package service
2 2
 
3 3
 import (
4
+	"encoding/json"
4 5
 	"spaceofcheng/services/models"
6
+	"spaceofcheng/services/models/model"
5 7
 	"spaceofcheng/services/utils"
6 8
 )
7 9
 
@@ -39,7 +41,7 @@ func (s *SysServ) SetUserProfile(id string) error {
39 41
 
40 42
 	found := false
41 43
 	for _, cs := range cases {
42
-		if cs.IsBelong == 1 {
44
+		if cs.IsBelong == models.BOOL_TRUE {
43 45
 			found = true
44 46
 			s.ctx.Set("currentCase", cs)
45 47
 		}
@@ -49,7 +51,7 @@ func (s *SysServ) SetUserProfile(id string) error {
49 51
 		return utils.LogError("用户没有设置默认案场")
50 52
 	}
51 53
 
52
-	org, err := s.dao.GetUserOrg(org)
54
+	org, err := s.dao.GetOrg(user.OrgId)
53 55
 	if err != nil {
54 56
 		return utils.LogError("获取用户组织信息失败: " + err.Error())
55 57
 	}
@@ -68,3 +70,34 @@ func (s *SysServ) SetCustomer(id string) error {
68 70
 	s.ctx.Set("customer", *cust)
69 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 查看文件

@@ -3,23 +3,87 @@ package utils
3 3
 import (
4 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 53
 // LogError 错误日志
10 54
 func LogError(v ...interface{}) error {
11
-	beego.Error(v...)
55
+	log := instances["common"]
12 56
 
13 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 62
 		case string:
63
+			log.Error(err, leftV...)
16 64
 			return errors.New(err)
17 65
 		case error:
66
+			log.Error(err.Error(), leftV...)
18 67
 			return err
19 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 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 查看文件

@@ -0,0 +1,23 @@
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
+}