chore: auto-commit (12 archivos)
- app.md - backend/handlers.go - backend/main.go - frontend/src/App.tsx - frontend/src/api.ts - frontend/vite.config.ts - backend/mcp_http.go - backend/mcp_tokens.go - backend/mcp_tokens_handlers.go - backend/migrations/016_mcp_tokens.sql - ... Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"fn-registry/functions/infra"
|
||||
)
|
||||
|
||||
// POST /api/mcp-tokens {name}
|
||||
//
|
||||
// Mints a new MCP token for the current user. The plaintext token is returned
|
||||
// ONLY in this response — there is no way to retrieve it again.
|
||||
func handleCreateMCPToken(db *DB) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
userID, _ := infra.UserIDFromContext(r.Context(), userCtxKey)
|
||||
if userID == "" {
|
||||
infra.HTTPErrorResponse(w, infra.HTTPError{Status: http.StatusUnauthorized, Code: "unauthorized", Message: "login required"})
|
||||
return
|
||||
}
|
||||
var body struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
if err := infra.HTTPParseBody(r, &body, maxBodyBytes); err != nil {
|
||||
badRequest(w, err.Error())
|
||||
return
|
||||
}
|
||||
name := strings.TrimSpace(body.Name)
|
||||
if name == "" {
|
||||
name = "default"
|
||||
}
|
||||
plaintext, tok, err := db.MintMCPToken(userID, name)
|
||||
if err != nil {
|
||||
serverError(w, err)
|
||||
return
|
||||
}
|
||||
infra.HTTPJSONResponse(w, http.StatusCreated, map[string]any{
|
||||
"id": tok.ID,
|
||||
"name": tok.Name,
|
||||
"created_at": tok.CreatedAt,
|
||||
"token": plaintext,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// GET /api/mcp-tokens
|
||||
func handleListMCPTokens(db *DB) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
userID, _ := infra.UserIDFromContext(r.Context(), userCtxKey)
|
||||
if userID == "" {
|
||||
infra.HTTPErrorResponse(w, infra.HTTPError{Status: http.StatusUnauthorized, Code: "unauthorized", Message: "login required"})
|
||||
return
|
||||
}
|
||||
tokens, err := db.ListMCPTokens(userID)
|
||||
if err != nil {
|
||||
serverError(w, err)
|
||||
return
|
||||
}
|
||||
infra.HTTPJSONResponse(w, http.StatusOK, tokens)
|
||||
}
|
||||
}
|
||||
|
||||
// DELETE /api/mcp-tokens/{id}
|
||||
func handleRevokeMCPToken(db *DB) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
userID, _ := infra.UserIDFromContext(r.Context(), userCtxKey)
|
||||
if userID == "" {
|
||||
infra.HTTPErrorResponse(w, infra.HTTPError{Status: http.StatusUnauthorized, Code: "unauthorized", Message: "login required"})
|
||||
return
|
||||
}
|
||||
id := r.PathValue("id")
|
||||
if err := db.RevokeMCPToken(userID, id); err != nil {
|
||||
if errors.Is(err, errMCPTokenNotFound) {
|
||||
notFound(w, "token not found")
|
||||
return
|
||||
}
|
||||
serverError(w, err)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user