feat(oidc): 支持自定义 OIDC 登录显示名称 (#6012)

* docs: add design spec for OIDC custom display name

Mirrors the existing Custom OAuth Provider name pattern so admins can
show a meaningful label instead of the hardcoded "OIDC" on the login
page and in related copy.

* feat(oidc): add configurable display name with OIDC fallback

* feat(oidc): use configured display name in provider name and status API

* feat(oidc): add display name field to default-theme OIDC settings

Claude-Session: https://claude.ai/code/session_01FDkWJqigJi9yE3HG5pjZP5

* feat(oidc): show configured display name on default-theme login button

* feat(oidc): add display name field to classic-theme OIDC settings

* feat(oidc): show configured display name on classic-theme login button

* fix(oidc): trim whitespace before applying display name fallback

* chore: remove internal design doc from PR

Design/planning docs are working artifacts for this session and
shouldn't be submitted to the upstream project.

* fix(oidc): lead with example in classic-theme display name placeholder

Reorders the combined placeholder to show the example first, then
the fallback note, matching the Custom OAuth Provider Name field's
placeholder convention (example-only) that this feature mirrors.

* fix(i18n): improve Russian grammar in OIDC display-name placeholder translation

Leads each clause with its condition/subject and adds the missing
verb, per PR review feedback.

* test(web): remove redundant OIDC harness tests
This commit is contained in:
June Chi
2026-07-29 16:27:15 +08:00
committed by GitHub
parent c27d1ef651
commit cb4c8c02f8
20 changed files with 213 additions and 6 deletions
+1
View File
@@ -111,6 +111,7 @@ func GetStatus(c *gin.Context) {
"oidc_enabled": system_setting.GetOIDCSettings().Enabled,
"oidc_client_id": system_setting.GetOIDCSettings().ClientId,
"oidc_authorization_endpoint": system_setting.GetOIDCSettings().AuthorizationEndpoint,
"oidc_display_name": system_setting.GetOIDCSettings().GetEffectiveDisplayName(),
"passkey_login": passkeySetting.Enabled,
"passkey_display_name": passkeySetting.RPDisplayName,
"passkey_rp_id": passkeySetting.RPID,
+60
View File
@@ -0,0 +1,60 @@
package controller
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/QuantumNous/new-api/common"
"github.com/QuantumNous/new-api/setting/system_setting"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGetStatusReturnsEffectiveOIDCDisplayName(t *testing.T) {
settings := system_setting.GetOIDCSettings()
originalDisplayName := settings.DisplayName
originalOptionMap := common.OptionMap
t.Cleanup(func() {
settings.DisplayName = originalDisplayName
common.OptionMap = originalOptionMap
})
common.OptionMap = map[string]string{}
tests := []struct {
name string
displayName string
want string
}{
{
name: "custom name is trimmed",
displayName: " Acme SSO ",
want: "Acme SSO",
},
{
name: "whitespace-only name falls back",
displayName: " ",
want: "OIDC",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
settings.DisplayName = tt.displayName
response := httptest.NewRecorder()
context, _ := gin.CreateTestContext(response)
context.Request = httptest.NewRequest(http.MethodGet, "/api/status", nil)
GetStatus(context)
var payload struct {
Success bool `json:"success"`
Data map[string]any `json:"data"`
}
require.NoError(t, common.Unmarshal(response.Body.Bytes(), &payload))
require.True(t, payload.Success)
assert.Equal(t, tt.want, payload.Data["oidc_display_name"])
})
}
}