mirror of
https://github.com/YFGaia/dify-plus.git
synced 2026-06-04 10:14:00 +08:00
102 lines
4.2 KiB
Go
102 lines
4.2 KiB
Go
package gaia
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||
"github.com/flipped-aurora/gin-vue-admin/server/model/gaia"
|
||
"github.com/flipped-aurora/gin-vue-admin/server/model/gaia/request"
|
||
"github.com/flipped-aurora/gin-vue-admin/server/model/gaia/response"
|
||
"github.com/flipped-aurora/gin-vue-admin/server/utils"
|
||
"net/url"
|
||
"strings"
|
||
)
|
||
|
||
// GetLoginOptions 获取登录方式选项(供登录页展示钉钉/OAuth2 按钮,不暴露密钥)
|
||
func (e *SystemIntegratedService) GetLoginOptions(frontendOrigin string) (res response.LoginOptionsResponse) {
|
||
// 非本地的需要加上admin
|
||
integrateDing := e.getIntegratedConfigRaw(gaia.SystemIntegrationDingTalk)
|
||
frontendOrigin = strings.TrimSuffix(frontendOrigin, "/")
|
||
if !strings.Contains(frontendOrigin, "localhost") {
|
||
frontendOrigin = frontendOrigin + "/admin"
|
||
}
|
||
if integrateDing.Status && integrateDing.AppKey != "" {
|
||
res.DingTalk.Enabled = true
|
||
callbackURI := frontendOrigin + "/#/loginCallback?provider=dingtalk"
|
||
res.DingTalk.AuthURL = fmt.Sprintf("https://login.dingtalk.com/oauth2/auth?client_id=%s&response_type=code&scope=openid&redirect_uri=%s&state=dingtalk",
|
||
integrateDing.AppKey, url.QueryEscape(callbackURI))
|
||
}
|
||
|
||
// OAuth2
|
||
integrateOAuth := e.getIntegratedConfigRaw(gaia.SystemIntegrationOAuth2)
|
||
if integrateOAuth.Status && integrateOAuth.AppID != "" && integrateOAuth.Config != "" {
|
||
var configMap request.SystemOAuth2Request
|
||
if err := json.Unmarshal([]byte(integrateOAuth.Config), &configMap); err != nil {
|
||
return res
|
||
}
|
||
if configMap.ServerURL == "" || configMap.AuthorizeURL == "" {
|
||
return res
|
||
}
|
||
res.OAuth2.Enabled = true
|
||
redirectURI := strings.TrimSpace(configMap.RedirectUri)
|
||
if redirectURI == "" {
|
||
redirectURI = frontendOrigin + "/#/loginCallback?provider=oauth2"
|
||
}
|
||
res.OAuth2.RedirectURI = redirectURI
|
||
scope := strings.TrimSpace(configMap.Scope)
|
||
if scope == "" {
|
||
scope = "openid"
|
||
}
|
||
// Extend: 兼容 Casdoor 等 provider。用 net/url 解析并合并 query,保证 client_id 等参数一定被附加上去
|
||
baseURLStr := strings.TrimSuffix(configMap.ServerURL, "/") + configMap.AuthorizeURL
|
||
u, err := url.Parse(baseURLStr)
|
||
if err != nil {
|
||
// 解析失败时退回字符串拼接
|
||
paramSep := "?"
|
||
if strings.Contains(configMap.AuthorizeURL, "?") {
|
||
paramSep = "&"
|
||
}
|
||
res.OAuth2.AuthURL = fmt.Sprintf("%s%sclient_id=%s&response_type=code&scope=%s&redirect_uri=%s&state=oauth2",
|
||
baseURLStr, paramSep, url.QueryEscape(integrateOAuth.AppID), url.QueryEscape(scope), url.QueryEscape(redirectURI))
|
||
} else {
|
||
q := u.Query()
|
||
q.Set("client_id", integrateOAuth.AppID)
|
||
q.Set("response_type", "code")
|
||
q.Set("scope", scope)
|
||
q.Set("redirect_uri", redirectURI)
|
||
q.Set("state", "oauth2")
|
||
u.RawQuery = q.Encode()
|
||
res.OAuth2.AuthURL = u.String()
|
||
}
|
||
}
|
||
return res
|
||
}
|
||
|
||
// GetDingTalkTestAuthURL 返回用于「测试连接」的钉钉授权 URL(state=dingtalk_test,回调后仅验证 code 换 token,不登录)
|
||
func (e *SystemIntegratedService) GetDingTalkTestAuthURL(frontendOrigin string) (string, error) {
|
||
integrate := e.getIntegratedConfigRaw(gaia.SystemIntegrationDingTalk)
|
||
if integrate.AppKey == "" || integrate.AppSecret == "" {
|
||
return "", fmt.Errorf("请先配置 AppKey 与 AppSecret")
|
||
}
|
||
frontendOrigin = strings.TrimSuffix(frontendOrigin, "/")
|
||
if !strings.Contains(frontendOrigin, "localhost") {
|
||
frontendOrigin = frontendOrigin + "/admin"
|
||
}
|
||
callbackURI := frontendOrigin + "/#/loginCallback?provider=dingtalk"
|
||
authURL := fmt.Sprintf("https://login.dingtalk.com/oauth2/auth?client_id=%s&response_type=code&scope=openid&redirect_uri=%s&state=dingtalk_test",
|
||
integrate.AppKey, url.QueryEscape(callbackURI))
|
||
return authURL, nil
|
||
}
|
||
|
||
// getIntegratedConfigRaw 获取集成配置(不脱敏,仅内部使用)
|
||
func (e *SystemIntegratedService) getIntegratedConfigRaw(classID uint) (integrate gaia.SystemIntegration) {
|
||
if err := global.GVA_DB.Where("classify = ?", classID).First(&integrate).Error; err != nil {
|
||
return gaia.SystemIntegration{Classify: classID, Status: false}
|
||
}
|
||
// 解密 AppSecret 供内部使用
|
||
if secret, err := utils.DecryptBlowfish(integrate.AppSecret, global.GVA_CONFIG.JWT.SigningKey); err == nil {
|
||
integrate.AppSecret = secret
|
||
}
|
||
return integrate
|
||
}
|