122 lines
3.2 KiB
Go
122 lines
3.2 KiB
Go
package amp
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/aoagents/agent-orchestrator/backend/internal/adapters/agent/authprobe"
|
|
"github.com/aoagents/agent-orchestrator/backend/internal/ports"
|
|
)
|
|
|
|
var _ ports.AgentAuthChecker = (*Plugin)(nil)
|
|
|
|
// AuthStatus returns the plugin's local authentication status.
|
|
func (p *Plugin) AuthStatus(ctx context.Context) (ports.AgentAuthStatus, error) {
|
|
binary, err := p.ResolveBinary(ctx)
|
|
if err != nil {
|
|
return ports.AgentAuthStatusUnknown, err
|
|
}
|
|
if status, ok, err := ampLocalAuthStatus(ctx); err != nil || ok {
|
|
return status, err
|
|
}
|
|
return ampUsageAuthStatus(ctx, binary)
|
|
}
|
|
|
|
func ampLocalAuthStatus(ctx context.Context) (ports.AgentAuthStatus, bool, error) {
|
|
if err := ctx.Err(); err != nil {
|
|
return ports.AgentAuthStatusUnknown, false, err
|
|
}
|
|
if strings.TrimSpace(os.Getenv("AMP_API_KEY")) != "" {
|
|
return ports.AgentAuthStatusAuthorized, true, nil
|
|
}
|
|
status, ok, err := ampSettingsAuthStatus(ampSettingsPath())
|
|
if err != nil {
|
|
return ports.AgentAuthStatusUnknown, false, err
|
|
}
|
|
return status, ok, nil
|
|
}
|
|
|
|
func ampSettingsPath() string {
|
|
if path := strings.TrimSpace(os.Getenv("AMP_SETTINGS_FILE")); path != "" {
|
|
return expandHome(path)
|
|
}
|
|
if home, err := os.UserHomeDir(); err == nil && home != "" {
|
|
return filepath.Join(home, ".config", "amp", "settings.json")
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func ampSettingsAuthStatus(path string) (ports.AgentAuthStatus, bool, error) {
|
|
if path == "" {
|
|
return ports.AgentAuthStatusUnknown, false, nil
|
|
}
|
|
data, err := os.ReadFile(path)
|
|
if err != nil {
|
|
if errors.Is(err, os.ErrNotExist) {
|
|
return ports.AgentAuthStatusUnknown, false, nil
|
|
}
|
|
return ports.AgentAuthStatusUnknown, false, err
|
|
}
|
|
var settings map[string]any
|
|
if err := json.Unmarshal(data, &settings); err != nil {
|
|
return ports.AgentAuthStatusUnknown, false, err
|
|
}
|
|
for _, key := range []string{"amp.apiKey", "amp.api_key", "apiKey", "api_key"} {
|
|
if value, ok := settings[key]; ok {
|
|
if strings.TrimSpace(stringValue(value)) != "" {
|
|
return ports.AgentAuthStatusAuthorized, true, nil
|
|
}
|
|
return ports.AgentAuthStatusUnauthorized, true, nil
|
|
}
|
|
}
|
|
return ports.AgentAuthStatusUnknown, false, nil
|
|
}
|
|
|
|
func ampUsageAuthStatus(ctx context.Context, binary string) (ports.AgentAuthStatus, error) {
|
|
if binary == "" {
|
|
return ports.AgentAuthStatusUnknown, nil
|
|
}
|
|
probeCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
|
defer cancel()
|
|
|
|
out, err := authprobe.CmdRunner(probeCtx, binary, "usage", "--no-color")
|
|
if probeCtx.Err() != nil {
|
|
return ports.AgentAuthStatusUnknown, probeCtx.Err()
|
|
}
|
|
if status := authprobe.StatusFromText(string(out)); status != ports.AgentAuthStatusUnknown {
|
|
return status, nil
|
|
}
|
|
if err == nil {
|
|
return ports.AgentAuthStatusAuthorized, nil
|
|
}
|
|
return ports.AgentAuthStatusUnknown, nil
|
|
}
|
|
|
|
func stringValue(value any) string {
|
|
switch v := value.(type) {
|
|
case string:
|
|
return v
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
func expandHome(path string) string {
|
|
if path == "~" {
|
|
if home, err := os.UserHomeDir(); err == nil {
|
|
return home
|
|
}
|
|
}
|
|
if strings.HasPrefix(path, "~/") {
|
|
if home, err := os.UserHomeDir(); err == nil {
|
|
return filepath.Join(home, strings.TrimPrefix(path, "~/"))
|
|
}
|
|
}
|
|
return path
|
|
}
|