package auth import ( "encoding/json" "errors" "io/fs" "os" "sync" ) type Store struct { file string users map[int64]bool mu sync.RWMutex } func New(file string) (*Store, error) { users, err := loadUsers(file) if err != nil { return nil, err } return &Store{ file: file, users: users, }, nil } func (s *Store) IsAllowed(userID int64) bool { s.mu.RLock() defer s.mu.RUnlock() return s.users[userID] } func (s *Store) IsEmpty() bool { s.mu.RLock() defer s.mu.RUnlock() return len(s.users) == 0 } func (s *Store) FirstUser(userID int64) error { s.mu.Lock() defer s.mu.Unlock() s.users[userID] = true return s.save() } func (s *Store) Add(userID int64) error { s.mu.Lock() defer s.mu.Unlock() s.users[userID] = true return s.save() } func (s *Store) Remove(userID int64) error { s.mu.Lock() defer s.mu.Unlock() delete(s.users, userID) return s.save() } func (s *Store) save() error { data, err := json.MarshalIndent(s.users, "", " ") if err != nil { return err } tmpFile := s.file + ".tmp" if err := os.WriteFile(tmpFile, data, 0644); err != nil { return err } return os.Rename(tmpFile, s.file) } func loadUsers(file string) (map[int64]bool, error) { data, err := os.ReadFile(file) if err != nil { if errors.Is(err, fs.ErrNotExist) { return make(map[int64]bool), nil } return nil, err } users := make(map[int64]bool) if len(data) == 0 { return users, nil } if err := json.Unmarshal(data, &users); err != nil { return nil, err } return users, nil }