mirror of
https://github.com/lejianwen/rustdesk-api.git
synced 2025-11-29 16:43:17 +00:00
272 lines
7.5 KiB
Go
272 lines
7.5 KiB
Go
package api
|
||
|
||
import (
|
||
"Gwen/global"
|
||
"Gwen/http/request/api"
|
||
"Gwen/http/response"
|
||
apiResp "Gwen/http/response/api"
|
||
"Gwen/model"
|
||
"Gwen/service"
|
||
"github.com/gin-gonic/gin"
|
||
"net/http"
|
||
"strconv"
|
||
"strings"
|
||
)
|
||
|
||
type Oauth struct {
|
||
}
|
||
|
||
// OidcAuth
|
||
// @Tags Oauth
|
||
// @Summary OidcAuth
|
||
// @Description OidcAuth
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Success 200 {object} apiResp.LoginRes
|
||
// @Failure 500 {object} response.ErrorResponse
|
||
// @Router /oidc/auth [post]
|
||
func (o *Oauth) OidcAuth(c *gin.Context) {
|
||
f := &api.OidcAuthRequest{}
|
||
err := c.ShouldBindJSON(&f)
|
||
if err != nil {
|
||
response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
|
||
return
|
||
}
|
||
//fmt.Println(f)
|
||
if f.Op != model.OauthTypeWebauth && f.Op != model.OauthTypeGoogle && f.Op != model.OauthTypeGithub && f.Op != model.OauthTypeOidc {
|
||
response.Error(c, response.TranslateMsg(c, "ParamsError"))
|
||
return
|
||
}
|
||
|
||
err, code, url := service.AllService.OauthService.BeginAuth(f.Op)
|
||
if err != nil {
|
||
response.Error(c, response.TranslateMsg(c, err.Error()))
|
||
return
|
||
}
|
||
|
||
service.AllService.OauthService.SetOauthCache(code, &service.OauthCacheItem{
|
||
Action: service.OauthActionTypeLogin,
|
||
Id: f.Id,
|
||
Op: f.Op,
|
||
Uuid: f.Uuid,
|
||
DeviceName: f.DeviceInfo.Name,
|
||
DeviceOs: f.DeviceInfo.Os,
|
||
DeviceType: f.DeviceInfo.Type,
|
||
}, 5*60)
|
||
//fmt.Println("code url", code, url)
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"code": code,
|
||
"url": url,
|
||
})
|
||
}
|
||
|
||
func (o *Oauth) OidcAuthQueryPre(c *gin.Context) (*model.User, *model.UserToken) {
|
||
var u *model.User
|
||
var ut *model.UserToken
|
||
q := &api.OidcAuthQuery{}
|
||
|
||
// 解析查询参数并处理错误
|
||
if err := c.ShouldBindQuery(q); err != nil {
|
||
response.Error(c, response.TranslateMsg(c, "ParamsError")+": "+err.Error())
|
||
return nil, nil
|
||
}
|
||
|
||
// 获取 OAuth 缓存
|
||
v := service.AllService.OauthService.GetOauthCache(q.Code)
|
||
if v == nil {
|
||
response.Error(c, response.TranslateMsg(c, "OauthExpired"))
|
||
return nil, nil
|
||
}
|
||
|
||
// 如果 UserId 为 0,说明还在授权中
|
||
if v.UserId == 0 {
|
||
c.JSON(http.StatusOK, gin.H{"message": "Authorization in progress, please login and bind"})
|
||
return nil, nil
|
||
}
|
||
|
||
// 获取用户信息
|
||
u = service.AllService.UserService.InfoById(v.UserId)
|
||
if u == nil {
|
||
response.Error(c, response.TranslateMsg(c, "UserNotFound"))
|
||
return nil, nil
|
||
}
|
||
|
||
// 删除 OAuth 缓存
|
||
service.AllService.OauthService.DeleteOauthCache(q.Code)
|
||
|
||
// 创建登录日志并生成用户令牌
|
||
ut = service.AllService.UserService.Login(u, &model.LoginLog{
|
||
UserId: u.Id,
|
||
Client: v.DeviceType,
|
||
Uuid: v.Uuid,
|
||
Ip: c.ClientIP(),
|
||
Type: model.LoginLogTypeOauth,
|
||
Platform: v.DeviceOs,
|
||
})
|
||
|
||
if ut == nil {
|
||
response.Error(c, response.TranslateMsg(c, "LoginFailed"))
|
||
return nil, nil
|
||
}
|
||
|
||
// 返回用户令牌
|
||
return u, ut
|
||
}
|
||
|
||
// OidcAuthQuery
|
||
// @Tags Oauth
|
||
// @Summary OidcAuthQuery
|
||
// @Description OidcAuthQuery
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Success 200 {object} apiResp.LoginRes
|
||
// @Failure 500 {object} response.ErrorResponse
|
||
// @Router /oidc/auth-query [get]
|
||
func (o *Oauth) OidcAuthQuery(c *gin.Context) {
|
||
u, ut := o.OidcAuthQueryPre(c)
|
||
if u == nil || ut == nil {
|
||
return
|
||
}
|
||
c.JSON(http.StatusOK, apiResp.LoginRes{
|
||
AccessToken: ut.Token,
|
||
Type: "access_token",
|
||
User: *(&apiResp.UserPayload{}).FromUser(u),
|
||
})
|
||
}
|
||
|
||
// OauthCallback 回调
|
||
// @Tags Oauth
|
||
// @Summary OauthCallback
|
||
// @Description OauthCallback
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Success 200 {object} apiResp.LoginRes
|
||
// @Failure 500 {object} response.ErrorResponse
|
||
// @Router /oauth/callback [get]
|
||
func (o *Oauth) OauthCallback(c *gin.Context) {
|
||
state := c.Query("state")
|
||
if state == "" {
|
||
c.String(http.StatusInternalServerError, response.TranslateParamMsg(c, "ParamIsEmpty", "state"))
|
||
return
|
||
}
|
||
|
||
cacheKey := state
|
||
//从缓存中获取
|
||
v := service.AllService.OauthService.GetOauthCache(cacheKey)
|
||
if v == nil {
|
||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthExpired"))
|
||
return
|
||
}
|
||
|
||
ty := v.Op
|
||
ac := v.Action
|
||
var u *model.User
|
||
openid := ""
|
||
thirdName := ""
|
||
//fmt.Println("ty ac ", ty, ac)
|
||
|
||
if ty == model.OauthTypeGithub {
|
||
code := c.Query("code")
|
||
err, userData := service.AllService.OauthService.GithubCallback(code)
|
||
if err != nil {
|
||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthFailed")+response.TranslateMsg(c, err.Error()))
|
||
return
|
||
}
|
||
openid = strconv.Itoa(userData.Id)
|
||
thirdName = userData.Login
|
||
} else if ty == model.OauthTypeGoogle {
|
||
code := c.Query("code")
|
||
err, userData := service.AllService.OauthService.GoogleCallback(code)
|
||
if err != nil {
|
||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthFailed")+response.TranslateMsg(c, err.Error()))
|
||
return
|
||
}
|
||
openid = userData.Email
|
||
//将空格替换成_
|
||
thirdName = strings.Replace(userData.Name, " ", "_", -1)
|
||
} else if ty == model.OauthTypeOidc {
|
||
code := c.Query("code")
|
||
err, userData := service.AllService.OauthService.OidcCallback(code)
|
||
if err != nil {
|
||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthFailed")+response.TranslateMsg(c, err.Error()))
|
||
return
|
||
}
|
||
openid = userData.Sub
|
||
thirdName = userData.PreferredUsername
|
||
} else {
|
||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ParamsError"))
|
||
return
|
||
}
|
||
if ac == service.OauthActionTypeBind {
|
||
|
||
//fmt.Println("bind", ty, userData)
|
||
utr := service.AllService.OauthService.UserThirdInfo(ty, openid)
|
||
if utr.UserId > 0 {
|
||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBindOtherUser"))
|
||
return
|
||
}
|
||
//绑定
|
||
u = service.AllService.UserService.InfoById(v.UserId)
|
||
if u == nil {
|
||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ItemNotFound"))
|
||
return
|
||
}
|
||
//绑定
|
||
err := service.AllService.OauthService.BindOauthUser(ty, openid, thirdName, v.UserId)
|
||
if err != nil {
|
||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "BindFail"))
|
||
return
|
||
}
|
||
c.String(http.StatusOK, response.TranslateMsg(c, "BindSuccess"))
|
||
return
|
||
|
||
} else if ac == service.OauthActionTypeLogin {
|
||
//登录
|
||
if v.UserId != 0 {
|
||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthHasBeenSuccess"))
|
||
return
|
||
}
|
||
u = service.AllService.UserService.InfoByGithubId(openid)
|
||
if u == nil {
|
||
oa := service.AllService.OauthService.InfoByOp(ty)
|
||
if !*oa.AutoRegister {
|
||
//c.String(http.StatusInternalServerError, "还未绑定用户,请先绑定")
|
||
v.ThirdName = thirdName
|
||
v.ThirdOpenId = openid
|
||
url := global.Config.Rustdesk.ApiServer + "/_admin/#/oauth/bind/" + cacheKey
|
||
c.Redirect(http.StatusFound, url)
|
||
return
|
||
}
|
||
|
||
//自动注册
|
||
u = service.AllService.UserService.RegisterByOauth(ty, thirdName, openid)
|
||
if u.Id == 0 {
|
||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "OauthRegisterFailed"))
|
||
return
|
||
}
|
||
}
|
||
v.UserId = u.Id
|
||
service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
|
||
// 如果是webadmin,登录成功后跳转到webadmin
|
||
if v.DeviceType == "webadmin" {
|
||
/*service.AllService.UserService.Login(u, &model.LoginLog{
|
||
UserId: u.Id,
|
||
Client: "webadmin",
|
||
Uuid: "", //must be empty
|
||
Ip: c.ClientIP(),
|
||
Type: model.LoginLogTypeOauth,
|
||
Platform: v.DeviceOs,
|
||
})*/
|
||
url := global.Config.Rustdesk.ApiServer + "/_admin/#/"
|
||
c.Redirect(http.StatusFound, url)
|
||
return
|
||
}
|
||
c.String(http.StatusOK, response.TranslateMsg(c, "OauthSuccess"))
|
||
return
|
||
} else {
|
||
c.String(http.StatusInternalServerError, response.TranslateMsg(c, "ParamsError"))
|
||
return
|
||
}
|
||
|
||
}
|