Skip to content

Commit 2962f4a

Browse files
authored
Merge branch 'dev' into dialog
2 parents d46da49 + d0925bd commit 2962f4a

11 files changed

Lines changed: 77 additions & 23 deletions

File tree

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.3.0
1+
0.3.1

backend/cmd/server/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
)
1010

1111
// @title DEEIX Chat API
12-
// @version 0.3.0
12+
// @version 0.3.1
1313
// @description DEEIX Chat 后端 API 文档
1414
// @BasePath /api/v1
1515
// @securityDefinitions.apikey BearerAuth

backend/docs/docs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17899,7 +17899,7 @@ const docTemplate = `{
1789917899

1790017900
// SwaggerInfo holds exported Swagger Info so clients can modify it
1790117901
var SwaggerInfo = &swag.Spec{
17902-
Version: "0.3.0",
17902+
Version: "0.3.1",
1790317903
Host: "",
1790417904
BasePath: "/api/v1",
1790517905
Schemes: []string{},

backend/docs/swagger.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"description": "DEEIX Chat 后端 API 文档",
55
"title": "DEEIX Chat API",
66
"contact": {},
7-
"version": "0.3.0"
7+
"version": "0.3.1"
88
},
99
"basePath": "/api/v1",
1010
"paths": {
@@ -17888,4 +17888,4 @@
1788817888
"in": "header"
1788917889
}
1789017890
}
17891-
}
17891+
}

backend/docs/swagger.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5148,7 +5148,7 @@ info:
51485148
contact: {}
51495149
description: DEEIX Chat 后端 API 文档
51505150
title: DEEIX Chat API
5151-
version: 0.3.0
5151+
version: "0.3.1"
51525152
paths:
51535153
/admin/announcements:
51545154
get:

backend/internal/application/auth/provider.go

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -598,13 +598,8 @@ func (s *Service) normalizeProviderInput(input UpsertIdentityProviderInput, curr
598598
return nil, ErrIdentityProviderSuperAdminDefaultRoleNotAllowed
599599
}
600600
logoURL := strings.TrimSpace(input.LogoURL)
601-
if logoURL != "" {
602-
parsedLogoURL, err := url.Parse(logoURL)
603-
isHTTPLogoURL := (parsedLogoURL.Scheme == "http" || parsedLogoURL.Scheme == "https") && parsedLogoURL.Host != ""
604-
isAbsolutePathLogoURL := strings.HasPrefix(logoURL, "/")
605-
if err != nil || (!isHTTPLogoURL && !isAbsolutePathLogoURL) {
606-
return nil, fmt.Errorf("logo url must be a valid http(s) or absolute path")
607-
}
601+
if logoURL != "" && !isValidProviderLogoURL(logoURL) {
602+
return nil, fmt.Errorf("logo url must be a valid http(s) or absolute path")
608603
}
609604
provider := &domainuser.IdentityProvider{
610605
Type: providerType,
@@ -660,6 +655,21 @@ func (s *Service) normalizeProviderInput(input UpsertIdentityProviderInput, curr
660655
return provider, nil
661656
}
662657

658+
func isValidProviderLogoURL(value string) bool {
659+
parsedLogoURL, err := url.Parse(value)
660+
if err != nil {
661+
return false
662+
}
663+
if (parsedLogoURL.Scheme == "http" || parsedLogoURL.Scheme == "https") && parsedLogoURL.Host != "" {
664+
return true
665+
}
666+
return parsedLogoURL.Scheme == "" &&
667+
parsedLogoURL.Host == "" &&
668+
strings.HasPrefix(value, "/") &&
669+
!strings.HasPrefix(value, "//") &&
670+
!strings.Contains(value, "\\")
671+
}
672+
663673
func toProviderViews(items []domainuser.IdentityProvider, includeSensitive bool) []IdentityProviderView {
664674
results := make([]IdentityProviderView, 0, len(items))
665675
for _, item := range items {

backend/internal/application/auth/provider_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,47 @@ func TestNormalizeProviderInputProtectsSuperAdminDefaultRole(t *testing.T) {
9090
}
9191
}
9292

93+
func TestNormalizeProviderInputValidatesLogoURL(t *testing.T) {
94+
service := NewService(config.Config{JWTSecret: "test-secret"}, &providerLoginRepo{}, nil)
95+
96+
cases := []struct {
97+
name string
98+
logoURL string
99+
wantErr bool
100+
}{
101+
{name: "https url", logoURL: "https://example.com/logo.svg"},
102+
{name: "http url", logoURL: "http://example.com/logo.svg"},
103+
{name: "absolute path", logoURL: "/identity-providers/acme.svg"},
104+
{name: "protocol relative url", logoURL: "//example.com/logo.svg", wantErr: true},
105+
{name: "data url", logoURL: "data:image/svg+xml,<svg/>", wantErr: true},
106+
{name: "javascript url", logoURL: "javascript:alert(1)", wantErr: true},
107+
{name: "relative path", logoURL: "identity-providers/acme.svg", wantErr: true},
108+
{name: "backslash path", logoURL: `/\example.svg`, wantErr: true},
109+
}
110+
111+
for _, tc := range cases {
112+
t.Run(tc.name, func(t *testing.T) {
113+
_, err := service.normalizeProviderInput(UpsertIdentityProviderInput{
114+
ActorRole: domainuser.RoleAdmin,
115+
Type: domainuser.IdentityProviderTypeOIDC,
116+
Name: "Acme SSO",
117+
LogoURL: tc.logoURL,
118+
ClientID: "client",
119+
ClientSecret: "secret",
120+
DiscoveryURL: "https://example.com/.well-known/openid-configuration",
121+
RegistrationEnabled: boolPtr(true),
122+
DefaultRole: domainuser.RoleUser,
123+
}, nil)
124+
if tc.wantErr && err == nil {
125+
t.Fatalf("expected logo URL %q to be rejected", tc.logoURL)
126+
}
127+
if !tc.wantErr && err != nil {
128+
t.Fatalf("expected logo URL %q to be accepted, got %v", tc.logoURL, err)
129+
}
130+
})
131+
}
132+
}
133+
93134
func TestResolveProviderUserAutoRegistrationAddsUsernameSuffixOnCollision(t *testing.T) {
94135
repo := &providerLoginRepo{duplicateUsernameAttempts: 1}
95136
service := NewService(config.Config{JWTSecret: "test-secret"}, repo, nil)

frontend/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
{
22
"name": "deeix-chat",
3-
"version": "0.3.0",
3+
"version": "0.3.1",
44
"private": true,
55
"packageManager": "pnpm@10.17.0",
66
"pnpm": {
77
"overrides": {
88
"@babel/core": "7.29.7",
99
"brace-expansion@1": "1.1.15",
1010
"brace-expansion@5": "5.0.6",
11-
"dompurify": "3.4.10",
11+
"dompurify": "3.4.11",
1212
"flatted": "3.4.2",
1313
"js-yaml": "4.2.0",
1414
"mermaid": "11.15.0",

frontend/pnpm-lock.yaml

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/public/sw.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const PWA_ASSET_VERSION = "0.3.0";
1+
const PWA_ASSET_VERSION = "0.3.1";
22
const PWA_ASSET_CACHE_KEY = "632cb83037d9";
33
const PWA_ASSET_MANIFEST = {
44
"/pwa/icon.svg": "/pwa/generated/icon.fe1d64d9758c.svg",

0 commit comments

Comments
 (0)