ouath.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. package api
  2. import (
  3. "Gwen/global"
  4. "Gwen/http/request/api"
  5. "Gwen/http/response"
  6. apiResp "Gwen/http/response/api"
  7. "Gwen/model"
  8. "Gwen/service"
  9. "github.com/gin-gonic/gin"
  10. "net/http"
  11. "strconv"
  12. "strings"
  13. )
  14. type Oauth struct {
  15. }
  16. // OidcAuth
  17. // @Tags Oauth
  18. // @Summary OidcAuth
  19. // @Description OidcAuth
  20. // @Accept json
  21. // @Produce json
  22. // @Success 200 {object} apiResp.LoginRes
  23. // @Failure 500 {object} response.ErrorResponse
  24. // @Router /oidc/auth [post]
  25. func (o *Oauth) OidcAuth(c *gin.Context) {
  26. f := &api.OidcAuthRequest{}
  27. err := c.ShouldBindJSON(&f)
  28. if err != nil {
  29. response.Error(c, "参数错误")
  30. return
  31. }
  32. if f.Op != model.OauthTypeWebauth && f.Op != model.OauthTypeGoogle && f.Op != model.OauthTypeGithub {
  33. response.Error(c, "参数错误")
  34. return
  35. }
  36. err, code, url := service.AllService.OauthService.BeginAuth(f.Op)
  37. if err != nil {
  38. response.Error(c, err.Error())
  39. return
  40. }
  41. service.AllService.OauthService.SetOauthCache(code, &service.OauthCacheItem{
  42. Action: service.OauthActionTypeLogin,
  43. Id: f.Id,
  44. Op: f.Op,
  45. Uuid: f.Uuid,
  46. DeviceName: f.DeviceInfo.Name,
  47. DeviceOs: f.DeviceInfo.Os,
  48. DeviceType: f.DeviceInfo.Type,
  49. }, 5*60)
  50. //fmt.Println("code url", code, url)
  51. c.JSON(http.StatusOK, gin.H{
  52. "code": code,
  53. "url": url,
  54. })
  55. }
  56. // OidcAuthQuery
  57. // @Tags Oauth
  58. // @Summary OidcAuthQuery
  59. // @Description OidcAuthQuery
  60. // @Accept json
  61. // @Produce json
  62. // @Success 200 {object} apiResp.LoginRes
  63. // @Failure 500 {object} response.ErrorResponse
  64. // @Router /oidc/auth-query [get]
  65. func (o *Oauth) OidcAuthQuery(c *gin.Context) {
  66. q := &api.OidcAuthQuery{}
  67. err := c.ShouldBindQuery(q)
  68. if err != nil {
  69. response.Error(c, "参数错误")
  70. return
  71. }
  72. v := service.AllService.OauthService.GetOauthCache(q.Code)
  73. if v == nil {
  74. response.Error(c, "授权已过期,请重新授权")
  75. return
  76. }
  77. if v.UserId == 0 {
  78. //正在授权
  79. c.JSON(http.StatusOK, gin.H{})
  80. return
  81. }
  82. u := service.AllService.UserService.InfoById(v.UserId)
  83. //fmt.Println("auth success u", u)
  84. if u.Id > 0 {
  85. service.AllService.OauthService.DeleteOauthCache(q.Code)
  86. ut := service.AllService.UserService.Login(u, &model.LoginLog{
  87. UserId: u.Id,
  88. Client: v.DeviceType,
  89. Uuid: v.Uuid,
  90. Ip: c.ClientIP(),
  91. Type: model.LoginLogTypeOauth,
  92. Platform: v.DeviceOs,
  93. })
  94. c.JSON(http.StatusOK, apiResp.LoginRes{
  95. AccessToken: ut.Token,
  96. Type: "access_token",
  97. User: *(&apiResp.UserPayload{}).FromUser(u),
  98. })
  99. return
  100. }
  101. response.Error(c, "用户不存在")
  102. }
  103. // OauthCallback 回调
  104. // @Tags Oauth
  105. // @Summary OauthCallback
  106. // @Description OauthCallback
  107. // @Accept json
  108. // @Produce json
  109. // @Success 200 {object} apiResp.LoginRes
  110. // @Failure 500 {object} response.ErrorResponse
  111. // @Router /oauth/callback [get]
  112. func (o *Oauth) OauthCallback(c *gin.Context) {
  113. state := c.Query("state")
  114. if state == "" {
  115. c.String(http.StatusInternalServerError, "state为空")
  116. return
  117. }
  118. cacheKey := state
  119. //从缓存中获取
  120. v := service.AllService.OauthService.GetOauthCache(cacheKey)
  121. if v == nil {
  122. c.String(http.StatusInternalServerError, "授权已过期,请重新授权")
  123. return
  124. }
  125. ty := v.Op
  126. ac := v.Action
  127. //fmt.Println("ty ac ", ty, ac)
  128. if ty == model.OauthTypeGithub {
  129. code := c.Query("code")
  130. err, userData := service.AllService.OauthService.GithubCallback(code)
  131. if err != nil {
  132. c.String(http.StatusInternalServerError, "授权失败:"+err.Error())
  133. return
  134. }
  135. if ac == service.OauthActionTypeBind {
  136. //fmt.Println("bind", ty, userData)
  137. utr := service.AllService.OauthService.UserThirdInfo(ty, strconv.Itoa(userData.Id))
  138. if utr.UserId > 0 {
  139. c.String(http.StatusInternalServerError, "已经绑定其他账号")
  140. return
  141. }
  142. //绑定
  143. u := service.AllService.UserService.InfoById(v.UserId)
  144. if u == nil {
  145. c.String(http.StatusInternalServerError, "用户不存在")
  146. return
  147. }
  148. //绑定github
  149. err = service.AllService.OauthService.BindGithubUser(strconv.Itoa(userData.Id), userData.Login, v.UserId)
  150. if err != nil {
  151. c.String(http.StatusInternalServerError, "绑定失败")
  152. return
  153. }
  154. c.String(http.StatusOK, "绑定成功")
  155. return
  156. } else if ac == service.OauthActionTypeLogin {
  157. //登录
  158. if v.UserId != 0 {
  159. c.String(http.StatusInternalServerError, "授权已经成功")
  160. return
  161. }
  162. u := service.AllService.UserService.InfoByGithubId(strconv.Itoa(userData.Id))
  163. if u == nil {
  164. oa := service.AllService.OauthService.InfoByOp(ty)
  165. if !*oa.AutoRegister {
  166. //c.String(http.StatusInternalServerError, "还未绑定用户,请先绑定")
  167. v.ThirdName = userData.Login
  168. v.ThirdOpenId = strconv.Itoa(userData.Id)
  169. url := global.Config.Rustdesk.ApiServer + "/_admin/#/oauth/bind/" + cacheKey
  170. c.Redirect(http.StatusFound, url)
  171. return
  172. }
  173. //自动注册
  174. u = service.AllService.UserService.RegisterByGithub(userData.Login, strconv.Itoa(userData.Id))
  175. if u.Id == 0 {
  176. c.String(http.StatusInternalServerError, "注册失败")
  177. return
  178. }
  179. }
  180. v.UserId = u.Id
  181. service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
  182. c.String(http.StatusOK, "授权成功")
  183. return
  184. }
  185. //返回js
  186. c.Header("Content-Type", "text/html; charset=utf-8")
  187. c.String(http.StatusOK, "授权错误")
  188. }
  189. if ty == model.OauthTypeGoogle {
  190. code := c.Query("code")
  191. err, userData := service.AllService.OauthService.GoogleCallback(code)
  192. if err != nil {
  193. c.String(http.StatusInternalServerError, "授权失败:"+err.Error())
  194. return
  195. }
  196. //将空格替换成_
  197. googleName := strings.Replace(userData.Name, " ", "_", -1)
  198. if ac == service.OauthActionTypeBind {
  199. //fmt.Println("bind", ty, userData)
  200. utr := service.AllService.OauthService.UserThirdInfo(ty, userData.Email)
  201. if utr.UserId > 0 {
  202. c.String(http.StatusInternalServerError, "已经绑定其他账号")
  203. return
  204. }
  205. //绑定
  206. u := service.AllService.UserService.InfoById(v.UserId)
  207. if u == nil {
  208. c.String(http.StatusInternalServerError, "用户不存在")
  209. return
  210. }
  211. //绑定
  212. err = service.AllService.OauthService.BindGoogleUser(userData.Email, googleName, v.UserId)
  213. if err != nil {
  214. c.String(http.StatusInternalServerError, "绑定失败")
  215. return
  216. }
  217. c.String(http.StatusOK, "绑定成功")
  218. return
  219. } else if ac == service.OauthActionTypeLogin {
  220. if v.UserId != 0 {
  221. c.String(http.StatusInternalServerError, "授权已经成功")
  222. return
  223. }
  224. u := service.AllService.UserService.InfoByGoogleEmail(userData.Email)
  225. if u == nil {
  226. oa := service.AllService.OauthService.InfoByOp(ty)
  227. if !*oa.AutoRegister {
  228. //c.String(http.StatusInternalServerError, "还未绑定用户,请先绑定")
  229. v.ThirdName = googleName
  230. v.ThirdOpenId = userData.Email
  231. url := global.Config.Rustdesk.ApiServer + "/_admin/#/oauth/bind/" + cacheKey
  232. c.Redirect(http.StatusFound, url)
  233. return
  234. }
  235. //自动注册
  236. u = service.AllService.UserService.RegisterByGoogle(googleName, userData.Email)
  237. if u.Id == 0 {
  238. c.String(http.StatusInternalServerError, "注册失败")
  239. return
  240. }
  241. }
  242. v.UserId = u.Id
  243. service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
  244. c.String(http.StatusOK, "授权成功")
  245. return
  246. }
  247. }
  248. c.String(http.StatusInternalServerError, "授权配置错误,请联系管理员")
  249. }