mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-07-13 15:07:37 +00:00
e85545dc1b
chat.history, chat.inject, chat.abort, and chat.session.status accepted any sessionKey without verifying the caller owns the session. A non-admin user could read, write, or disrupt another user's conversations by supplying their sessionKey. Apply the same requireSessionOwner() guard already used by sessions.* methods: canSeeAll() bypass for admin/owner, sess.UserID match for regular users. Extracted shared helper to access.go to reduce duplication. Also fixes: handleSessionStatus i18n compliance (was hardcoded English), and closes runId-only abort gap (non-admin must provide sessionKey).
45 lines
1.6 KiB
Go
45 lines
1.6 KiB
Go
package methods
|
|
|
|
import (
|
|
"context"
|
|
"slices"
|
|
|
|
"github.com/nextlevelbuilder/goclaw/internal/config"
|
|
"github.com/nextlevelbuilder/goclaw/internal/gateway"
|
|
"github.com/nextlevelbuilder/goclaw/internal/i18n"
|
|
"github.com/nextlevelbuilder/goclaw/internal/permissions"
|
|
"github.com/nextlevelbuilder/goclaw/internal/store"
|
|
"github.com/nextlevelbuilder/goclaw/pkg/protocol"
|
|
)
|
|
|
|
// canSeeAll checks if user has full data visibility (admin role OR owner user).
|
|
func canSeeAll(role permissions.Role, ownerIDs []string, userID string) bool {
|
|
if permissions.HasMinRole(role, permissions.RoleAdmin) {
|
|
return true
|
|
}
|
|
if userID != "" && slices.Contains(ownerIDs, userID) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// requireSessionOwner verifies the caller owns the session identified by key.
|
|
// Returns true if the caller is authorized (owner, admin, or matching user).
|
|
// On failure, sends an error response and returns false.
|
|
func requireSessionOwner(ctx context.Context, sessions store.SessionStore, cfg *config.Config, client *gateway.Client, reqID string, key string) bool {
|
|
if canSeeAll(client.Role(), cfg.Gateway.OwnerIDs, client.UserID()) {
|
|
return true
|
|
}
|
|
locale := store.LocaleFromContext(ctx)
|
|
sess := sessions.Get(ctx, key)
|
|
if sess == nil {
|
|
client.SendResponse(protocol.NewErrorResponse(reqID, protocol.ErrNotFound, i18n.T(locale, i18n.MsgNotFound, "session", key)))
|
|
return false
|
|
}
|
|
if sess.UserID != client.UserID() {
|
|
client.SendResponse(protocol.NewErrorResponse(reqID, protocol.ErrUnauthorized, i18n.T(locale, i18n.MsgPermissionDenied, "session")))
|
|
return false
|
|
}
|
|
return true
|
|
}
|