add oauth loginlog & fix bugs

This commit is contained in:
ljw
2024-09-19 10:44:49 +08:00
parent ebd1feb8d1
commit a4b413dadb
48 changed files with 3477 additions and 184 deletions

View File

@@ -5,6 +5,7 @@ import (
"Gwen/http/request/admin"
"Gwen/http/response"
adResp "Gwen/http/response/admin"
"Gwen/model"
"Gwen/service"
"github.com/gin-gonic/gin"
)
@@ -43,7 +44,14 @@ func (ct *Login) Login(c *gin.Context) {
return
}
ut := service.AllService.UserService.Login(u)
ut := service.AllService.UserService.Login(u, &model.LoginLog{
UserId: u.Id,
Client: "webadmin",
Uuid: "",
Ip: c.ClientIP(),
Type: "account",
Platform: f.Platform,
})
response.Success(c, &adResp.LoginPayload{
Token: ut.Token,

View File

@@ -0,0 +1,110 @@
package admin
import (
"Gwen/global"
"Gwen/http/request/admin"
"Gwen/http/response"
"Gwen/model"
"Gwen/service"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"strconv"
)
type LoginLog struct {
}
// Detail 登录日志
// @Tags 登录日志
// @Summary 登录日志详情
// @Description 登录日志详情
// @Accept json
// @Produce json
// @Param id path int true "ID"
// @Success 200 {object} response.Response{data=model.LoginLog}
// @Failure 500 {object} response.Response
// @Router /admin/loginLog/detail/{id} [get]
// @Security token
func (ct *LoginLog) Detail(c *gin.Context) {
id := c.Param("id")
iid, _ := strconv.Atoi(id)
u := service.AllService.LoginLogService.InfoById(uint(iid))
if u.Id > 0 {
response.Success(c, u)
return
}
response.Fail(c, 101, "信息不存在")
return
}
// List 列表
// @Tags 登录日志
// @Summary 登录日志列表
// @Description 登录日志列表
// @Accept json
// @Produce json
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Param user_id query int false "用户ID"
// @Success 200 {object} response.Response{data=model.LoginLogList}
// @Failure 500 {object} response.Response
// @Router /admin/loginLog/list [get]
// @Security token
func (ct *LoginLog) List(c *gin.Context) {
query := &admin.LoginLogQuery{}
if err := c.ShouldBindQuery(query); err != nil {
response.Fail(c, 101, "参数错误")
return
}
u := service.AllService.UserService.CurUser(c)
if !service.AllService.UserService.IsAdmin(u) || query.IsMy == 1 {
query.UserId = int(u.Id)
}
res := service.AllService.LoginLogService.List(query.Page, query.PageSize, func(tx *gorm.DB) {
if query.UserId > 0 {
tx.Where("user_id = ?", query.UserId)
}
})
response.Success(c, res)
}
// Delete 删除
// @Tags 登录日志
// @Summary 登录日志删除
// @Description 登录日志删除
// @Accept json
// @Produce json
// @Param body body model.LoginLog true "登录日志信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/loginLog/delete [post]
// @Security token
func (ct *LoginLog) Delete(c *gin.Context) {
f := &model.LoginLog{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "系统错误")
return
}
id := f.Id
errList := global.Validator.ValidVar(id, "required,gt=0")
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
}
l := service.AllService.LoginLogService.InfoById(f.Id)
u := service.AllService.UserService.CurUser(c)
if !service.AllService.UserService.IsAdmin(u) && l.UserId != u.Id {
response.Fail(c, 101, "无权限")
return
}
if l.Id > 0 {
err := service.AllService.LoginLogService.Delete(l)
if err == nil {
response.Success(c, nil)
return
}
response.Fail(c, 101, err.Error())
return
}
response.Fail(c, 101, "信息不存在")
}

View File

