ouath.go 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  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, response.TranslateMsg(c, "ParamsError")+err.Error())
  30. return
  31. }
  32. if f.Op != model.OauthTypeWebauth && f.Op != model.OauthTypeGoogle && f.Op != model.OauthTypeGithub && f.Op != model.OauthTypeOidc {
  33. response.Error(c, response.TranslateMsg(c, "ParamsError"))
  34. return
  35. }
  36. err, code, url := service.AllService.OauthService.BeginAuth(f.Op)
  37. if err != nil {
  38. response.Error(c, response.TranslateMsg(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, response.TranslateMsg(c, "ParamsError")+err.Error())
  70. return
  71. }
  72. v := service.AllService.OauthService.GetOauthCache(q.Code)
  73. if v == nil {
  74. response.Error(c, response.TranslateMsg(c, "OauthExpired"))
  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. service.AllService.OauthService.DeleteOauthCache(q.Code)
  85. ut := service.AllService.UserService.Login(u, &model.LoginLog{
  86. UserId: u.Id,
  87. Client: v.DeviceType,
  88. Uuid: v.Uuid,
  89. Ip: c.ClientIP(),
  90. Type: model.LoginLogTypeOauth,
  91. Platform: v.DeviceOs,
  92. })
  93. c.JSON(http.StatusOK, apiResp.LoginRes{
  94. AccessToken: ut.Token,
  95. Type: "access_token",
  96. User: *(&apiResp.UserPayload{}).FromUser(u),
  97. })
  98. }
  99. // OauthCallback 回调
  100. // @Tags Oauth
  101. // @Summary OauthCallback
  102. // @Description OauthCallback
  103. // @Accept json
  104. // @Produce json
  105. // @Success 200 {object} apiResp.LoginRes
  106. // @Failure 500 {object} response.ErrorResponse
  107. // @Router /oauth/callback [get]
  108. func (o *Oauth) OauthCallback(c *gin.Context) {
  109. state := c.Query("state")
  110. if state == "" {
  111. c.String(http.StatusInternalServerError, response.TranslateParamMsg(c, "ParamIsEmpty", "state"))
  112. return
  113. }
  114. cacheKey := state
  115. //从缓存中获取
  116. v := service.AllService.OauthService.GetOauthCache(cacheKey)
  117. if v == nil {
  118. c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthExpired"))
  119. return
  120. }
  121. ty := v.Op
  122. ac := v.Action
  123. //fmt.Println("ty ac ", ty, ac)
  124. if ty == model.OauthTypeGithub {
  125. code := c.Query("code")
  126. err, userData := service.AllService.OauthService.GithubCallback(code)
  127. if err != nil {
  128. c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthFailed")+response.TranslateMsg(c, err.Error()))
  129. return
  130. }
  131. if ac == service.OauthActionTypeBind {
  132. //fmt.Println("bind", ty, userData)
  133. utr := service.AllService.OauthService.UserThirdInfo(ty, strconv.Itoa(userData.Id))
  134. if utr.UserId > 0 {
  135. c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBindOtherUser"))
  136. return
  137. }
  138. //绑定
  139. u := service.AllService.UserService.InfoById(v.UserId)
  140. if u == nil {
  141. c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ItemNotFound"))
  142. return
  143. }
  144. //绑定github
  145. err = service.AllService.OauthService.BindGithubUser(strconv.Itoa(userData.Id), userData.Login, v.UserId)
  146. if err != nil {
  147. c.String(http.StatusInternalServerError, response.TranslateMsg(c, "BindFail"))
  148. return
  149. }
  150. c.String(http.StatusOK, response.TranslateMsg(c, "BindSuccess"))
  151. return
  152. } else if ac == service.OauthActionTypeLogin {
  153. //登录
  154. if v.UserId != 0 {
  155. c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBeenSuccess"))
  156. return
  157. }
  158. u := service.AllService.UserService.InfoByGithubId(strconv.Itoa(userData.Id))
  159. if u == nil {
  160. oa := service.AllService.OauthService.InfoByOp(ty)
  161. if !*oa.AutoRegister {
  162. //c.String(http.StatusInternalServerError, "还未绑定用户,请先绑定")
  163. v.ThirdName = userData.Login
  164. v.ThirdOpenId = strconv.Itoa(userData.Id)
  165. url := global.Config.Rustdesk.ApiServer + "/_admin/#/oauth/bind/" + cacheKey
  166. c.Redirect(http.StatusFound, url)
  167. return
  168. }
  169. //自动注册
  170. u = service.AllService.UserService.RegisterByGithub(userData.Login, strconv.Itoa(userData.Id))
  171. if u.Id == 0 {
  172. c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthRegisterFailed"))
  173. return
  174. }
  175. }
  176. v.UserId = u.Id
  177. service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
  178. c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
  179. return
  180. }
  181. }
  182. if ty == model.OauthTypeGoogle {
  183. code := c.Query("code")
  184. err, userData := service.AllService.OauthService.GoogleCallback(code)
  185. if err != nil {
  186. c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthFailed")+response.TranslateMsg(c, err.Error()))
  187. return
  188. }
  189. //将空格替换成_
  190. googleName := strings.Replace(userData.Name, " ", "_", -1)
  191. if ac == service.OauthActionTypeBind {
  192. //fmt.Println("bind", ty, userData)
  193. utr := service.AllService.OauthService.UserThirdInfo(ty, userData.Email)
  194. if utr.UserId > 0 {
  195. c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBindOtherUser"))
  196. return
  197. }
  198. //绑定
  199. u := service.AllService.UserService.InfoById(v.UserId)
  200. if u == nil {
  201. c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ItemNotFound"))
  202. return
  203. }
  204. //绑定
  205. err = service.AllService.OauthService.BindGoogleUser(userData.Email, googleName, v.UserId)
  206. if err != nil {
  207. c.String(http.StatusInternalServerError, response.TranslateMsg(c, "BindFail"))
  208. return
  209. }
  210. c.String(http.StatusOK, response.TranslateMsg(c, "BindSuccess"))
  211. return
  212. } else if ac == service.OauthActionTypeLogin {
  213. if v.UserId != 0 {
  214. c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBeenSuccess"))
  215. return
  216. }
  217. u := service.AllService.UserService.InfoByGoogleEmail(userData.Email)
  218. if u == nil {
  219. oa := service.AllService.OauthService.InfoByOp(ty)
  220. if !*oa.AutoRegister {
  221. //c.String(http.StatusInternalServerError, "还未绑定用户,请先绑定")
  222. v.ThirdName = googleName
  223. v.ThirdOpenId = userData.Email
  224. url := global.Config.Rustdesk.ApiServer + "/_admin/#/oauth/bind/" + cacheKey
  225. c.Redirect(http.StatusFound, url)
  226. return
  227. }
  228. //自动注册
  229. u = service.AllService.UserService.RegisterByGoogle(googleName, userData.Email)
  230. if u.Id == 0 {
  231. c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthRegisterFailed"))
  232. return
  233. }
  234. }
  235. v.UserId = u.Id
  236. service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
  237. c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
  238. return
  239. }
  240. }
  241. if ty == model.OauthTypeOidc {
  242. code := c.Query("code")
  243. err, userData := service.AllService.OauthService.OidcCallback(code)
  244. if err != nil {
  245. c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthFailed")+response.TranslateMsg(c, err.Error()))
  246. return
  247. }
  248. //将空格替换成_
  249. // OidcName := strings.Replace(userData.Name, " ", "_", -1)
  250. if ac == service.OauthActionTypeBind {
  251. //fmt.Println("bind", ty, userData)
  252. utr := service.AllService.OauthService.UserThirdInfo(ty, userData.Sub)
  253. if utr.UserId > 0 {
  254. c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBindOtherUser"))
  255. return
  256. }
  257. //绑定
  258. u := service.AllService.UserService.InfoById(v.UserId)
  259. if u == nil {
  260. c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ItemNotFound"))
  261. return
  262. }
  263. //绑定, user preffered_username as username
  264. err = service.AllService.OauthService.BindOidcUser(userData.Sub, userData.PrefferedUsername, v.UserId)
  265. if err != nil {
  266. c.String(http.StatusInternalServerError, response.TranslateMsg(c, "BindFail"))
  267. return
  268. }
  269. c.String(http.StatusOK, response.TranslateMsg(c, "BindSuccess"))
  270. return
  271. } else if ac == service.OauthActionTypeLogin {
  272. if v.UserId != 0 {
  273. c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBeenSuccess"))
  274. return
  275. }
  276. u := service.AllService.UserService.InfoByOidcSub(userData.Sub)
  277. if u == nil {
  278. oa := service.AllService.OauthService.InfoByOp(ty)
  279. if !*oa.AutoRegister {
  280. //c.String(http.StatusInternalServerError, "还未绑定用户,请先绑定")
  281. v.ThirdName = userData.PrefferedUsername
  282. v.ThirdOpenId = userData.Sub
  283. url := global.Config.Rustdesk.ApiServer + "/_admin/#/oauth/bind/" + cacheKey
  284. c.Redirect(http.StatusFound, url)
  285. return
  286. }
  287. //自动注册
  288. u = service.AllService.UserService.RegisterByOidc(userData.PrefferedUsername, userData.Sub)
  289. if u.Id == 0 {
  290. c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthRegisterFailed"))
  291. return
  292. }
  293. }
  294. v.UserId = u.Id
  295. service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
  296. c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
  297. return
  298. }
  299. }
  300. c.String(http.StatusInternalServerError, response.TranslateMsg(c, "SystemError"))
  301. }