Просмотр исходного кода

add some /admin/ to surport web OIDC

Tao Chen 1 год назад
Родитель
Сommit
7c1fc4fa6d
3 измененных файлов с 182 добавлено и 48 удалено
  1. 86 1
      http/controller/admin/login.go
  2. 93 46
      http/controller/api/ouath.go
  3. 3 1
      http/router/admin.go

+ 86 - 1
http/controller/admin/login.go

@@ -5,6 +5,8 @@ import (
5 5
 	"Gwen/http/request/admin"
6 6
 	"Gwen/http/response"
7 7
 	adResp "Gwen/http/response/admin"
8
+	apiReq "Gwen/http/request/api"
9
+	"Gwen/http/controller/api"
8 10
 	"Gwen/model"
9 11
 	"Gwen/service"
10 12
 	"fmt"
@@ -51,7 +53,7 @@ func (ct *Login) Login(c *gin.Context) {
51 53
 	ut := service.AllService.UserService.Login(u, &model.LoginLog{
52 54
 		UserId:   u.Id,
53 55
 		Client:   "webadmin",
54
-		Uuid:     "",
56
+		Uuid:     "", //must be empty
55 57
 		Ip:       c.ClientIP(),
56 58
 		Type:     "account",
57 59
 		Platform: f.Platform,
@@ -82,3 +84,86 @@ func (ct *Login) Logout(c *gin.Context) {
82 84
 	}
83 85
 	response.Success(c, nil)
84 86
 }
87
+
88
+
89
+// LoginOptions
90
+// @Tags 登录
91
+// @Summary 登录选项
92
+// @Description 登录选项
93
+// @Accept  json
94
+// @Produce  json
95
+// @Success 200 {object} []string
96
+// @Failure 500 {object} response.ErrorResponse
97
+// @Router /admin/login-options [post]
98
+// 直接调用/api/login的LoginOptions方法
99
+func (ct *Login) LoginOptions(c *gin.Context) {
100
+	l := &api.Login{}
101
+    l.LoginOptions(c)
102
+}
103
+
104
+
105
+// OidcAuth
106
+// @Tags Oauth
107
+// @Summary OidcAuth
108
+// @Description OidcAuth
109
+// @Accept  json
110
+// @Produce  json
111
+// @Router /admin/oidc/auth [post]
112
+func (ct *Login) OidcAuth(c *gin.Context) {
113
+	// o := &api.Oauth{}
114
+	// o.OidcAuth(c)
115
+	f := &apiReq.OidcAuthRequest{}
116
+	err := c.ShouldBindJSON(f)
117
+	if err != nil {
118
+		response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
119
+		return
120
+	}
121
+
122
+	err, code, url := service.AllService.OauthService.BeginAuth(f.Op)
123
+	if err != nil {
124
+		response.Error(c, response.TranslateMsg(c, err.Error()))
125
+		return
126
+	}
127
+
128
+	service.AllService.OauthService.SetOauthCache(code, &service.OauthCacheItem{
129
+		Action: service.OauthActionTypeLogin,
130
+		Op:     	f.Op,
131
+		Id: 		f.Id,
132
+		DeviceType: "webadmin",
133
+		// DeviceOs: ct.Platform(c),
134
+		DeviceOs: 	f.DeviceInfo.Os,
135
+		Uuid: 		f.Uuid,
136
+	}, 5*60)
137
+
138
+	response.Success(c, gin.H{
139
+		"code": code,
140
+		"url":  url,
141
+	})
142
+}
143
+
144
+
145
+
146
+// OidcAuthQuery
147
+// @Tags Oauth
148
+// @Summary OidcAuthQuery
149
+// @Description OidcAuthQuery
150
+// @Accept  json
151
+// @Produce  json
152
+// @Success 200 {object} response.Response{data=adResp.LoginPayload}
153
+// @Failure 500 {object} response.Response
154
+// @Router /admin/oidc/auth-query [get]
155
+func (ct *Login) OidcAuthQuery(c *gin.Context) {
156
+	o := &api.Oauth{}
157
+	u, ut := o.OidcAuthQueryPre(c)
158
+	if ut == nil {
159
+		return
160
+	}
161
+	fmt.Println("u:", u)
162
+	fmt.Println("ut:", ut)
163
+	response.Success(c, &adResp.LoginPayload{
164
+		Token:      ut.Token,
165
+		Username:   u.Username,
166
+		RouteNames: service.AllService.UserService.RouteNames(u),
167
+		Nickname:   u.Nickname,
168
+	})
169
+}

+ 93 - 46
http/controller/api/ouath.go

@@ -59,36 +59,42 @@ func (o *Oauth) OidcAuth(c *gin.Context) {
59 59
 	})
60 60
 }
61 61
 
62
-// OidcAuthQuery
63
-// @Tags Oauth
64
-// @Summary OidcAuthQuery
65
-// @Description OidcAuthQuery
66
-// @Accept  json
67
-// @Produce  json
68
-// @Success 200 {object} apiResp.LoginRes
69
-// @Failure 500 {object} response.ErrorResponse
70
-// @Router /oidc/auth-query [get]
71
-func (o *Oauth) OidcAuthQuery(c *gin.Context) {
62
+func (o *Oauth) OidcAuthQueryPre(c *gin.Context) (*model.User, *model.UserToken) {
63
+	var u *model.User
64
+	var ut *model.UserToken
72 65
 	q := &api.OidcAuthQuery{}
73
-	err := c.ShouldBindQuery(q)
74
-	if err != nil {
75
-		response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
76
-		return
66
+
67
+	// 解析查询参数并处理错误
68
+	if err := c.ShouldBindQuery(q); err != nil {
69
+		response.Error(c, response.TranslateMsg(c, "ParamsError")+": "+err.Error())
70
+		return nil, nil
77 71
 	}
72
+
73
+	// 获取 OAuth 缓存
78 74
 	v := service.AllService.OauthService.GetOauthCache(q.Code)
79 75
 	if v == nil {
80 76
 		response.Error(c, response.TranslateMsg(c, "OauthExpired"))
81
-		return
77
+		return nil, nil
82 78
 	}
79
+
80
+	// 如果 UserId 为 0,说明还在授权中
83 81
 	if v.UserId == 0 {
84
-		//正在授权
85
-		c.JSON(http.StatusOK, gin.H{})
86
-		return
82
+		c.JSON(http.StatusOK, gin.H{"message": "Authorization in progress"})
83
+		return nil, nil
87 84
 	}
88
-	u := service.AllService.UserService.InfoById(v.UserId)
89
-	//fmt.Println("auth success u", u)
85
+
86
+	// 获取用户信息
87
+	u = service.AllService.UserService.InfoById(v.UserId)
88
+	if u == nil {
89
+		response.Error(c, response.TranslateMsg(c, "UserNotFound"))
90
+		return nil, nil
91
+	}
92
+
93
+	// 删除 OAuth 缓存
90 94
 	service.AllService.OauthService.DeleteOauthCache(q.Code)
91
-	ut := service.AllService.UserService.Login(u, &model.LoginLog{
95
+
96
+	// 创建登录日志并生成用户令牌
97
+	ut = service.AllService.UserService.Login(u, &model.LoginLog{
92 98
 		UserId:   u.Id,
93 99
 		Client:   v.DeviceType,
94 100
 		Uuid:     v.Uuid,
@@ -96,6 +102,27 @@ func (o *Oauth) OidcAuthQuery(c *gin.Context) {
96 102
 		Type:     model.LoginLogTypeOauth,
97 103
 		Platform: v.DeviceOs,
98 104
 	})
105
+
106
+	if ut == nil {
107
+		response.Error(c, response.TranslateMsg(c, "LoginFailed"))
108
+		return nil, nil
109
+	}
110
+
111
+	// 返回用户令牌
112
+	return u, ut
113
+}
114
+
115
+// OidcAuthQuery
116
+// @Tags Oauth
117
+// @Summary OidcAuthQuery
118
+// @Description OidcAuthQuery
119
+// @Accept  json
120
+// @Produce  json
121
+// @Success 200 {object} apiResp.LoginRes
122
+// @Failure 500 {object} response.ErrorResponse
123
+// @Router /oidc/auth-query [get]
124
+func (o *Oauth) OidcAuthQuery(c *gin.Context) {
125
+	u, ut := o.OidcAuthQueryPre(c)
99 126
 	c.JSON(http.StatusOK, apiResp.LoginRes{
100 127
 		AccessToken: ut.Token,
101 128
 		Type:        "access_token",
@@ -129,6 +156,7 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
129 156
 
130 157
 	ty := v.Op
131 158
 	ac := v.Action
159
+	var u *model.User
132 160
 	//fmt.Println("ty ac ", ty, ac)
133 161
 	if ty == model.OauthTypeGithub {
134 162
 		code := c.Query("code")
@@ -145,7 +173,7 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
145 173
 				return
146 174
 			}
147 175
 			//绑定
148
-			u := service.AllService.UserService.InfoById(v.UserId)
176
+			u = service.AllService.UserService.InfoById(v.UserId)
149 177
 			if u == nil {
150 178
 				c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ItemNotFound"))
151 179
 				return
@@ -164,7 +192,7 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
164 192
 				c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBeenSuccess"))
165 193
 				return
166 194
 			}
167
-			u := service.AllService.UserService.InfoByGithubId(strconv.Itoa(userData.Id))
195
+			u = service.AllService.UserService.InfoByGithubId(strconv.Itoa(userData.Id))
168 196
 			if u == nil {
169 197
 				oa := service.AllService.OauthService.InfoByOp(ty)
170 198
 				if !*oa.AutoRegister {
@@ -184,15 +212,13 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
184 212
 				}
185 213
 			}
186 214
 
187
-			v.UserId = u.Id
188
-			service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
189
-			c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
190
-			return
215
+			// v.UserId = u.Id
216
+			// service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
217
+			// c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
218
+			// return
191 219
 		}
192 220
 
193
-	}
194
-
195
-	if ty == model.OauthTypeGoogle {
221
+	} else if ty == model.OauthTypeGoogle {
196 222
 		code := c.Query("code")
197 223
 		err, userData := service.AllService.OauthService.GoogleCallback(code)
198 224
 		if err != nil {
@@ -209,7 +235,7 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
209 235
 				return
210 236
 			}
211 237
 			//绑定
212
-			u := service.AllService.UserService.InfoById(v.UserId)
238
+			u = service.AllService.UserService.InfoById(v.UserId)
213 239
 			if u == nil {
214 240
 				c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ItemNotFound"))
215 241
 				return
@@ -227,7 +253,7 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
227 253
 				c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBeenSuccess"))
228 254
 				return
229 255
 			}
230
-			u := service.AllService.UserService.InfoByGoogleEmail(userData.Email)
256
+			u = service.AllService.UserService.InfoByGoogleEmail(userData.Email)
231 257
 			if u == nil {
232 258
 				oa := service.AllService.OauthService.InfoByOp(ty)
233 259
 				if !*oa.AutoRegister {
@@ -248,13 +274,12 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
248 274
 				}
249 275
 			}
250 276
 
251
-			v.UserId = u.Id
252
-			service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
253
-			c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
254
-			return
277
+			// v.UserId = u.Id
278
+			// service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
279
+			// c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
280
+			// return
255 281
 		}
256
-	}
257
-	if ty == model.OauthTypeOidc {
282
+	} else if ty == model.OauthTypeOidc {
258 283
 		code := c.Query("code")
259 284
 		err, userData := service.AllService.OauthService.OidcCallback(code)
260 285
 		if err != nil {
@@ -271,7 +296,7 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
271 296
 				return
272 297
 			}
273 298
 			//绑定
274
-			u := service.AllService.UserService.InfoById(v.UserId)
299
+			u = service.AllService.UserService.InfoById(v.UserId)
275 300
 			if u == nil {
276 301
 				c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ItemNotFound"))
277 302
 				return
@@ -289,7 +314,7 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
289 314
 				c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBeenSuccess"))
290 315
 				return
291 316
 			}
292
-			u := service.AllService.UserService.InfoByOidcSub(userData.Sub)
317
+			u = service.AllService.UserService.InfoByOidcSub(userData.Sub)
293 318
 			if u == nil {
294 319
 				oa := service.AllService.OauthService.InfoByOp(ty)
295 320
 				if !*oa.AutoRegister {
@@ -311,13 +336,35 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
311 336
 				}
312 337
 			}
313 338
 
314
-			v.UserId = u.Id
315
-			service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
316
-			c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
317
-			return
339
+			// v.UserId = u.Id
340
+			// service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
341
+			// c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
342
+			// return
318 343
 		}
319 344
 	}
320
-
321
-	c.String(http.StatusInternalServerError, response.TranslateMsg(c, "SystemError"))
345
+	// 如果u为空,说明没有绑定用户
346
+	if u == nil {
347
+		c.String(http.StatusInternalServerError, response.TranslateMsg(c, "SystemError"))
348
+		return
349
+	}
350
+	// 认证成功,设置缓存
351
+	v.UserId = u.Id
352
+	service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
353
+	// 如果是webadmin,登录成功后跳转到webadmin
354
+	if v.DeviceType == "webadmin" {
355
+		service.AllService.UserService.Login(u, &model.LoginLog{
356
+			UserId:   u.Id,
357
+			Client:   "webadmin",
358
+			Uuid:     "",//must be empty
359
+			Ip:       c.ClientIP(),
360
+			Type:     "account",
361
+			Platform: v.DeviceOs,
362
+		})
363
+		url := global.Config.Rustdesk.ApiServer + "/_admin/#/"
364
+		c.Redirect(http.StatusFound, url)
365
+		return
366
+	}
367
+	c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
368
+	return
322 369
 
323 370
 }

+ 3 - 1
http/router/admin.go

@@ -33,7 +33,6 @@ func Init(g *gin.Engine) {
33 33
 	rs := &admin.Rustdesk{}
34 34
 	adg.GET("/server-config", rs.ServerConfig)
35 35
 	adg.GET("/app-config", rs.AppConfig)
36
-
37 36
 	//访问静态文件
38 37
 	//g.StaticFS("/upload", http.Dir(global.Config.Gin.ResourcesPath+"/upload"))
39 38
 }
@@ -41,6 +40,9 @@ func LoginBind(rg *gin.RouterGroup) {
41 40
 	cont := &admin.Login{}
42 41
 	rg.POST("/login", cont.Login)
43 42
 	rg.POST("/logout", cont.Logout)
43
+	rg.GET("/login-options", cont.LoginOptions)
44
+	rg.POST("/oidc/auth", cont.OidcAuth)
45
+	rg.GET("/oidc/auth-query", cont.OidcAuthQuery)
44 46
 }
45 47
 
46 48
 func UserBind(rg *gin.RouterGroup) {