github.com/crewjam/saml@v0.4.14/samlidp/user.go (about)

     1  package samlidp
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net/http"
     7  
     8  	"github.com/zenazn/goji/web"
     9  	"golang.org/x/crypto/bcrypt"
    10  )
    11  
    12  // User represents a stored user. The data here are used to
    13  // populate user once the user has authenticated.
    14  type User struct {
    15  	Name              string   `json:"name"`
    16  	PlaintextPassword *string  `json:"password,omitempty"` // not stored
    17  	HashedPassword    []byte   `json:"hashed_password,omitempty"`
    18  	Groups            []string `json:"groups,omitempty"`
    19  	Email             string   `json:"email,omitempty"`
    20  	CommonName        string   `json:"common_name,omitempty"`
    21  	Surname           string   `json:"surname,omitempty"`
    22  	GivenName         string   `json:"given_name,omitempty"`
    23  	ScopedAffiliation string   `json:"scoped_affiliation,omitempty"`
    24  }
    25  
    26  // HandleListUsers handles the `GET /users/` request and responds with a JSON formatted list
    27  // of user names.
    28  func (s *Server) HandleListUsers(_ web.C, w http.ResponseWriter, _ *http.Request) {
    29  	users, err := s.Store.List("/users/")
    30  	if err != nil {
    31  		s.logger.Printf("ERROR: %s", err)
    32  		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
    33  		return
    34  	}
    35  
    36  	err = json.NewEncoder(w).Encode(struct {
    37  		Users []string `json:"users"`
    38  	}{Users: users})
    39  	if err != nil {
    40  		s.logger.Printf("ERROR: %s", err)
    41  		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
    42  		return
    43  	}
    44  }
    45  
    46  // HandleGetUser handles the `GET /users/:id` request and responds with the user object in JSON
    47  // format. The HashedPassword field is excluded.
    48  func (s *Server) HandleGetUser(c web.C, w http.ResponseWriter, _ *http.Request) {
    49  	user := User{}
    50  	err := s.Store.Get(fmt.Sprintf("/users/%s", c.URLParams["id"]), &user)
    51  	if err != nil {
    52  		s.logger.Printf("ERROR: %s", err)
    53  		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
    54  		return
    55  	}
    56  	user.HashedPassword = nil
    57  	if err := json.NewEncoder(w).Encode(user); err != nil {
    58  		s.logger.Printf("ERROR: %s", err)
    59  		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
    60  		return
    61  	}
    62  }
    63  
    64  // HandlePutUser handles the `PUT /users/:id` request. It accepts a JSON formatted user object in
    65  // the request body and stores it. If the PlaintextPassword field is present then it is hashed
    66  // and stored in HashedPassword. If the PlaintextPassword field is not present then
    67  // HashedPassword retains it's stored value.
    68  func (s *Server) HandlePutUser(c web.C, w http.ResponseWriter, r *http.Request) {
    69  	user := User{}
    70  	if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
    71  		s.logger.Printf("ERROR: %s", err)
    72  		http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
    73  		return
    74  	}
    75  	user.Name = c.URLParams["id"]
    76  
    77  	if user.PlaintextPassword != nil {
    78  		var err error
    79  		user.HashedPassword, err = bcrypt.GenerateFromPassword([]byte(*user.PlaintextPassword), bcrypt.DefaultCost)
    80  		if err != nil {
    81  			s.logger.Printf("ERROR: %s", err)
    82  			http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
    83  			return
    84  		}
    85  	} else {
    86  		existingUser := User{}
    87  		err := s.Store.Get(fmt.Sprintf("/users/%s", c.URLParams["id"]), &existingUser)
    88  		switch {
    89  		case err == nil:
    90  			user.HashedPassword = existingUser.HashedPassword
    91  		case err == ErrNotFound:
    92  			// nop
    93  		default:
    94  			s.logger.Printf("ERROR: %s", err)
    95  			http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
    96  			return
    97  		}
    98  	}
    99  	user.PlaintextPassword = nil
   100  
   101  	err := s.Store.Put(fmt.Sprintf("/users/%s", c.URLParams["id"]), &user)
   102  	if err != nil {
   103  		s.logger.Printf("ERROR: %s", err)
   104  		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
   105  		return
   106  	}
   107  	w.WriteHeader(http.StatusNoContent)
   108  }
   109  
   110  // HandleDeleteUser handles the `DELETE /users/:id` request.
   111  func (s *Server) HandleDeleteUser(c web.C, w http.ResponseWriter, _ *http.Request) {
   112  	err := s.Store.Delete(fmt.Sprintf("/users/%s", c.URLParams["id"]))
   113  	if err != nil {
   114  		s.logger.Printf("ERROR: %s", err)
   115  		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
   116  		return
   117  	}
   118  	w.WriteHeader(http.StatusNoContent)
   119  }