Skip to content

Commit 36b9446

Browse files
committed
fix: cover other paths by auth
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
1 parent 0105b17 commit 36b9446

15 files changed

Lines changed: 84 additions & 34 deletions

core/http/app.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,8 @@ func API(application *application.Application) (*echo.Echo, error) {
267267
opcache = services.NewOpCache(application.GalleryService())
268268
}
269269

270-
routes.RegisterLocalAIRoutes(e, requestExtractor, application.ModelConfigLoader(), application.ModelLoader(), application.ApplicationConfig(), application.GalleryService(), opcache, application.TemplatesEvaluator(), application, adminMiddleware, mcpJobsMw)
270+
mcpMw := auth.RequireFeature(application.AuthDB(), auth.FeatureMCP)
271+
routes.RegisterLocalAIRoutes(e, requestExtractor, application.ModelConfigLoader(), application.ModelLoader(), application.ApplicationConfig(), application.GalleryService(), opcache, application.TemplatesEvaluator(), application, adminMiddleware, mcpJobsMw, mcpMw)
271272
routes.RegisterAgentPoolRoutes(e, application, agentsMw, skillsMw, collectionsMw)
272273
routes.RegisterOpenAIRoutes(e, requestExtractor, application)
273274
routes.RegisterAnthropicRoutes(e, requestExtractor, application)

core/http/auth/apikeys.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ func ValidateAPIKey(db *gorm.DB, plaintext string) (*UserAPIKey, error) {
7474
return nil, fmt.Errorf("invalid API key")
7575
}
7676

77+
if key.User.Status != StatusActive {
78+
return nil, fmt.Errorf("user account is not active")
79+
}
80+
7781
// Update LastUsed
7882
now := time.Now()
7983
db.Model(&key).Update("last_used", now)

core/http/auth/db_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ var _ = Describe("InitDB", func() {
4040
Provider: "github",
4141
Subject: "12345",
4242
Role: "admin",
43-
Status: "active",
43+
Status: auth.StatusActive,
4444
}
4545
Expect(db.Create(user).Error).ToNot(HaveOccurred())
4646

core/http/auth/features.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,29 @@ var RouteFeatureRegistry = []RouteFeature{
6262

6363
// Sound generation
6464
{"POST", "/v1/sound-generation", FeatureSound},
65+
66+
// Realtime
67+
{"GET", "/v1/realtime", FeatureRealtime},
68+
{"POST", "/v1/realtime/sessions", FeatureRealtime},
69+
{"POST", "/v1/realtime/transcription_session", FeatureRealtime},
70+
{"POST", "/v1/realtime/calls", FeatureRealtime},
71+
72+
// MCP
73+
{"POST", "/v1/mcp/chat/completions", FeatureMCP},
74+
{"POST", "/mcp/v1/chat/completions", FeatureMCP},
75+
{"POST", "/mcp/chat/completions", FeatureMCP},
76+
77+
// Tokenize
78+
{"POST", "/v1/tokenize", FeatureTokenize},
79+
80+
// Rerank
81+
{"POST", "/v1/rerank", FeatureRerank},
82+
83+
// Stores
84+
{"POST", "/stores/set", FeatureStores},
85+
{"POST", "/stores/delete", FeatureStores},
86+
{"POST", "/stores/get", FeatureStores},
87+
{"POST", "/stores/find", FeatureStores},
6588
}
6689

6790
// FeatureMeta describes a feature for the admin API/UI.
@@ -93,5 +116,10 @@ func APIFeatureMetas() []FeatureMeta {
93116
{FeatureVideo, "Video Generation", true},
94117
{FeatureEmbeddings, "Embeddings", true},
95118
{FeatureSound, "Sound Generation", true},
119+
{FeatureRealtime, "Realtime", true},
120+
{FeatureRerank, "Rerank", true},
121+
{FeatureTokenize, "Tokenize", true},
122+
{FeatureMCP, "MCP", true},
123+
{FeatureStores, "Stores", true},
96124
}
97125
}

