package auth import ( "encoding/json" "fmt" "dynatron.me/x/blasphem/pkg/auth/provider" "dynatron.me/x/blasphem/pkg/storage" ) const ( AuthStoreKey = "auth" ) type AuthStore interface { User(UserID) *User Credential(provider.ProviderUser) *Credential } type authStore struct { Users []User `json:"users"` Groups []Group `json:"groups"` Credentials []Credential `json:"credentials"` Refresh []RefreshToken `json:"refresh_tokens"` userMap map[UserID]*User providerUsers map[provider.ProviderUser]*Credential } func (as *authStore) Credential(p provider.ProviderUser) *Credential { c, have := as.providerUsers[p] if !have { return nil } return c } func (a *Authenticator) newAuthStore(s storage.Store) (as *authStore, err error) { as = &authStore{} err = s.Get(AuthStoreKey, as) as.userMap = make(map[UserID]*User) as.providerUsers = make(map[provider.ProviderUser]*Credential) for _, u := range as.Users { as.userMap[u.ID] = &u } for _, c := range as.Credentials { prov := a.Provider(c.AuthProviderType) if prov == nil { return nil, fmt.Errorf("no such provider %s", c.AuthProviderType) } if c.DataRaw != nil { pd := prov.NewCredData() err := json.Unmarshal(*c.DataRaw, pd) if err != nil { return nil, err } c.user = prov.Lookup(pd.(provider.ProviderUser)) if c.user == nil { return nil, fmt.Errorf("cannot find user in provider %s", prov.ProviderName()) } as.providerUsers[c.user] = &c } } // remove invalid RefreshTokens i := 0 for _, rt := range as.Refresh { if rt.IsValid() { as.Refresh[i] = rt i++ } } // don't leak memory for j := i; j < len(as.Refresh); j++ { as.Refresh[j] = RefreshToken{} } as.Refresh = as.Refresh[:i] return } func (s *authStore) User(uid UserID) *User { return s.userMap[uid] }