package usermanager import ( "WWWShop/wwwshop/model/user" "database/sql" "fmt" "golang.org/x/crypto/bcrypt" "strings" "errors" ) type UserManager struct { db *sql.DB } func New(db *sql.DB) UserManager { return UserManager{db} } func (self UserManager) Add(username string, password_hash string) (*user.User, error) { var id int64 result := self.db.QueryRow("INSERT INTO users(username, password) VALUES ($1, $2) RETURNING id", username, password_hash) err := result.Scan(&id) if err != nil { return nil, err } user := user.New(id, username, password_hash) return &user, nil } func (self UserManager) AddWithPlainPassword(username string, password string) (*user.User, error) { password_hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { return nil, err } user, err := self.Add(username, string(password_hash)) return user, err } type QueryParameter interface{} func (self UserManager) GenerateWhere(cur_key *int64, ids []int64, usernames []string) string { where_string := "WHERE true " if usernames != nil && len(usernames) > 0 { where_string = strings.Join([]string{where_string, "AND ( false"}, "") for range usernames { where_string = strings.Join([]string{where_string, fmt.Sprintf(" OR username = $%d", *cur_key)}, "") (*cur_key)++ } where_string = strings.Join([]string{where_string, " ) "}, "") } if ids != nil && len(ids) > 0 { where_string = strings.Join([]string{where_string, "AND ( false"}, "") for range ids { where_string = strings.Join([]string{where_string, fmt.Sprintf(" OR id = $%d", *cur_key)}, "") (*cur_key)++ } where_string = strings.Join([]string{where_string, " ) "}, "") } return where_string } func (self UserManager) Delete(ids []int64, usernames []string) ([]string, error) { var where bool var cur_key int64 var where_string string cur_key = 1 if ids != nil && len(ids) > 0 { where = true } if usernames != nil && len(usernames) > 0 { where = true } if where { where_string = self.GenerateWhere(&cur_key, ids, usernames) } else { return nil, errors.New("Cannot delete without a clause") } query_parameters := make([]interface{}, 0) for _, username := range usernames { query_parameters = append(query_parameters, username) } for _, id := range ids { query_parameters = append(query_parameters, id) } query_string := fmt.Sprintf("DELETE FROM users %s RETURNING username", where_string) result, err := self.db.Query( query_string, query_parameters..., ) if err != nil { return nil, err } defer result.Close() var deleted_users []string for result.Next() { var username string err := result.Scan(&username) if err != nil { return nil, err } deleted_users = append(deleted_users, username) } if deleted_users == nil { deleted_users = make([]string, 0) } return deleted_users, nil } func (self UserManager) Retrieve(page int64, ids []int64, usernames []string) ([]user.User, error) { var where bool var cur_key int64 if ids != nil && len(ids) > 0 { where = true } if usernames != nil && len(usernames) > 0 { where = true } cur_key = 1 where_string := "" if where { where_string = self.GenerateWhere(&cur_key, ids, usernames) } page = (10 * page) page_string := fmt.Sprintf("LIMIT 10 OFFSET %d", page) query_parameters := make([]interface{}, 0) for _, username := range usernames { query_parameters = append(query_parameters, username) } for _, id := range ids { query_parameters = append(query_parameters, id) } query_string := fmt.Sprintf("SELECT id, username, password from users %s %s;", where_string, page_string) result, err := self.db.Query( query_string, query_parameters..., ) if err != nil { return nil, err } defer result.Close() var users []user.User for result.Next() { var ( id_user int64 username_user string password_user string ) err := result.Scan(&id_user, &username_user, &password_user) if err != nil { return nil, err } u := user.New(id_user, username_user, password_user) users = append(users, u) } if users == nil { users = make([]user.User, 0) } return users, nil }