You've already forked agentic-coding-workflow
bugfix
This commit is contained in:
+17
-8
@@ -144,14 +144,14 @@ func postToken(deps AdminHandlerDeps) http.HandlerFunc {
|
||||
}
|
||||
|
||||
type tokenRow struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Issuer string `json:"issuer"`
|
||||
Scope Scope `json:"scope"`
|
||||
ExpiresAt *string `json:"expires_at,omitempty"`
|
||||
RevokedAt *string `json:"revoked_at,omitempty"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Issuer string `json:"issuer"`
|
||||
Scope Scope `json:"scope"`
|
||||
ExpiresAt *string `json:"expires_at,omitempty"`
|
||||
RevokedAt *string `json:"revoked_at,omitempty"`
|
||||
LastUsedAt *string `json:"last_used_at,omitempty"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
}
|
||||
|
||||
func listTokens(deps AdminHandlerDeps) http.HandlerFunc {
|
||||
@@ -200,7 +200,7 @@ func listTokens(deps AdminHandlerDeps) http.HandlerFunc {
|
||||
func deleteToken(deps AdminHandlerDeps) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
rid := middleware.RequestIDFromContext(r.Context())
|
||||
caller, _, err := resolveSessionUser(r.Context(), deps.Users, r)
|
||||
caller, isAdmin, err := resolveSessionUser(r.Context(), deps.Users, r)
|
||||
if err != nil {
|
||||
httpx.WriteError(w, rid, err)
|
||||
return
|
||||
@@ -211,6 +211,15 @@ func deleteToken(deps AdminHandlerDeps) http.HandlerFunc {
|
||||
httpx.WriteError(w, rid, errs.Wrap(err, errs.CodeInvalidInput, "id parse"))
|
||||
return
|
||||
}
|
||||
// 授权:仅 admin 或 token 持有者可撤销。非 admin 时按 id 反查 token
|
||||
// 校验归属;不归属(或不存在)一律返 NotFound,避免暴露 token 是否存在。
|
||||
if !isAdmin {
|
||||
tok, err := deps.Tokens.GetByID(r.Context(), id)
|
||||
if err != nil || tok.UserID != caller {
|
||||
httpx.WriteError(w, rid, errs.New(errs.CodeMcpTokenNotFound, "mcp token not found"))
|
||||
return
|
||||
}
|
||||
}
|
||||
if err := deps.Tokens.Revoke(r.Context(), id, caller); err != nil {
|
||||
httpx.WriteError(w, rid, err)
|
||||
return
|
||||
|
||||
@@ -8,11 +8,15 @@ RETURNING id, token_hash, user_id, name, issuer, scope,
|
||||
created_by, created_at;
|
||||
|
||||
-- name: GetMcpTokenByHash :one
|
||||
SELECT id, token_hash, user_id, name, issuer, scope,
|
||||
acp_session_id, expires_at, last_used_at, revoked_at,
|
||||
created_by, created_at
|
||||
FROM mcp_tokens
|
||||
WHERE token_hash = $1;
|
||||
-- 鉴权用:仅返回属于 enabled 用户的 token,禁用用户的 MCP token 立即失效
|
||||
-- (与 web session 解析 GetSessionByTokenHash 的 enabled=true 约束一致)。
|
||||
SELECT t.id, t.token_hash, t.user_id, t.name, t.issuer, t.scope,
|
||||
t.acp_session_id, t.expires_at, t.last_used_at, t.revoked_at,
|
||||
t.created_by, t.created_at
|
||||
FROM mcp_tokens t
|
||||
JOIN users u ON u.id = t.user_id
|
||||
WHERE t.token_hash = $1
|
||||
AND u.enabled = true;
|
||||
|
||||
-- name: GetMcpTokenByID :one
|
||||
SELECT id, token_hash, user_id, name, issuer, scope,
|
||||
|
||||
@@ -74,13 +74,17 @@ func (q *Queries) DeleteMcpTokenByID(ctx context.Context, id pgtype.UUID) error
|
||||
}
|
||||
|
||||
const getMcpTokenByHash = `-- name: GetMcpTokenByHash :one
|
||||
SELECT id, token_hash, user_id, name, issuer, scope,
|
||||
acp_session_id, expires_at, last_used_at, revoked_at,
|
||||
created_by, created_at
|
||||
FROM mcp_tokens
|
||||
WHERE token_hash = $1
|
||||
SELECT t.id, t.token_hash, t.user_id, t.name, t.issuer, t.scope,
|
||||
t.acp_session_id, t.expires_at, t.last_used_at, t.revoked_at,
|
||||
t.created_by, t.created_at
|
||||
FROM mcp_tokens t
|
||||
JOIN users u ON u.id = t.user_id
|
||||
WHERE t.token_hash = $1
|
||||
AND u.enabled = true
|
||||
`
|
||||
|
||||
// 鉴权用:仅返回属于 enabled 用户的 token,禁用用户的 MCP token 立即失效
|
||||
// (与 web session 解析 GetSessionByTokenHash 的 enabled=true 约束一致)。
|
||||
func (q *Queries) GetMcpTokenByHash(ctx context.Context, tokenHash []byte) (McpToken, error) {
|
||||
row := q.db.QueryRow(ctx, getMcpTokenByHash, tokenHash)
|
||||
var i McpToken
|
||||
|
||||
Reference in New Issue
Block a user