mirror of
https://github.com/danielmiessler/Fabric.git
synced 2026-01-10 23:08:06 -05:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b60bad7799 | ||
|
|
234d1303ad | ||
|
|
cd74a96be2 | ||
|
|
ceaa90a7c7 | ||
|
|
15a2eeadc9 | ||
|
|
8d02f5b21d | ||
|
|
0f8f0b6b39 | ||
|
|
fd58b6d410 | ||
|
|
2579d37c16 | ||
|
|
4f28d85e96 | ||
|
|
f529b8bb80 | ||
|
|
71437605e1 | ||
|
|
01770cc6e3 |
@@ -15,7 +15,7 @@
|
||||
</p>
|
||||
|
||||
[Updates](#updates) •
|
||||
[What and Why](#whatandwhy) •
|
||||
[What and Why](#what-and-why) •
|
||||
[Philosophy](#philosophy) •
|
||||
[Installation](#Installation) •
|
||||
[Usage](#Usage) •
|
||||
|
||||
@@ -57,7 +57,7 @@ func Cli(version string) (err error) {
|
||||
|
||||
if currentFlags.Serve {
|
||||
registry.ConfigureVendors()
|
||||
err = restapi.Serve(registry, currentFlags.ServeAddress)
|
||||
err = restapi.Serve(registry, currentFlags.ServeAddress, currentFlags.ServeAPIKey)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ type Flags struct {
|
||||
Serve bool `long:"serve" description:"Serve the Fabric Rest API"`
|
||||
ServeOllama bool `long:"serveOllama" description:"Serve the Fabric Rest API with ollama endpoints"`
|
||||
ServeAddress string `long:"address" description:"The address to bind the REST API" default:":8080"`
|
||||
ServeAPIKey string `long:"api-key" description:"API key used to secure server routes" default:""`
|
||||
Config string `long:"config" description:"Path to YAML config file"`
|
||||
Version bool `long:"version" description:"Print current version"`
|
||||
ListExtensions bool `long:"listextensions" description:"List all registered extensions"`
|
||||
|
||||
@@ -1 +1 @@
|
||||
"1.4.165"
|
||||
"1.4.168"
|
||||
|
||||
@@ -8,49 +8,39 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Define command line flags
|
||||
// Command line flags
|
||||
maxDepth := flag.Int("depth", 3, "Maximum directory depth to scan")
|
||||
ignorePatterns := flag.String("ignore", ".git,node_modules,vendor", "Comma-separated patterns to ignore")
|
||||
outputFile := flag.String("out", "", "Output file (default: stdout)")
|
||||
showHelp := flag.Bool("help", false, "Show help message")
|
||||
|
||||
// Parse command line flags
|
||||
flag.Usage = printUsage
|
||||
flag.Parse()
|
||||
|
||||
// Show help if requested or no arguments provided
|
||||
if *showHelp || flag.NArg() < 1 {
|
||||
// Require exactly two positional arguments: directory and instructions
|
||||
if flag.NArg() != 2 {
|
||||
printUsage()
|
||||
os.Exit(0)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Get directory and instructions from positional arguments
|
||||
directory := flag.Arg(0)
|
||||
instructions := ""
|
||||
if flag.NArg() > 1 {
|
||||
instructions = flag.Arg(1)
|
||||
}
|
||||
instructions := flag.Arg(1)
|
||||
|
||||
// Validate directory
|
||||
if _, err := os.Stat(directory); os.IsNotExist(err) {
|
||||
fmt.Fprintf(os.Stderr, "Error: Directory '%s' does not exist\n", directory)
|
||||
if info, err := os.Stat(directory); err != nil || !info.IsDir() {
|
||||
fmt.Fprintf(os.Stderr, "Error: Directory '%s' does not exist or is not a directory\n", directory)
|
||||
os.Exit(1)
|
||||
}
|
||||
// Parse ignore patterns
|
||||
ignoreList := ParseIgnorePatterns(*ignorePatterns)
|
||||
|
||||
// Scan directory and generate JSON
|
||||
var jsonData []byte
|
||||
var err error
|
||||
jsonData, err = ScanDirectory(directory, *maxDepth, instructions, ignoreList)
|
||||
// Parse ignore patterns and scan directory
|
||||
jsonData, err := ScanDirectory(directory, *maxDepth, instructions, strings.Split(*ignorePatterns, ","))
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
fmt.Fprintf(os.Stderr, "Error scanning directory: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Write output
|
||||
// Output result
|
||||
if *outputFile != "" {
|
||||
if err := os.WriteFile(*outputFile, jsonData, 0644); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error writing to file: %v\n", err)
|
||||
fmt.Fprintf(os.Stderr, "Error writing file: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
} else {
|
||||
@@ -58,30 +48,18 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
// ParseIgnorePatterns converts a comma-separated string of patterns to a slice
|
||||
func ParseIgnorePatterns(patterns string) []string {
|
||||
if patterns == "" {
|
||||
return nil
|
||||
}
|
||||
return strings.Split(patterns, ",")
|
||||
}
|
||||
|
||||
func printUsage() {
|
||||
fmt.Println(`code_helper - Code project scanner for use with Fabric AI
|
||||
fmt.Fprintf(os.Stderr, `code_helper - Code project scanner for use with Fabric AI
|
||||
|
||||
Usage:
|
||||
code_helper [options] <directory> [instructions]
|
||||
code_helper [options] <directory> <instructions>
|
||||
|
||||
Examples:
|
||||
# Scan current directory with instructions
|
||||
code_helper . "Add input validation to all user inputs"
|
||||
|
||||
# Scan specific directory with depth limit
|
||||
code_helper -depth 4 ./my-project "Implement error handling"
|
||||
|
||||
# Output to file instead of stdout
|
||||
code_helper -out project.json ./src "Fix security issues"
|
||||
|
||||
Options:`)
|
||||
Options:
|
||||
`)
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
|
||||
27
restapi/auth.go
Normal file
27
restapi/auth.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package restapi
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const APIKeyHeader = "X-API-Key"
|
||||
|
||||
func APIKeyMiddleware(apiKey string) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
headerApiKey := c.GetHeader(APIKeyHeader)
|
||||
|
||||
if headerApiKey == "" {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Missing API Key"})
|
||||
return
|
||||
}
|
||||
|
||||
if headerApiKey != apiKey {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Wrong API Key"})
|
||||
return
|
||||
}
|
||||
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,25 @@
|
||||
package restapi
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
|
||||
"github.com/danielmiessler/fabric/core"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func Serve(registry *core.PluginRegistry, address string) (err error) {
|
||||
func Serve(registry *core.PluginRegistry, address string, apiKey string) (err error) {
|
||||
r := gin.New()
|
||||
|
||||
// Middleware
|
||||
r.Use(gin.Logger())
|
||||
r.Use(gin.Recovery())
|
||||
|
||||
if apiKey != "" {
|
||||
r.Use(APIKeyMiddleware(apiKey))
|
||||
} else {
|
||||
slog.Warn("Starting REST API server without API key authentication. This may pose security risks.")
|
||||
}
|
||||
|
||||
// Register routes
|
||||
fabricDb := registry.Db
|
||||
NewPatternsHandler(r, fabricDb.Patterns)
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
package main
|
||||
|
||||
var version = "v1.4.165"
|
||||
var version = "v1.4.168"
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
{ code: 'es', name: 'Spanish' },
|
||||
{ code: 'de', name: 'German' },
|
||||
{ code: 'zh', name: 'Chinese' },
|
||||
{ code: 'ja', name: 'Japanese' }
|
||||
{ code: 'ja', name: 'Japanese' },
|
||||
{ code: 'it', name: 'Italian' }
|
||||
];
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user