@@ -0,0 +1,291 @@
package admin
import (
"Gwen/global"
"Gwen/http/request/admin"
adminReq "Gwen/http/request/admin"
"Gwen/http/response"
"Gwen/model"
"Gwen/service"
"github.com/gin-gonic/gin"
"strconv"
)
type Oauth struct {
}
// Info
func (o *Oauth) Info(c *gin.Context) {
code := c.Query("code")
if code == "" {
response.Fail(c, 101, "参数错误")
return
}
v := service.AllService.OauthService.GetOauthCache(code)
if v == nil {
response.Fail(c, 101, "信息不存在")
return
}
response.Success(c, v)
}
func (o *Oauth) ToBind(c *gin.Context) {
f := &adminReq.BindOauthForm{}
err := c.ShouldBindJSON(f)
if err != nil {
response.Fail(c, 101, "参数错误")
return
}
u := service.AllService.UserService.CurUser(c)
utr := service.AllService.UserService.UserThirdInfo(u.Id, f.Op)
if utr.Id > 0 {
response.Fail(c, 101, "已绑定过了")
return
}
err, code, url := service.AllService.OauthService.BeginAuth(f.Op)
if err != nil {
response.Error(c, err.Error())
return
}
service.AllService.OauthService.SetOauthCache(code, &service.OauthCacheItem{
Action: service.OauthActionTypeBind,
Op: f.Op,
UserId: u.Id,
}, 5*60)
response.Success(c, gin.H{
"code": code,
"url": url,
})
}
// Confirm 确认授权登录
func (o *Oauth) Confirm(c *gin.Context) {
j := &adminReq.OauthConfirmForm{}
err := c.ShouldBindJSON(j)
if err != nil {
response.Fail(c, 101, "参数错误"+err.Error())
return
}
if j.Code == "" {
response.Fail(c, 101, "参数错误: code 不存在")
return
}
v := service.AllService.OauthService.GetOauthCache(j.Code)
if v == nil {
response.Fail(c, 101, "授权已过期")
return
}
u := service.AllService.UserService.CurUser(c)
v.UserId = u.Id
service.AllService.OauthService.SetOauthCache(j.Code, v, 0)
response.Success(c, v)
}
func (o *Oauth) BindConfirm(c *gin.Context) {
j := &adminReq.OauthConfirmForm{}
err := c.ShouldBindJSON(j)
if err != nil {
response.Fail(c, 101, "参数错误"+err.Error())
return
}
if j.Code == "" {
response.Fail(c, 101, "参数错误: code 不存在")
return
}
v := service.AllService.OauthService.GetOauthCache(j.Code)
if v == nil {
response.Fail(c, 101, "授权已过期")
return
}
u := service.AllService.UserService.CurUser(c)
err = service.AllService.OauthService.BindGithubUser(v.ThirdOpenId, v.ThirdOpenId, u.Id)
if err != nil {
response.Fail(c, 101, "绑定失败,请重试")
return
}
v.UserId = u.Id
service.AllService.OauthService.SetOauthCache(j.Code, v, 0)
response.Success(c, v)
}
func (o *Oauth) Unbind(c *gin.Context) {
f := &adminReq.UnBindOauthForm{}
err := c.ShouldBindJSON(f)
if err != nil {
response.Fail(c, 101, "参数错误")
return
}
u := service.AllService.UserService.CurUser(c)
utr := service.AllService.UserService.UserThirdInfo(u.Id, f.Op)
if utr.Id == 0 {
response.Fail(c, 101, "未绑定")
return
}
if f.Op == model.OauthTypeGithub {
err = service.AllService.OauthService.UnBindGithubUser(u.Id)
if err != nil {
response.Fail(c, 101, "解绑失败")
return
}
}
response.Success(c, nil)
}
// Detail Oauth
// @Tags Oauth
// @Summary Oauth详情
// @Description Oauth详情
// @Accept json
// @Produce json
// @Param id path int true "ID"
// @Success 200 {object} response.Response{data=model.Oauth}
// @Failure 500 {object} response.Response
// @Router /admin/oauth/detail/{id} [get]
// @Security token
func (o *Oauth) Detail(c *gin.Context) {
id := c.Param("id")
iid, _ := strconv.Atoi(id)
u := service.AllService.OauthService.InfoById(uint(iid))
if u.Id > 0 {
response.Success(c, u)
return
}
response.Fail(c, 101, "信息不存在")
return
}
// Create 创建Oauth
// @Tags Oauth
// @Summary 创建Oauth
// @Description 创建Oauth
// @Accept json
// @Produce json
// @Param body body admin.OauthForm true "Oauth信息"
// @Success 200 {object} response.Response{data=model.Oauth}
// @Failure 500 {object} response.Response
// @Router /admin/oauth/create [post]
// @Security token
func (o *Oauth) Create(c *gin.Context) {
f := &admin.OauthForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "参数错误"+err.Error())
return
}
errList := global.Validator.ValidStruct(f)
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
}
ex := service.AllService.OauthService.InfoByOp(f.Op)
if ex.Id > 0 {
response.Fail(c, 101, "已存在"+f.Op)
return
}
u := f.ToOauth()
err := service.AllService.OauthService.Create(u)
if err != nil {
response.Fail(c, 101, "创建失败")
return
}
response.Success(c, u)
}
// List 列表
// @Tags Oauth
// @Summary Oauth列表
// @Description Oauth列表
// @Accept json
// @Produce json
// @Param page query int false "页码"
// @Param page_size query int false "页大小"
// @Success 200 {object} response.Response{data=model.OauthList}
// @Failure 500 {object} response.Response
// @Router /admin/oauth/list [get]
// @Security token
func (o *Oauth) List(c *gin.Context) {
query := &admin.PageQuery{}
if err := c.ShouldBindQuery(query); err != nil {
response.Fail(c, 101, "参数错误")
return
}
res := service.AllService.OauthService.List(query.Page, query.PageSize, nil)
response.Success(c, res)
}
// Update 编辑
// @Tags Oauth
// @Summary Oauth编辑
// @Description Oauth编辑
// @Accept json
// @Produce json
// @Param body body admin.OauthForm true "Oauth信息"
// @Success 200 {object} response.Response{data=model.OauthList}
// @Failure 500 {object} response.Response
// @Router /admin/oauth/update [post]
// @Security token
func (o *Oauth) Update(c *gin.Context) {
f := &admin.OauthForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "参数错误")
return
}
if f.Id == 0 {
response.Fail(c, 101, "参数错误")
return
}
errList := global.Validator.ValidStruct(f)
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
}
u := f.ToOauth()
err := service.AllService.OauthService.Update(u)
if err != nil {
response.Fail(c, 101, "更新失败")
return
}
response.Success(c, nil)
}
// Delete 删除
// @Tags Oauth
// @Summary Oauth删除
// @Description Oauth删除
// @Accept json
// @Produce json
// @Param body body admin.OauthForm true "Oauth信息"
// @Success 200 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /admin/oauth/delete [post]
// @Security token
func (o *Oauth) Delete(c *gin.Context) {
f := &admin.OauthForm{}
if err := c.ShouldBindJSON(f); err != nil {
response.Fail(c, 101, "系统错误")
return
}
id := f.Id
errList := global.Validator.ValidVar(id, "required,gt=0")
if len(errList) > 0 {
response.Fail(c, 101, errList[0])
return
}
u := service.AllService.OauthService.InfoById(f.Id)
if u.Id > 0 {
err := service.AllService.OauthService.Delete(u)
if err == nil {
response.Success(c, nil)
return
}
response.Fail(c, 101, err.Error())
return
}
response.Fail(c, 101, "信息不存在")
}

