package models import ( "context" "code.crute.us/mcrute/golib/db/mongodb" ) const userCol = "users" type UserStore interface { List(context.Context) ([]*User, error) Get(context.Context, string) (*User, error) // Error on not found Put(context.Context, *User) error Delete(context.Context, *User) error } type AuthToken struct { Kind string Token string RefreshToken string } type User struct { Username string `bson:"_id"` IsAdmin bool IsService bool Keys map[string]*SessionKey // kid -> key AuthTokens map[string]*AuthToken // kind -> token } // GCKeys garbage collects keys that are no longer valid func (u *User) GCKeys() { for k, v := range u.Keys { if v.IsGarbage() { delete(u.Keys, k) } } } // GetKey returns a key for a key ID. It will only return valid keys. func (u *User) GetKey(kid string) *SessionKey { if u.Keys != nil { if k := u.Keys[kid]; k != nil && k.IsValid() { return k } } return nil } func (u *User) AddKey(k *SessionKey) { if u.Keys == nil { u.Keys = map[string]*SessionKey{} } u.Keys[k.KeyId] = k } func (u *User) AddToken(t *AuthToken) { if u.AuthTokens == nil { u.AuthTokens = map[string]*AuthToken{} } u.AuthTokens[t.Kind] = t } type MongoDbUserStore struct { Db *mongodb.Mongo } func (s *MongoDbUserStore) List(ctx context.Context) ([]*User, error) { var out []*User if err := s.Db.FindAll(ctx, userCol, &out); err != nil { return nil, err } return out, nil } func (s *MongoDbUserStore) Get(ctx context.Context, username string) (*User, error) { var u User if err := s.Db.FindOneById(ctx, userCol, username, &u); err != nil { return nil, err } return &u, nil } func (s *MongoDbUserStore) Put(ctx context.Context, u *User) error { if err := s.Db.ReplaceOneById(ctx, userCol, u.Username, u); err != nil { return err } return nil } func (s *MongoDbUserStore) Delete(ctx context.Context, u *User) error { if err := s.Db.DeleteOneById(ctx, userCol, u.Username); err != nil { return err } return nil } var _ UserStore = (*MongoDbUserStore)(nil)