package main import ( "fmt" "golang.org/x/crypto/bcrypt" ) var ErrUserNotFound = fmt.Errorf("user not found") type User struct { Name string Roles []string } type storeUser struct { name string roles []string passwordHash []byte } type Userstore struct { users map[string]storeUser } func (u *Userstore) Create(name string, roles []string, password string) error { if u.users == nil { u.users = map[string]storeUser{} } hashed, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { return err } u.users[name] = storeUser{ name: name, roles: roles, passwordHash: hashed, } return nil } func (u *Userstore) UpdatePassword(name string, password string) error { if u.users == nil { u.users = map[string]storeUser{} return ErrUserNotFound } hashed, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { return err } user, ok := u.users[name] if !ok { return ErrUserNotFound } user.passwordHash = hashed u.users[name] = user return nil } func (u *Userstore) UpdateUser(name string, updatedUser User) error { if u.users == nil { u.users = map[string]storeUser{} return ErrUserNotFound } user, ok := u.users[name] if !ok { return ErrUserNotFound } user.name = updatedUser.Name user.roles = updatedUser.Roles u.users[name] = user return nil } func (u *Userstore) Authenticate(name string, password string) (User, error) { if u.users == nil { u.users = map[string]storeUser{} return User{}, ErrUserNotFound } user, ok := u.users[name] if !ok { return User{}, ErrUserNotFound } err := bcrypt.CompareHashAndPassword(user.passwordHash, []byte(password)) if err != nil { return User{}, err } return User{ Name: user.name, Roles: user.roles, }, nil } func (u *Userstore) Delete(name string) error { if u.users == nil { u.users = map[string]storeUser{} return ErrUserNotFound } _, ok := u.users[name] if !ok { return ErrUserNotFound } delete(u.users, name) return nil }