View File

@@ -259,3 +259,37 @@ func (ct *User) ChangeCurPwd(c *gin.Context) {
}
response.Success(c, nil)
}
// MyOauth
// @Tags 用户
// @Summary 我的授权
// @Description 我的授权
// @Accept json
// @Produce json
// @Success 200 {object} response.Response{data=[]adResp.UserOauthItem}
// @Failure 500 {object} response.Response
// @Router /admin/user/myOauth [get]
// @Security token
func (ct *User) MyOauth(c *gin.Context) {
u := service.AllService.UserService.CurUser(c)
oal := service.AllService.OauthService.List(1, 100, nil)
ops := make([]string, 0)
for _, oa := range oal.Oauths {
ops = append(ops, oa.Op)
}
uts := service.AllService.UserService.UserThirdsByUserId(u.Id)
var res []*adResp.UserOauthItem
for _, oa := range oal.Oauths {
item := &adResp.UserOauthItem{
ThirdType: oa.Op,
}
for _, ut := range uts {
if ut.ThirdType == oa.Op {
item.Status = 1
break
}
}
res = append(res, item)
}
response.Success(c, res)
}

View File

@@ -7,7 +7,6 @@ import (
"Gwen/model"
"Gwen/service"
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
)
@@ -66,7 +65,6 @@ func (a *Ab) UpAb(c *gin.Context) {
abf := &requstform.AddressBookForm{}
err := c.ShouldBindJSON(&abf)
if err != nil {
fmt.Println(err)
response.Error(c, "参数错误")
return
}
@@ -93,7 +91,6 @@ func (a *Ab) UpAb(c *gin.Context) {
tc := map[string]uint{}
err = json.Unmarshal([]byte(abd.TagColors), &tc)
if err != nil {
fmt.Println(err)
response.Error(c, "系统错误")
return
} else {
@@ -134,7 +131,6 @@ func (a *Ab) TagAdd(c *gin.Context) {
t := &model.Tag{}
err := c.ShouldBindJSON(t)
if err != nil {
fmt.Println(err)
response.Error(c, "参数错误")
return

View File

@@ -5,7 +5,9 @@ import (
"Gwen/http/request/api"
"Gwen/http/response"
apiResp "Gwen/http/response/api"
"Gwen/model"
"Gwen/service"
"encoding/json"
"github.com/gin-gonic/gin"
"net/http"
)
@@ -26,8 +28,9 @@ type Login struct {
func (l *Login) Login(c *gin.Context) {
f := &api.LoginForm{}
err := c.ShouldBindJSON(f)
//fmt.Println(f)
if err != nil {
response.Error(c, "系统错误")
response.Error(c, "参数错误")
return
}
@@ -44,7 +47,20 @@ func (l *Login) Login(c *gin.Context) {
return
}
ut := service.AllService.UserService.Login(u)
//根据refer判断是webclient还是app
ref := c.GetHeader("referer")
if ref != "" {
f.DeviceInfo.Type = "webclient"
}
ut := service.AllService.UserService.Login(u, &model.LoginLog{
UserId: u.Id,
Client: f.DeviceInfo.Type,
Uuid: f.Uuid,
Ip: c.ClientIP(),
Type: model.LoginLogTypeAccount,
Platform: f.DeviceInfo.Os,
})
c.JSON(http.StatusOK, apiResp.LoginRes{
AccessToken: ut.Token,
@@ -63,11 +79,31 @@ func (l *Login) Login(c *gin.Context) {
// @Failure 500 {object} response.ErrorResponse
// @Router /login-options [post]
func (l *Login) LoginOptions(c *gin.Context) {
test := []string{
//"common-oidc/[{\"name\":\"google\"},{\"name\":\"github\"},{\"name\":\"facebook\"},{\"name\":\"网页授权登录\",\"icon\":\"\"}]",
//"oidc/myapp",
oauthOks := []string{}
err, _ := service.AllService.OauthService.GetOauthConfig(model.OauthTypeGithub)
if err == nil {
oauthOks = append(oauthOks, model.OauthTypeGithub)
}
c.JSON(http.StatusOK, test)
err, _ = service.AllService.OauthService.GetOauthConfig(model.OauthTypeGoogle)
if err == nil {
oauthOks = append(oauthOks, model.OauthTypeGoogle)
}
oauthOks = append(oauthOks, model.OauthTypeWebauth)
var oidcItems []map[string]string
for _, v := range oauthOks {
oidcItems = append(oidcItems, map[string]string{"name": v})
}
common, err := json.Marshal(oidcItems)
if err != nil {
response.Error(c, "参数错误")
return
}
var res []string
res = append(res, "common-oidc/"+string(common))
for _, v := range oauthOks {
res = append(res, "oidc/"+v)
}
c.JSON(http.StatusOK, res)
}
// Logout

View File

@@ -0,0 +1,222 @@
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"
)
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, "参数错误")
return
}
if f.Op != model.OauthTypeWebauth && f.Op != model.OauthTypeGoogle && f.Op != model.OauthTypeGithub {
response.Error(c, "参数错误")
return
}
err, code, url := service.AllService.OauthService.BeginAuth(f.Op)
if err != nil {
response.Error(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,
})
}
// 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) {
q := &api.OidcAuthQuery{}
err := c.ShouldBindQuery(q)
if err != nil {
response.Error(c, "参数错误")
return
}
v := service.AllService.OauthService.GetOauthCache(q.Code)
if v == nil {
response.Error(c, "授权已过期,请重新授权")
return
}
if v.UserId == 0 {
//正在授权
c.JSON(http.StatusOK, gin.H{})
return
}
u := service.AllService.UserService.InfoById(v.UserId)
//fmt.Println("auth success u", u)
if u.Id > 0 {
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,
})
c.JSON(http.StatusOK, apiResp.LoginRes{
AccessToken: ut.Token,
Type: "access_token",
User: *(&apiResp.UserPayload{}).FromUser(u),
})
return
}
response.Error(c, "用户不存在")
}
// 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, "state为空")
return
}
cacheKey := state
//从缓存中获取
v := service.AllService.OauthService.GetOauthCache(cacheKey)
if v == nil {
c.String(http.StatusInternalServerError, "授权已过期,请重新授权")
return
}
ty := v.Op
ac := v.Action
//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, "授权失败:"+err.Error())
return
}
if ac == service.OauthActionTypeBind {
//fmt.Println("bind", ty, userData)
utr := service.AllService.OauthService.UserThirdInfo(ty, strconv.Itoa(userData.Id))
if utr.UserId > 0 {
c.String(http.StatusInternalServerError, "已经绑定其他账号")
return
}
//绑定
u := service.AllService.UserService.InfoById(v.UserId)
if u == nil {
c.String(http.StatusInternalServerError, "用户不存在")
return
}
//绑定github
err = service.AllService.OauthService.BindGithubUser(strconv.Itoa(userData.Id), userData.Login, v.UserId)
if err != nil {
c.String(http.StatusInternalServerError, "绑定失败")
return
}
c.String(http.StatusOK, "绑定成功")
return
}
//登录
if ac == service.OauthActionTypeLogin {
if v.UserId != 0 {
c.String(http.StatusInternalServerError, "授权已经成功")
return
}
u := service.AllService.UserService.InfoByGithubId(strconv.Itoa(userData.Id))
if u == nil {
oa := service.AllService.OauthService.InfoByOp(ty)
if !*oa.AutoRegister {
//c.String(http.StatusInternalServerError, "还未绑定用户,请先绑定")
v.ThirdName = userData.Login
v.ThirdOpenId = strconv.Itoa(userData.Id)
url := global.Config.Rustdesk.ApiServer + "/_admin/#/oauth/bind/" + cacheKey
c.Redirect(http.StatusFound, url)
return
}
//自动注册
u = service.AllService.UserService.RegisterByGithub(userData.Login, int64(userData.Id))
if u.Id == 0 {
c.String(http.StatusInternalServerError, "注册失败")
return
}
}
v.UserId = u.Id
service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
c.String(http.StatusOK, "授权成功")
return
}
//返回js
c.Header("Content-Type", "text/html; charset=utf-8")
c.String(http.StatusOK, "授权错误")
//up := &apiResp.UserPayload{}
//c.JSON(http.StatusOK, apiResp.LoginRes{
// AccessToken: ut.Token,
// Type: "access_token",
// User: *up.FromUser(u),
//})
}
}
// WebOauthLogin
// @Tags Oauth
// @Summary WebOauthLogin
// @Description WebOauthLogin
// @Accept json
// @Produce json
// @Success 200 {string} string
// @Failure 500 {string} string
// @Router /oauth/login [get]
func (o *Oauth) WebOauthLogin(c *gin.Context) {
}

