github.com/mssola/todo@v0.0.0-20181029153210-d25348dc3f48/app/users.go (about)

     1  // Copyright (C) 2014-2017 Miquel Sabaté Solà <mikisabate@gmail.com>
     2  //
     3  // This Source Code Form is subject to the terms of the Mozilla Public
     4  // License, v. 2.0. If a copy of the MPL was not distributed with this
     5  // file, You can obtain one at http://mozilla.org/MPL/2.0/.
     6  
     7  package app
     8  
     9  import (
    10  	"errors"
    11  	"log"
    12  	"net/http"
    13  	"time"
    14  
    15  	"github.com/docker/distribution/uuid"
    16  	"github.com/mssola/go-utils/security"
    17  )
    18  
    19  // User contains a user in this application.
    20  type User struct {
    21  	ID           string    `json:"token"`
    22  	Name         string    `json:"-"`
    23  	PasswordHash string    `json:"-" db:"password_hash"`
    24  	CreatedAt    time.Time `json:"-" db:"created_at"`
    25  }
    26  
    27  // Create a new user with the given name and password. The given password is
    28  // stored as-is. Therefore, it should've been encrypted before calling this
    29  // function.
    30  func createUser(name, password string) error {
    31  	// Only one user is allowed in this application.
    32  	if count, err := Db.SelectInt("select count(*) from users"); err != nil {
    33  		return err
    34  	} else if count > 0 {
    35  		return errors.New("too many users")
    36  	}
    37  
    38  	// Create the user and redirect.
    39  	id := uuid.Generate().String()
    40  	return Db.Insert(&User{ID: id, Name: name, PasswordHash: password})
    41  }
    42  
    43  // Match the user with the given name and password and its id.
    44  func matchPassword(name, password string) (string, error) {
    45  	var u User
    46  
    47  	e := Db.SelectOne(&u, "select * from users where name=$1", name)
    48  	if e != nil {
    49  		return "", e
    50  	}
    51  	if !security.PasswordMatch(u.PasswordHash, password) {
    52  		return "", errors.New("Wrong password!")
    53  	}
    54  	return u.ID, nil
    55  }
    56  
    57  // UsersCreate responds to: POST /users. It expects the "name" and the
    58  // "password" form values to be present. Moreover, only one user is
    59  // allowed in this application.
    60  func UsersCreate(res http.ResponseWriter, req *http.Request) {
    61  	password := security.PasswordSalt(req.FormValue("password"))
    62  
    63  	if err := createUser(req.FormValue("name"), password); err != nil {
    64  		log.Printf("Could not create user: %v", err)
    65  		http.Redirect(res, req, "/", http.StatusForbidden)
    66  	} else {
    67  		http.Redirect(res, req, "/", http.StatusFound)
    68  	}
    69  }