Files
dify-plus/admin/server/api/v1/system/sys_user_extend.go
T
2025-04-19 12:17:18 +08:00

187 lines
6.8 KiB
Go

package system
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
"github.com/flipped-aurora/gin-vue-admin/server/model/system"
systemReq "github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
systemRes "github.com/flipped-aurora/gin-vue-admin/server/model/system/response"
"github.com/flipped-aurora/gin-vue-admin/server/utils"
"github.com/gin-gonic/gin"
"github.com/go-resty/resty/v2"
"go.uber.org/zap"
"gorm.io/gorm"
)
// Extend Start: sync user
// SyncUser
// @Tags Base
// @Summary 用户同步
// @Produce application/json
// @Param data body systemReq.Login true "用户名, 密码, 验证码"
// @Success 200 {object} response.Response{data=systemRes.LoginResponse,msg=string} "返回包括用户信息,token,过期时间"
// @Router /user/sync [post]
func (b *BaseApi) SyncUser(c *gin.Context) {
userExtendService.SyncUser()
response.OkWithMessage("同步中", c)
}
// Extend Stop: sync user
// OaLogin
// @Tags Base
// @Summary 用户登录
// @Produce application/json
// @Param data body systemReq.Login true "用户名, 密码, 验证码"
// @Success 200 {object} response.Response{data=systemRes.LoginResponse,msg=string} "返回包括用户信息,token,过期时间"
// @Router /base/oaLogin [post]
func (b *BaseApi) OaLogin(c *gin.Context) {
var l systemReq.OaLoginReq
err := c.ShouldBindJSON(&l)
if err != nil {
response.FailWithMessage(err.Error(), c)
return
}
err = utils.Verify(l, utils.OaLoginVerify)
if err != nil {
response.FailWithMessage(err.Error(), c)
return
}
/**
请求获取accessToken
*/
clientGetToken := resty.New().R()
var accessTokenResponse *resty.Response
getTokenUrl := fmt.Sprintf("%s%s", global.GVA_CONFIG.OaLogin.Url, global.GVA_CONFIG.OaLogin.GetTokenByCodeApiPath)
var postParams = map[string]string{
"client_id": global.GVA_CONFIG.OaLogin.Oauth2ClientId,
"client_secret": global.GVA_CONFIG.OaLogin.Oauth2ClientSecret,
"code": l.AuthorizeCode,
"grant_type": "authorization_code",
"redirect_uri": "",
}
accessTokenResponse, err = clientGetToken.
SetFormData(postParams).
Post(getTokenUrl)
if err != nil {
global.GVA_LOG.Error("请求OA用户信息失败,响应数据为:", zap.Error(errors.New(accessTokenResponse.String())))
response.FailWithMessage("请求OA用户信息失败:"+err.Error(), c)
return
}
tokenRes := accessTokenResponse.String()
var oaAccessToken systemRes.OaAccessTokenRes
err = json.Unmarshal([]byte(tokenRes), &oaAccessToken)
if err != nil {
global.GVA_LOG.Error("解析OA AccessToken接口返回数据失败,响应数据为:", zap.Error(errors.New(accessTokenResponse.String())))
response.FailWithMessage("解析OA AccessToken接口返回数据失败:"+err.Error(), c)
return
}
/**
请求OA,返回用户信息
*/
getUserInfoUrl := fmt.Sprintf("%s%s", global.GVA_CONFIG.OaLogin.Url, global.GVA_CONFIG.OaLogin.GetUserApiPath)
clientGetUser := resty.New().R()
var userInfoResponse *resty.Response
userInfoResponse, err = clientGetUser.SetHeader("Authorization", oaAccessToken.AccessToken).Post(getUserInfoUrl)
if err != nil {
global.GVA_LOG.Error("请求OA用户信息失败,响应数据为:", zap.Error(errors.New(userInfoResponse.String())))
response.FailWithMessage("请求OA用户信息失败:"+err.Error(), c)
return
}
userInfoRes := userInfoResponse.String()
var oaUserInfo systemRes.OaUserInfoRes
err = json.Unmarshal([]byte(userInfoRes), &oaUserInfo)
if err != nil {
global.GVA_LOG.Error("解析OA用户信息接口返回数据失败,响应数据为:", zap.Error(errors.New(userInfoRes)))
global.GVA_LOG.Error("解析OA用户信息接口返回数据失败,请求Token为:", zap.String("", oaAccessToken.AccessToken))
global.GVA_LOG.Error("解析OA用户信息接口返回数据失败,请求Token为:", zap.String("", accessTokenResponse.String()))
response.FailWithMessage("解析OA用户信息接口返回数据失败:"+err.Error(), c)
return
}
// 查询数据库数据
sysUser := &system.SysUser{}
err = global.GVA_DB.Where("email", oaUserInfo.Data.Email).First(&sysUser).Error
if err != nil && err != gorm.ErrRecordNotFound {
response.FailWithMessage("查询数据库信息失败:"+err.Error(), c)
return
}
// 判断是否需要注册
if sysUser.ID == 0 {
// TODO 从ldap中获取用户详细数据
// 注册用户
sysUser = &system.SysUser{
Username: oaUserInfo.Data.Username,
NickName: oaUserInfo.Data.Username,
HeaderImg: "https://hn1.oss-cn-shenzhen.aliyuncs.com/w.jpg",
AuthorityId: system.NormalAuthorityId,
Authorities: []system.SysAuthority{{AuthorityId: system.NormalAuthorityId}},
Enable: 1,
//Phone: r.Phone, // TODO 手机需要从ldap中获取用户详细数据
Email: oaUserInfo.Data.Email,
Password: utils.RandomString(16),
}
var userReturn system.SysUser
userReturn, err = userService.Register(*sysUser, "")
if err != nil {
global.GVA_LOG.Error("注册失败!", zap.Error(err))
response.FailWithDetailed(systemRes.SysUserResponse{User: userReturn}, "注册失败", c)
return
} else {
global.GVA_LOG.Info("注册成功!", zap.Any("username", userReturn.Username))
}
sysUser = &userReturn
}
var user *system.SysUser
user, err = userExtendService.OaLogin(sysUser) // 注意这个方法不检查密码
if err != nil {
global.GVA_LOG.Error("登陆失败! 用户名不存在!", zap.Error(err))
response.FailWithMessage("用户名不存在", c)
return
}
if sysUser.Enable != 1 {
global.GVA_LOG.Error("登陆失败! 用户被禁止登录!")
response.FailWithMessage("用户被禁止登录", c)
return
}
b.TokenNext(c, *user)
return
}
// Extend Start: oAuth2 callback verification
// OAuth2Callback
// @Tags Base
// @Summary oAuth2回调校验
// @Produce application/json
// @Param code query string true "授权码"
// @Success 200 {string} string "返回HTML内容,包含授权码"
// @Router /base/auth2/callback [get]
func (b *BaseApi) OAuth2Callback(c *gin.Context) {
// 获取授权码
code := c.Request.URL.Query().Get("code")
if code == "" {
global.GVA_LOG.Error("OAuth2回调未获取到授权码")
c.String(http.StatusBadRequest, "授权码不能为空")
return
}
// 返回HTML内容,通过BroadcastChannel将授权码传递给前端
htmlContent := fmt.Sprintf(`<html><body><script>const channel = new BroadcastChannel('oAuth2');channel.postMessage({code: '%s', timestamp: Date.now() });channel.close();window.close();</script></body></html>`, code)
c.Header("Content-Type", "text/html; charset=utf-8")
c.String(http.StatusOK, htmlContent)
}
// Extend Stop: oAuth2 callback verification