View File

@@ -21,11 +21,11 @@ type User struct {
// @Failure 500 {object} response.Response
// @Router /currentUser [get]
// @Security token
func (u *User) currentUser(c *gin.Context) {
user := service.AllService.UserService.CurUser(c)
up := (&apiResp.UserPayload{}).FromUser(user)
c.JSON(http.StatusOK, up)
}
//func (u *User) currentUser(c *gin.Context) {
// user := service.AllService.UserService.CurUser(c)
// up := (&apiResp.UserPayload{}).FromUser(user)
// c.JSON(http.StatusOK, up)
//}
// Info 用户信息
// @Tags 用户

View File

@@ -36,7 +36,7 @@ func (i *WebClient) ServerConfig(c *gin.Context) {
gin.H{
"id_server": global.Config.Rustdesk.IdServer,
"key": global.Config.Rustdesk.Key,
//"peers": peers,
"peers": peers,
},
)
}

View File

@@ -53,7 +53,13 @@ const autoWriteServer = () => {
}
if (res.data.peers) {
localStorage.setItem('peers', JSON.stringify(res.data.peers))
oldPeers = JSON.parse(localStorage.getItem('peers')) || {}
Object.keys(res.data.peers).forEach(k => {
if(!oldPeers[k]) {
oldPeers[k] = res.data.peers[k]
}
})
localStorage.setItem('peers', JSON.stringify(oldPeers))
}
}
})

