This is an automated email from the ASF dual-hosted git repository.

hsluoyz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/casbin-gateway.git

commit 192105781dbdeb66b3bc67b9cb7e7a0f25e15b7a
Author: Yang Luo <[email protected]>
AuthorDate: Sun Sep 6 15:08:11 2026 +0800

    fix(connector): write a connection into the home of the account the agent 
runs as
---
 agent/config_owner.go        | 41 +++++++++++++++++++++++++++++++++++++++++
 controllers/connector.go     |  8 ++++++--
 controllers/permission.go    |  2 +-
 object/connection.go         |  7 +++++--
 object/connection_install.go | 13 +++++++++----
 5 files changed, 62 insertions(+), 9 deletions(-)

diff --git a/agent/config_owner.go b/agent/config_owner.go
new file mode 100644
index 0000000..ac35e61
--- /dev/null
+++ b/agent/config_owner.go
@@ -0,0 +1,41 @@
+// Copyright 2026 The casbin Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package agent
+
+import "github.com/apache/casbin-gateway/agenthome"
+
+// ConfigOwnerOf is the account whose home an agent's configuration files live
+// in. It is not the account a Gateway row is stored under: that one names who
+// signed in here, and writing a file needs the account the agent runs as.
+//
+// Installations of one agent under several accounts share an id, so the first
+// one whose home this Gateway can actually reach wins. An agent no scan found
+// falls back to the account Gateway runs as, which is where its files would 
be.
+func ConfigOwnerOf(agentId string) string {
+       installations, err := Scan(false)
+       if err != nil {
+               return ""
+       }
+
+       for _, installation := range installations {
+               if installation.AgentId != agentId {
+                       continue
+               }
+               if _, err := agenthome.Resolve(installation.Owner); err == nil {
+                       return installation.Owner
+               }
+       }
+       return ""
+}
diff --git a/controllers/connector.go b/controllers/connector.go
index 5a3759d..f243b62 100644
--- a/controllers/connector.go
+++ b/controllers/connector.go
@@ -151,11 +151,15 @@ func connectorTargets() ([]*ConnectorTarget, error) {
                        continue
                }
                seen[installation.AgentId] = true
+               // The account whose configuration is written rather than the 
one this
+               // row was found under, so the file named here is the file a 
connection
+               // actually lands in.
+               account := agent.ConfigOwnerOf(installation.AgentId)
                targets = append(targets, &ConnectorTarget{
                        AgentId: installation.AgentId,
                        Name:    installation.Name,
-                       Owner:   installation.Owner,
-                       McpFile: 
agentconfig.McpConfigFile(installation.AgentId, installation.Owner),
+                       Owner:   account,
+                       McpFile: 
agentconfig.McpConfigFile(installation.AgentId, account),
                })
        }
 
diff --git a/controllers/permission.go b/controllers/permission.go
index 2784dfd..9f32633 100644
--- a/controllers/permission.go
+++ b/controllers/permission.go
@@ -59,7 +59,7 @@ func mcpItemsOf(agentId string, owner string) 
[]object.ToolItem {
        }
        // A connection that has been tested knows what it offers, so its tools 
get a
        // switch each, under the server switch they already had.
-       items = append(items, object.ConnectionToolItems(agentId, owner)...)
+       items = append(items, object.ConnectionToolItems(agentId)...)
        return items
 }
 
diff --git a/object/connection.go b/object/connection.go
index 11fad51..a35ff82 100644
--- a/object/connection.go
+++ b/object/connection.go
@@ -263,8 +263,11 @@ func DeleteConnection(owner string, name string) error {
 // this agent, built from what the last test found. A connection nobody has
 // tested contributes none and is governed by its server switch alone, which is
 // what makes testing worth doing beyond seeing that it works.
-func ConnectionToolItems(agentId string, owner string) []ToolItem {
-       connections, err := GetConnections(owner)
+// Every connection on the machine is looked at, whoever signed in to make it:
+// the switches are per agent, and an agent does not know which account added
+// the server it was given.
+func ConnectionToolItems(agentId string) []ToolItem {
+       connections, err := getAllConnections()
        if err != nil {
                return nil
        }
diff --git a/object/connection_install.go b/object/connection_install.go
index b02e899..2ecec4c 100644
--- a/object/connection_install.go
+++ b/object/connection_install.go
@@ -18,6 +18,7 @@ import (
        "fmt"
        "sort"
 
+       "github.com/apache/casbin-gateway/agent"
        "github.com/apache/casbin-gateway/agentconfig"
        "github.com/apache/casbin-gateway/agentpatch"
        "github.com/apache/casbin-gateway/connector"
@@ -100,13 +101,17 @@ func proxyRequest(connection *Connection, found 
connector.Connector, agentId str
        if err != nil {
                return agentconfig.McpRequest{}, err
        }
-       token, err := agentpatch.IssueIngestToken(agentpatch.Target{AgentId: 
agentId, Owner: connection.Owner})
+       // Two different accounts meet here: connection.Owner is who signed in 
to
+       // Gateway, and the entry has to be written into the home of the 
account the
+       // agent runs as. Only the proxy's own --owner names the first.
+       account := agent.ConfigOwnerOf(agentId)
+       token, err := agentpatch.IssueIngestToken(agentpatch.Target{AgentId: 
agentId, Owner: account})
        if err != nil {
                return agentconfig.McpRequest{}, err
        }
 
        return agentconfig.McpRequest{
-               Owner:     connection.Owner,
+               Owner:     account,
                To:        []string{agentId},
                Name:      found.Server.Name,
                Transport: agentconfig.TransportStdio,
@@ -169,7 +174,7 @@ func revokeUnusedTokens(owner string, agentIds []string) {
                if remaining[agentId] {
                        continue
                }
-               _ = agentpatch.RevokeIngestToken(agentpatch.Target{AgentId: 
agentId, Owner: owner})
+               _ = agentpatch.RevokeIngestToken(agentpatch.Target{AgentId: 
agentId, Owner: agent.ConfigOwnerOf(agentId)})
        }
 }
 
@@ -211,7 +216,7 @@ func removeFrom(connection *Connection, serverName string, 
agentIds []string) []
        planned := []*agentconfig.PlanItem{}
        for _, agentId := range agentIds {
                item := &agentconfig.PlanItem{AgentId: agentId, Name: 
serverName, Action: agentconfig.ActionRemove}
-               if err := agentconfig.Delete(agentId, connection.Owner, 
agentconfig.KindMcp, serverName); err != nil {
+               if err := agentconfig.Delete(agentId, 
agent.ConfigOwnerOf(agentId), agentconfig.KindMcp, serverName); err != nil {
                        item.Action, item.Reason = agentconfig.ActionSkip, 
err.Error()
                }
                planned = append(planned, item)


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to