package store import ( "time" "git.tukangketik.id/swanadiva/hostkeeper/v2/internal/model" ) type KeyStore struct { keys []model.Key } func NewKeyStore() *KeyStore { s := &KeyStore{} mu.RLock() readFile("keys.json", &s.keys) mu.RUnlock() if s.keys == nil { s.keys = []model.Key{} } return s } func (s *KeyStore) All() []model.Key { mu.RLock() defer mu.RUnlock() return s.keys } func (s *KeyStore) Search(q string) []model.Key { mu.RLock() defer mu.RUnlock() if q == "" { return s.keys } var res []model.Key for _, k := range s.keys { if contains(k.Name, q) || contains(k.Username, q) || contains(k.URL, q) { res = append(res, k) } } return res } func (s *KeyStore) Add(name, username, url, passphrase string) model.Key { mu.Lock() defer mu.Unlock() keyType := guessKeyType(name, passphrase) k := model.Key{ ID: randID(), Name: name, Username: username, Passphrase: passphrase, Strength: calcStrength(passphrase), Type: keyType, URL: url, KeyFile: "— " + keyType + " credential —", CreatedAt: time.Now().Format("Jan 2, 2006"), } s.keys = append(s.keys, k) writeFile("keys.json", &s.keys) return k } func guessKeyType(name, passphrase string) string { switch { case len(passphrase) >= 25: return "ED25519" case contains(name, "aws") || contains(name, "AWS"): return "AWS Key" case contains(name, "token") || contains(name, "bearer") || contains(name, "TOKEN"): return "Bearer Token" case len(passphrase) <= 3: return "PASSWORD" default: return "SSH RSA" } } func (s *KeyStore) Delete(id string) { mu.Lock() defer mu.Unlock() for i, k := range s.keys { if k.ID == id { s.keys = append(s.keys[:i], s.keys[i+1:]...) writeFile("keys.json", &s.keys) return } } } func calcStrength(p string) string { l, d, u, s := 0, 0, 0, 0 for _, c := range p { switch { case c >= 'a' && c <= 'z': l++ case c >= 'A' && c <= 'Z': u++ case c >= '0' && c <= '9': d++ default: s++ } } if len(p) >= 12 && u >= 1 && d >= 1 && s >= 1 { return "secure" } if len(p) >= 8 && u+d+s >= 2 { return "moderate" } return "weak" }