mirror of
https://github.com/lejianwen/rustdesk-api.git
synced 2026-02-19 02:41:31 +00:00
add oauth loginlog & fix bugs
This commit is contained in:
@@ -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,
|
||||
|
||||
110
http/controller/admin/loginLog.go
Normal file
110
http/controller/admin/loginLog.go
Normal 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, "信息不存在")
|
||||
}
|
||||
291
http/controller/admin/oauth.go
Normal file
291
http/controller/admin/oauth.go
Normal 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, "信息不存在")
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
222
http/controller/api/ouath.go
Normal file
222
http/controller/api/ouath.go
Normal 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) {
|
||||
|
||||
}
|
||||
@@ -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 用户
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
11
http/http.go
11
http/http.go
@@ -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 {
|
||||
|
||||
@@ -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:]
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
34
http/request/admin/oauth.go
Normal file
34
http/request/admin/oauth.go
Normal 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
14
http/request/api/oauth.go
Normal 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"`
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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{}
|
||||
//提交系统信息
|
||||
|
||||
Reference in New Issue
Block a user