core/http/auth/helpers_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func createTestUser(db *gorm.DB, email, role, provider string) *auth.User {
2929
Provider: provider,
3030
Subject: generateTestID(),
3131
Role: role,
32-
Status: "active",
32+
Status: auth.StatusActive,
3333
}
3434
err := db.Create(user).Error
3535
Expect(err).ToNot(HaveOccurred())

core/http/auth/middleware.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,10 @@ func isAPIPath(path string) bool {
473473
strings.HasPrefix(path, "/vad") ||
474474
strings.HasPrefix(path, "/video") ||
475475
strings.HasPrefix(path, "/stores/") ||
476-
strings.HasPrefix(path, "/system")
476+
strings.HasPrefix(path, "/system") ||
477+
strings.HasPrefix(path, "/ws/") ||
478+
strings.HasPrefix(path, "/generated-") ||
479+
path == "/metrics"
477480
}
478481

479482
// authError returns an appropriate error response.

core/http/auth/oauth.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -211,15 +211,15 @@ func (m *OAuthManager) CallbackHandler(providerName string, db *gorm.DB, adminEm
211211
}
212212

213213
// For new users that are pending, check if they have a valid invite
214-
if user.Status != "active" && inviteCode != "" {
214+
if user.Status != StatusActive && inviteCode != "" {
215215
if invite, err := ValidateInvite(db, inviteCode); err == nil {
216-
user.Status = "active"
217-
db.Model(user).Update("status", "active")
216+
user.Status = StatusActive
217+
db.Model(user).Update("status", StatusActive)
218218
ConsumeInvite(db, invite, user.ID)
219219
}
220220
}
221221

222-
if user.Status != "active" {
222+
if user.Status != StatusActive {
223223
if registrationMode == "invite" {
224224
return c.JSON(http.StatusForbidden, map[string]string{"error": "a valid invite code is required to register"})
225225
}
@@ -383,15 +383,15 @@ func upsertOAuthUser(db *gorm.DB, provider string, info *oauthUserInfo, adminEma
383383
}
384384

385385
// New user
386-
status := "active"
386+
status := StatusActive
387387
if registrationMode == "approval" || registrationMode == "invite" {
388-
status = "pending"
388+
status = StatusPending
389389
}
390390

391391
role := AssignRole(db, info.Email, adminEmail)
392392
// First user is always active regardless of registration mode
393393
if role == RoleAdmin {
394-
status = "active"
394+
status = StatusActive
395395
}
396396

397397
user = User{

core/http/auth/permissions.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ const (
4242
FeatureVideo = "video"
4343
FeatureEmbeddings = "embeddings"
4444
FeatureSound = "sound"
45+
FeatureRealtime = "realtime"
46+
FeatureRerank = "rerank"
47+
FeatureTokenize = "tokenize"
48+
FeatureMCP = "mcp"
49+
FeatureStores = "stores"
4550
)
4651

4752
// AgentFeatures lists agent-related features (default OFF).
@@ -51,6 +56,7 @@ var AgentFeatures = []string{FeatureAgents, FeatureSkills, FeatureCollections, F
5156
var APIFeatures = []string{
5257
FeatureChat, FeatureImages, FeatureAudioSpeech, FeatureAudioTranscription,
5358
FeatureVAD, FeatureDetection, FeatureVideo, FeatureEmbeddings, FeatureSound,
59+
FeatureRealtime, FeatureRerank, FeatureTokenize, FeatureMCP, FeatureStores,
5460
}
5561

5662
// AllFeatures lists all known features (used by UI and validation).

core/http/auth/roles.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ import (
1111
const (
1212
RoleAdmin = "admin"
1313
RoleUser = "user"
14+
15+
StatusActive = "active"
16+
StatusPending = "pending"
17+
StatusDisabled = "disabled"
1418
)
1519

1620
// AssignRole determines the role for a new user.

core/http/auth/session.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ func ValidateSession(db *gorm.DB, sessionID string) *User {
4747
if err := db.Preload("User").Where("id = ? AND expires_at > ?", sessionID, time.Now()).First(&session).Error; err != nil {
4848
return nil
4949
}
50+
if session.User.Status != StatusActive {
51+
return nil
52+
}
5053
return &session.User
5154
}
5255

0 commit comments

Comments
 (0)