View File

@@ -7,12 +7,23 @@ import (
"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
"net/http"
"strings"
)
func ApiInit() {
gin.SetMode(global.Config.Gin.Mode)
g := gin.New()
//[WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
//Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
if global.Config.Gin.TrustProxy != "" {
pro := strings.Split(global.Config.Gin.TrustProxy, ",")
err := g.SetTrustedProxies(pro)
if err != nil {
panic(err)
}
}
if global.Config.Gin.Mode == gin.ReleaseMode {
//修改gin Recovery日志 输出为logger的输出点
if global.Logger != nil {

View File

@@ -17,6 +17,13 @@ func RustAuth() gin.HandlerFunc {
c.Abort()
return
}
if len(token) <= 7 {
c.JSON(401, gin.H{
"error": "Unauthorized",
})
c.Abort()
return
}
//提取token格式是Bearer {token}
//这里只是简单的提取
token = token[7:]

View File

@@ -3,4 +3,11 @@ package admin
type Login struct {
Username string `json:"username" validate:"required" label:"用户名"`
Password string `json:"password,omitempty" validate:"required" label:"密码"`
Platform string `json:"platform" label:"平台"`
}
type LoginLogQuery struct {
UserId int `form:"user_id"`
IsMy int `form:"is_my"`
PageQuery
}

View File

@@ -0,0 +1,34 @@
package admin
import "Gwen/model"
type BindOauthForm struct {
Op string `json:"op" binding:"required"`
}
type OauthConfirmForm struct {
Code string `json:"code" binding:"required"`
}
type UnBindOauthForm struct {
Op string `json:"op" binding:"required"`
}
type OauthForm struct {
Id uint `json:"id"`
Op string `json:"op" validate:"required"`
ClientId string `json:"client_id" validate:"required"`
ClientSecret string `json:"client_secret" validate:"required"`
RedirectUrl string `json:"redirect_url" validate:"required"`
AutoRegister *bool `json:"auto_register"`
}
func (of *OauthForm) ToOauth() *model.Oauth {
oa := &model.Oauth{
Op: of.Op,
ClientId: of.ClientId,
ClientSecret: of.ClientSecret,
RedirectUrl: of.RedirectUrl,
AutoRegister: of.AutoRegister,
}
oa.Id = of.Id
return oa
}

14
http/request/api/oauth.go Normal file
View File

@@ -0,0 +1,14 @@
package api
type OidcAuthRequest struct {
DeviceInfo DeviceInfoInLogin `json:"deviceInfo" label:"设备信息"`
Id string `json:"id" label:"id"`
Op string `json:"op" label:"op"`
Uuid string `json:"uuid" label:"uuid"`
}
type OidcAuthQuery struct {
Code string `json:"code" form:"code" label:"code"`
Id string `json:"id" form:"id" label:"id"`
Uuid string `json:"uuid" form:"uuid" label:"uuid"`
}

View File

@@ -21,9 +21,21 @@ package api
bytes hwid = 14;
}
*/
type DeviceInfoInLogin struct {
Name string `json:"name" label:"name"`
Os string `json:"os" label:"os"`
Type string `json:"type" label:"type"`
}
type LoginForm struct {
Username string `json:"username" validate:"required,gte=4,lte=10" label:"用户名"`
Password string `json:"password,omitempty" validate:"gte=4,lte=20" label:"密码"`
AutoLogin bool `json:"autoLogin" label:"自动登录"`
DeviceInfo DeviceInfoInLogin `json:"deviceInfo" label:"设备信息"`
Id string `json:"id" label:"id"`
Type string `json:"type" label:"type"`
Uuid string `json:"uuid" label:"uuid"`
Username string `json:"username" validate:"required,gte=4,lte=10" label:"用户名"`
Password string `json:"password,omitempty" validate:"gte=4,lte=20" label:"密码"`
}
type UserListQuery struct {

View File

@@ -8,6 +8,11 @@ type LoginPayload struct {
}
var UserRouteNames = []string{
"MyTagList", "MyAddressBookList",
"MyTagList", "MyAddressBookList", "MyInfo",
}
var AdminRouteNames = []string{"*"}
type UserOauthItem struct {
ThirdType string `json:"third_type"`
Status int `json:"status"`
}

View File

@@ -19,17 +19,19 @@ UserStatus status;
bool isAdmin = false;
*/
type UserPayload struct {
Name string `json:"name"`
Email string `json:"email"`
Note string `json:"note"`
IsAdmin *bool `json:"is_admin"`
Status int `json:"status"`
Name string `json:"name"`
Email string `json:"email"`
Note string `json:"note"`
IsAdmin *bool `json:"is_admin"`
Status int `json:"status"`
Info map[string]interface{} `json:"info"`
}
func (up *UserPayload) FromUser(user *model.User) *UserPayload {
up.Name = user.Username
up.IsAdmin = user.IsAdmin
up.Status = int(user.Status)
up.Info = map[string]interface{}{}
return up
}
@@ -50,6 +52,6 @@ type LoginRes struct {
Type string `json:"type"`
AccessToken string `json:"access_token"`
User UserPayload `json:"user"`
Secret string `json:"secret"`
TfaType string `json:"tfa_type"`
Secret string `json:"secret,omitempty"`
TfaType string `json:"tfa_type,omitempty"`
}

View File

@@ -5,33 +5,6 @@ import (
"time"
)
// type T struct {
// Field1 struct {
// ViewStyle string `json:"view-style"`
// Tm int64 `json:"tm"`
// Info struct {
// Username string `json:"username"`
// Hostname string `json:"hostname"`
// Platform string `json:"platform"`
// Displays []struct {
// X int `json:"x"`
// Y int `json:"y"`
// Width int `json:"width"`
// Height int `json:"height"`
// Name string `json:"name"`
// Online bool `json:"online"`
// } `json:"displays"`
// CurrentDisplay int `json:"current_display"`
// SasEnabled bool `json:"sas_enabled"`
// Version string `json:"version"`
// ConnId int `json:"conn_id"`
// Features struct {
// PrivacyMode bool `json:"privacy_mode"`
// } `json:"features"`
// } `json:"info"`
// } `json:"1799928825"`
// }
type WebClientPeerPayload struct {
ViewStyle string `json:"view-style"`
Tm int64 `json:"tm"`
@@ -46,7 +19,8 @@ type WebClientPeerInfoPayload struct {
func (wcpp *WebClientPeerPayload) FromAddressBook(a *model.AddressBook) {
wcpp.ViewStyle = "shrink"
wcpp.Tm = time.Now().UnixNano()
//24小时前
wcpp.Tm = time.Now().Add(-time.Hour * 24).UnixNano()
wcpp.Info = WebClientPeerInfoPayload{
Username: a.Username,
Hostname: a.Hostname,

View File

@@ -25,6 +25,8 @@ func Init(g *gin.Engine) {
TagBind(adg)
AddressBookBind(adg)
PeerBind(adg)
OauthBind(adg)
LoginLogBind(adg)
rs := &admin.Rustdesk{}
adg.GET("/server-config", rs.ServerConfig)
@@ -44,6 +46,7 @@ func UserBind(rg *gin.RouterGroup) {
cont := &admin.User{}
aR.GET("/current", cont.Current)
aR.POST("/changeCurPwd", cont.ChangeCurPwd)
aR.POST("/myOauth", cont.MyOauth)
}
aRP := rg.Group("/user").Use(middleware.AdminPrivilege())
{
@@ -104,6 +107,35 @@ func PeerBind(rg *gin.RouterGroup) {
}
}
func OauthBind(rg *gin.RouterGroup) {
aR := rg.Group("/oauth")
{
cont := &admin.Oauth{}
aR.POST("/confirm", cont.Confirm)
aR.POST("/bind", cont.ToBind)
aR.POST("/bindConfirm", cont.BindConfirm)
aR.POST("/unbind", cont.Unbind)
aR.GET("/info", cont.Info)
}
arp := aR.Use(middleware.AdminPrivilege())
{
cont := &admin.Oauth{}
arp.GET("/list", cont.List)
arp.GET("/detail/:id", cont.Detail)
arp.POST("/create", cont.Create)
arp.POST("/update", cont.Update)
arp.POST("/delete", cont.Delete)
}
}
func LoginLogBind(rg *gin.RouterGroup) {
aR := rg.Group("/login_log")
cont := &admin.LoginLog{}
aR.GET("/list", cont.List)
aR.POST("/delete", cont.Delete)
}
/*
func FileBind(rg *gin.RouterGroup) {
aR := rg.Group("/file")

View File

@@ -19,7 +19,7 @@ func ApiInit(g *gin.Engine) {
frg := g.Group("/api")
frg.Use(middleware.Cors())
//frg.Use(middleware.Cors())
frg.OPTIONS("/*any", nil)
i := &api.Index{}
@@ -34,6 +34,16 @@ func ApiInit(g *gin.Engine) {
frg.POST("/login", l.Login)
}
{
o := &api.Oauth{}
// [method:POST] [uri:/api/oidc/auth]
frg.POST("/oidc/auth", o.OidcAuth)
// [method:GET] [uri:/api/oidc/auth-query?code=abc&id=xxxxx&uuid=xxxxx]
frg.GET("/oidc/auth-query", o.OidcAuthQuery)
//api/oauth/callback
frg.GET("/oauth/callback", o.OauthCallback)
frg.GET("/oauth/login", o.OauthCallback)
}
{
pe := &api.Peer{}
//提交系统信息