Files
dify-plus/admin/server/service/gaia/login_options.go
T
npc0-hue 10ec0eb953 feat: 合并近期功能与修复
- GLM/MiniMax 模型支持及 provider_name 修复
- OAuth2 登录跳转与重定向 hash 保留
- Azure 模型支持与转发特殊处理
- 后台登录与钉钉邮箱默认域名
- 转发获取密钥、Jinja 路径、RSA 私钥加载
- 模型管理可用模型输入与新增
- 自动更新权限、健康监测、admin 配置等

Co-authored-by: Cursor <github@npc0.com>
2026-02-24 16:24:23 +08:00

86 lines
3.3 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
}
// 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
}