package test import ( "errors" "strings" "github.com/porter-dev/porter/internal/models" "github.com/porter-dev/porter/internal/repository" "golang.org/x/crypto/bcrypt" "gorm.io/gorm" ) const ( CreateUserMethod string = "create_user_0" ReadUserMethod string = "read_user_0" ReadUserByEmailMethod string = "read_user_by_email_0" DeleteUserMethod string = "delete_user_0" ) // UserRepository will return errors on queries if canQuery is false // and only stores a small set of users in-memory that are indexed by their // array index + 1 type UserRepository struct { canQuery bool failingMethods string users []*models.User } // NewUserRepository will return errors if canQuery is false func NewUserRepository(canQuery bool, failingMethods ...string) repository.UserRepository { return &UserRepository{canQuery, strings.Join(failingMethods, ","), []*models.User{}} } // CreateUser adds a new User row to the Users table in array memory func (repo *UserRepository) CreateUser(user *models.User) (*models.User, error) { if !repo.canQuery || strings.Contains(repo.failingMethods, CreateUserMethod) { return nil, errors.New("Cannot write database") } // make sure email doesn't exist for _, u := range repo.users { if u.Email == user.Email { return nil, errors.New("Cannot write database") } } users := repo.users users = append(users, user) repo.users = users user.ID = uint(len(repo.users)) return user, nil } // ReadUser finds a single user based on their unique id func (repo *UserRepository) ReadUser(id uint) (*models.User, error) { if !repo.canQuery || strings.Contains(repo.failingMethods, ReadUserMethod) { return nil, errors.New("Cannot read from database") } if int(id-1) >= len(repo.users) || repo.users[id-1] == nil { return nil, gorm.ErrRecordNotFound } index := int(id - 1) return repo.users[index], nil } func (repo *UserRepository) ListUsersByIDs(ids []uint) ([]*models.User, error) { if !repo.canQuery { return nil, errors.New("Cannot read from database") } resp := make([]*models.User, 0) // find all roles matching for _, user := range repo.users { for _, userID := range ids { if userID == user.ID { resp = append(resp, user) } } } return resp, nil } // ReadUserByEmail finds a single user based on their unique email func (repo *UserRepository) ReadUserByEmail(email string) (*models.User, error) { if !repo.canQuery || strings.Contains(repo.failingMethods, ReadUserByEmailMethod) { return nil, errors.New("Cannot read from database") } for _, u := range repo.users { if u.Email == email { return u, nil } } return nil, gorm.ErrRecordNotFound } // ReadUserByGithubUserID finds a single user based on their github id field func (repo *UserRepository) ReadUserByGithubUserID(id int64) (*models.User, error) { if !repo.canQuery { return nil, errors.New("Cannot read from database") } for _, u := range repo.users { if u.GithubUserID == id && id != 0 { return u, nil } } return nil, gorm.ErrRecordNotFound } // ReadUserByGoogleUserID finds a single user based on their github id field func (repo *UserRepository) ReadUserByGoogleUserID(id string) (*models.User, error) { if !repo.canQuery { return nil, errors.New("Cannot read from database") } for _, u := range repo.users { if u.GoogleUserID == id && id != "" { return u, nil } } return nil, gorm.ErrRecordNotFound } // UpdateUser modifies an existing User in the database func (repo *UserRepository) UpdateUser(user *models.User) (*models.User, error) { if !repo.canQuery { return nil, errors.New("Cannot write database") } if int(user.ID-1) >= len(repo.users) || repo.users[user.ID-1] == nil { return nil, gorm.ErrRecordNotFound } index := int(user.ID - 1) oldUser := *repo.users[index] repo.users[index] = user user.Email = oldUser.Email user.Password = oldUser.Password return user, nil } // DeleteUser deletes a single user using their unique id func (repo *UserRepository) DeleteUser(user *models.User) (*models.User, error) { if !repo.canQuery || strings.Contains(repo.failingMethods, DeleteUserMethod) { return nil, errors.New("Cannot write database") } if int(user.ID-1) >= len(repo.users) || repo.users[user.ID-1] == nil { return nil, gorm.ErrRecordNotFound } index := int(user.ID - 1) repo.users[index] = nil return user, nil } // CheckPassword checks the input password is correct for the provided user id. func (repo *UserRepository) CheckPassword(id int, pwd string) (bool, error) { if !repo.canQuery { return false, errors.New("Cannot write database") } if int(id-1) >= len(repo.users) || repo.users[id-1] == nil { return false, gorm.ErrRecordNotFound } index := int(id - 1) user := *repo.users[index] if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(pwd)); err != nil { return false, err } return true, nil }