hunk.code_window: 	// Settings represents Portainer settings.
   	Settings struct {
   		HiddenLabels   []Pair `json:"hiddenLabels"`
   		Logo           string `json:"logo"`
   		Authentication bool   `json:"authentication"`
   	}
   	// User represent a user account.
   	User struct {
  
hunk.labels: keep keep keep keep add keep keep keep keep
hunk.after_edit: 		Analytics      bool   `json:"analytics"`
  
hunk.file_path: api/portainer.go
hunk.type: add
file: package http
  
  import (
  	"github.com/portainer/portainer"
  
  	"encoding/json"
  	"log"
  	"net/http"
  	"os"
  
  	"github.com/asaskevich/govalidator"
  	"github.com/gorilla/mux"
  )
  
  // AuthHandler represents an HTTP API handler for managing authentication.
  type AuthHandler struct {
  	*mux.Router
  	Logger        *log.Logger
  	authDisabled  bool
  	UserService   portainer.UserService
  	CryptoService portainer.CryptoService
  	JWTService    portainer.JWTService
  }
  
  const (
  	// ErrInvalidCredentialsFormat is an error raised when credentials format is not valid
  	ErrInvalidCredentialsFormat = portainer.Error("Invalid credentials format")
  	// ErrInvalidCredentials is an error raised when credentials for a user are invalid
  	ErrInvalidCredentials = portainer.Error("Invalid credentials")
  	// ErrAuthDisabled is an error raised when trying to access the authentication endpoints
  	// when the server has been started with the --no-auth flag
  	ErrAuthDisabled = portainer.Error("Authentication is disabled")
  )
  
  // NewAuthHandler returns a new instance of AuthHandler.
  func NewAuthHandler() *AuthHandler {
  	h := &AuthHandler{
  		Router: mux.NewRouter(),
  		Logger: log.New(os.Stderr, "", log.LstdFlags),
  	}
  	h.HandleFunc("/auth", h.handlePostAuth)
  	return h
  }
  
  func (handler *AuthHandler) handlePostAuth(w http.ResponseWriter, r *http.Request) {
  	if r.Method != http.MethodPost {
  		handleNotAllowed(w, []string{http.MethodPost})
  		return
  	}
  
  	if handler.authDisabled {
  		Error(w, ErrAuthDisabled, http.StatusServiceUnavailable, handler.Logger)
  		return
  	}
  
  	var req postAuthRequest
  	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
  		Error(w, ErrInvalidJSON, http.StatusBadRequest, handler.Logger)
  		return
  	}
  
  	_, err := govalidator.ValidateStruct(req)
  	if err != nil {
  		Error(w, ErrInvalidCredentialsFormat, http.StatusBadRequest, handler.Logger)
  		return
  	}
  
  	var username = req.Username
  	var password = req.Password
  
  	u, err := handler.UserService.User(username)
  	if err == portainer.ErrUserNotFound {
  		Error(w, err, http.StatusNotFound, handler.Logger)
  		return
  	} else if err != nil {
  		Error(w, err, http.StatusInternalServerError, handler.Logger)
  		return
  	}
  
  	err = handler.CryptoService.CompareHashAndData(u.Password, password)
  	if err != nil {
  		Error(w, ErrInvalidCredentials, http.StatusUnprocessableEntity, handler.Logger)
  		return
  	}
  
  	tokenData := &portainer.TokenData{
  		username,
  	}
  	token, err := handler.JWTService.GenerateToken(tokenData)
  	if err != nil {
  		Error(w, err, http.StatusInternalServerError, handler.Logger)
  		return
  	}
  
  	encodeJSON(w, &postAuthResponse{JWT: token}, handler.Logger)
  }
  
  type postAuthRequest struct {
  	Username string `valid:"alphanum,required"`
  	Password string `valid:"required"`
  }
  
  type postAuthResponse struct {
  	JWT string `json:"jwt"`
  }
  