package autofillcache import ( "encoding/json" "net/url" "os" "path/filepath" "strings" "time" "git.julianfamily.org/keepassgo/vault" ) type Entry struct { ID string `json:"id"` Title string `json:"title"` Username string `json:"username"` Password string `json:"password"` URL string `json:"url"` Host string `json:"host"` Path []string `json:"path,omitempty"` } type File struct { UpdatedAt string `json:"updatedAt"` Entries []Entry `json:"entries"` } func Build(model vault.Model, now time.Time) File { entries := make([]Entry, 0, len(model.Entries)) for _, item := range model.Entries { host := normalizeHost(item.URL) if host == "" { continue } if strings.TrimSpace(item.Username) == "" || strings.TrimSpace(item.Password) == "" { continue } entries = append(entries, Entry{ ID: item.ID, Title: item.Title, Username: item.Username, Password: item.Password, URL: item.URL, Host: host, Path: append([]string(nil), item.Path...), }) } return File{ UpdatedAt: now.UTC().Format(time.RFC3339), Entries: entries, } } func Write(path string, model vault.Model, now time.Time) error { if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { return err } data, err := json.MarshalIndent(Build(model, now), "", " ") if err != nil { return err } return os.WriteFile(path, data, 0o600) } func Clear(path string) error { if err := os.Remove(path); err != nil && !os.IsNotExist(err) { return err } return nil } func normalizeHost(raw string) string { value := strings.TrimSpace(raw) if value == "" { return "" } if !strings.Contains(value, "://") { value = "https://" + value } parsed, err := url.Parse(value) if err != nil { return "" } host := strings.TrimSpace(parsed.Hostname()) return strings.ToLower(host) }