@@ -72,6 +72,7 @@ type Config struct {
7272 LinuxDo LinuxDoConnectConfig `mapstructure:"linuxdo_connect"`
7373 WeChat WeChatConnectConfig `mapstructure:"wechat_connect"`
7474 OIDC OIDCConnectConfig `mapstructure:"oidc_connect"`
75+ DingTalk DingTalkConnectConfig `mapstructure:"dingtalk_connect"`
7576 GitHubOAuth EmailOAuthProviderConfig `mapstructure:"github_oauth"`
7677 GoogleOAuth EmailOAuthProviderConfig `mapstructure:"google_oauth"`
7778 Default DefaultConfig `mapstructure:"default"`
@@ -242,6 +243,47 @@ type OIDCConnectConfig struct {
242243 UserInfoUsernamePath string `mapstructure:"userinfo_username_path"`
243244}
244245
246+ type DingTalkConnectConfig struct {
247+ Enabled bool `mapstructure:"enabled"`
248+ ClientID string `mapstructure:"client_id"`
249+ ClientSecret string `mapstructure:"client_secret"`
250+ AuthorizeURL string `mapstructure:"authorize_url"`
251+ TokenURL string `mapstructure:"token_url"`
252+ UserInfoURL string `mapstructure:"userinfo_url"`
253+ Scopes string `mapstructure:"scopes"`
254+ RedirectURL string `mapstructure:"redirect_url"`
255+ FrontendRedirectURL string `mapstructure:"frontend_redirect_url"`
256+
257+ // 平台底座 + 业务行为
258+ DingTalkAppKind string `mapstructure:"dingtalk_app_kind"` // 仅 "internal_app"(V4 fail-closed)
259+ AppType string `mapstructure:"app_type"` // "public" (default) | "internal"
260+
261+ // Corp 限定(none | internal_only)
262+ CorpRestrictionPolicy string `mapstructure:"corp_restriction_policy"`
263+ InternalCorpID string `mapstructure:"internal_corp_id"`
264+ BypassRegistration bool `mapstructure:"bypass_registration"`
265+ SyncCorpEmail bool `mapstructure:"sync_corp_email"`
266+ SyncDisplayName bool `mapstructure:"sync_display_name"`
267+ SyncDept bool `mapstructure:"sync_dept"`
268+ SyncCorpEmailAttrKey string `mapstructure:"sync_corp_email_attr_key"`
269+ SyncDisplayNameAttrKey string `mapstructure:"sync_display_name_attr_key"`
270+ SyncDeptAttrKey string `mapstructure:"sync_dept_attr_key"`
271+ SyncCorpEmailAttrName string `mapstructure:"sync_corp_email_attr_name"`
272+ SyncDisplayNameAttrName string `mapstructure:"sync_display_name_attr_name"`
273+ SyncDeptAttrName string `mapstructure:"sync_dept_attr_name"`
274+
275+ // 邮箱 + Username
276+ RequireEmail bool `mapstructure:"require_email"`
277+ UsernameOverwritePolicy string `mapstructure:"username_overwrite_policy"`
278+
279+ // Attribute(私有版扩展点;开源版仅声明)
280+ UsernameAttributeKey string `mapstructure:"username_attribute_key"`
281+ EnableAttributeMatching bool `mapstructure:"enable_attribute_matching"`
282+ EnableAttributeSync bool `mapstructure:"enable_attribute_sync"`
283+ AttributeSyncFields []string `mapstructure:"attribute_sync_fields"`
284+ AttributeSyncOverwritePolicy string `mapstructure:"attribute_sync_overwrite_policy"`
285+ }
286+
245287type EmailOAuthProviderConfig struct {
246288 Enabled bool `mapstructure:"enabled"`
247289 ClientID string `mapstructure:"client_id"`
@@ -1536,6 +1578,19 @@ func setDefaults() {
15361578 viper .SetDefault ("oidc_connect.userinfo_id_path" , "" )
15371579 viper .SetDefault ("oidc_connect.userinfo_username_path" , "" )
15381580
1581+ // DingTalk Connect OAuth 登录
1582+ viper .SetDefault ("dingtalk_connect.enabled" , false )
1583+ viper .SetDefault ("dingtalk_connect.authorize_url" , "https://login.dingtalk.com/oauth2/auth" )
1584+ viper .SetDefault ("dingtalk_connect.token_url" , "https://api.dingtalk.com/v1.0/oauth2/userAccessToken" )
1585+ viper .SetDefault ("dingtalk_connect.userinfo_url" , "https://api.dingtalk.com/v1.0/contact/users/me" )
1586+ viper .SetDefault ("dingtalk_connect.scopes" , "openid" )
1587+ viper .SetDefault ("dingtalk_connect.frontend_redirect_url" , "/auth/dingtalk/callback" )
1588+ viper .SetDefault ("dingtalk_connect.dingtalk_app_kind" , "internal_app" )
1589+ viper .SetDefault ("dingtalk_connect.app_type" , "public" )
1590+ viper .SetDefault ("dingtalk_connect.corp_restriction_policy" , "none" )
1591+ viper .SetDefault ("dingtalk_connect.require_email" , true )
1592+ viper .SetDefault ("dingtalk_connect.username_overwrite_policy" , "if_empty" )
1593+
15391594 // Database
15401595 viper .SetDefault ("database.host" , "localhost" )
15411596 viper .SetDefault ("database.port" , 5432 )
@@ -2608,6 +2663,9 @@ func (c *Config) Validate() error {
26082663 if c .Concurrency .PingInterval < 5 || c .Concurrency .PingInterval > 30 {
26092664 return fmt .Errorf ("concurrency.ping_interval must be between 5-30 seconds" )
26102665 }
2666+ if err := ValidateDingTalkConfig (c .DingTalk ); err != nil {
2667+ return fmt .Errorf ("dingtalk_connect: %w" , err )
2668+ }
26112669 return nil
26122670}
26132671
0 commit comments