You've already forked nginx-proxy-manager
							
							
				mirror of
				https://github.com/NginxProxyManager/nginx-proxy-manager.git
				synced 2025-10-30 18:05:34 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			236 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			236 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package handler
 | |
| 
 | |
| import (
 | |
| 	"encoding/json"
 | |
| 	"net/http"
 | |
| 
 | |
| 	c "npm/internal/api/context"
 | |
| 	h "npm/internal/api/http"
 | |
| 	"npm/internal/api/middleware"
 | |
| 	"npm/internal/config"
 | |
| 	"npm/internal/entity/auth"
 | |
| 	"npm/internal/entity/user"
 | |
| 	"npm/internal/errors"
 | |
| 	"npm/internal/logger"
 | |
| 
 | |
| 	"github.com/go-chi/chi"
 | |
| )
 | |
| 
 | |
| // GetUsers returns all users
 | |
| // Route: GET /users
 | |
| func GetUsers() func(http.ResponseWriter, *http.Request) {
 | |
| 	return func(w http.ResponseWriter, r *http.Request) {
 | |
| 		pageInfo, err := getPageInfoFromRequest(r)
 | |
| 		if err != nil {
 | |
| 			h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		users, err := user.List(pageInfo, middleware.GetFiltersFromContext(r), getExpandFromContext(r))
 | |
| 		if err != nil {
 | |
| 			h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
 | |
| 		} else {
 | |
| 			h.ResultResponseJSON(w, r, http.StatusOK, users)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // GetUser returns a specific user
 | |
| // Route: GET /users/{userID}
 | |
| func GetUser() func(http.ResponseWriter, *http.Request) {
 | |
| 	return func(w http.ResponseWriter, r *http.Request) {
 | |
| 		userID, _, userIDErr := getUserIDFromRequest(r)
 | |
| 		if userIDErr != nil {
 | |
| 			h.ResultErrorJSON(w, r, http.StatusBadRequest, userIDErr.Error(), nil)
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		userObject, err := user.GetByID(userID)
 | |
| 		if err != nil {
 | |
| 			h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
 | |
| 		} else {
 | |
| 			// nolint: errcheck,gosec
 | |
| 			userObject.Expand(getExpandFromContext(r))
 | |
| 			h.ResultResponseJSON(w, r, http.StatusOK, userObject)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // UpdateUser updates a user
 | |
| // Route: PUT /users/{userID}
 | |
| func UpdateUser() func(http.ResponseWriter, *http.Request) {
 | |
| 	return func(w http.ResponseWriter, r *http.Request) {
 | |
| 		userID, self, userIDErr := getUserIDFromRequest(r)
 | |
| 		if userIDErr != nil {
 | |
| 			h.ResultErrorJSON(w, r, http.StatusBadRequest, userIDErr.Error(), nil)
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		userObject, err := user.GetByID(userID)
 | |
| 		if err != nil {
 | |
| 			h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
 | |
| 		} else {
 | |
| 			// nolint: errcheck,gosec
 | |
| 			userObject.Expand([]string{"capabilities"})
 | |
| 			bodyBytes, _ := r.Context().Value(c.BodyCtxKey).([]byte)
 | |
| 			err := json.Unmarshal(bodyBytes, &userObject)
 | |
| 			if err != nil {
 | |
| 				h.ResultErrorJSON(w, r, http.StatusBadRequest, h.ErrInvalidPayload.Error(), nil)
 | |
| 				return
 | |
| 			}
 | |
| 
 | |
| 			if userObject.IsDisabled && self {
 | |
| 				h.ResultErrorJSON(w, r, http.StatusBadRequest, "You cannot disable yourself!", nil)
 | |
| 				return
 | |
| 			}
 | |
| 
 | |
| 			if err = userObject.Save(); err != nil {
 | |
| 				if err == errors.ErrDuplicateEmailUser || err == errors.ErrSystemUserReadonly {
 | |
| 					h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
 | |
| 				} else {
 | |
| 					logger.Error("UpdateUserError", err)
 | |
| 					h.ResultErrorJSON(w, r, http.StatusInternalServerError, "Unable to save User", nil)
 | |
| 				}
 | |
| 				return
 | |
| 			}
 | |
| 
 | |
| 			if !self {
 | |
| 				err = userObject.SaveCapabilities()
 | |
| 				if err != nil {
 | |
| 					h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
 | |
| 					return
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			// nolint: errcheck,gosec
 | |
| 			userObject.Expand(getExpandFromContext(r))
 | |
| 
 | |
| 			h.ResultResponseJSON(w, r, http.StatusOK, userObject)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // DeleteUser removes a user
 | |
| // Route: DELETE /users/{userID}
 | |
| func DeleteUser() func(http.ResponseWriter, *http.Request) {
 | |
| 	return func(w http.ResponseWriter, r *http.Request) {
 | |
| 		var userID int
 | |
| 		var err error
 | |
| 		if userID, err = getURLParamInt(r, "userID"); err != nil {
 | |
| 			h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		myUserID, _ := r.Context().Value(c.UserIDCtxKey).(int)
 | |
| 		if myUserID == userID {
 | |
| 			h.ResultErrorJSON(w, r, http.StatusBadRequest, "You cannot delete yourself!", nil)
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		user, err := user.GetByID(userID)
 | |
| 		if err != nil {
 | |
| 			h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
 | |
| 		} else {
 | |
| 			h.ResultResponseJSON(w, r, http.StatusOK, user.Delete())
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // CreateUser creates a user
 | |
| // Route: POST /users
 | |
| func CreateUser() func(http.ResponseWriter, *http.Request) {
 | |
| 	return func(w http.ResponseWriter, r *http.Request) {
 | |
| 		bodyBytes, _ := r.Context().Value(c.BodyCtxKey).([]byte)
 | |
| 
 | |
| 		var newUser user.Model
 | |
| 		err := json.Unmarshal(bodyBytes, &newUser)
 | |
| 		if err != nil {
 | |
| 			h.ResultErrorJSON(w, r, http.StatusBadRequest, h.ErrInvalidPayload.Error(), nil)
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		if err = newUser.Save(); err != nil {
 | |
| 			if err == errors.ErrDuplicateEmailUser || err == errors.ErrSystemUserReadonly {
 | |
| 				h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
 | |
| 			} else {
 | |
| 				logger.Error("UpdateUserError", err)
 | |
| 				h.ResultErrorJSON(w, r, http.StatusInternalServerError, "Unable to save User", nil)
 | |
| 			}
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		// Set the permissions to full-admin for this user
 | |
| 		if !config.IsSetup {
 | |
| 			newUser.Capabilities = []string{user.CapabilityFullAdmin}
 | |
| 		}
 | |
| 
 | |
| 		// nolint: errcheck,gosec
 | |
| 		err = newUser.SaveCapabilities()
 | |
| 		if err != nil {
 | |
| 			h.ResultErrorJSON(w, r, http.StatusInternalServerError, err.Error(), nil)
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		// newUser has been saved, now save their auth
 | |
| 		if newUser.Auth.Secret != "" && newUser.Auth.ID == 0 {
 | |
| 			newUser.Auth.UserID = newUser.ID
 | |
| 			if newUser.Auth.Type == auth.TypePassword {
 | |
| 				err = newUser.Auth.SetPassword(newUser.Auth.Secret)
 | |
| 				if err != nil {
 | |
| 					logger.Error("SetPasswordError", err)
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			if err = newUser.Auth.Save(); err != nil {
 | |
| 				h.ResultErrorJSON(w, r, http.StatusInternalServerError, "Unable to save Authentication for User", nil)
 | |
| 				return
 | |
| 			}
 | |
| 
 | |
| 			newUser.Auth.Secret = ""
 | |
| 		}
 | |
| 
 | |
| 		if !config.IsSetup {
 | |
| 			config.IsSetup = true
 | |
| 			logger.Info("A new user was created, leaving Setup Mode")
 | |
| 		}
 | |
| 
 | |
| 		h.ResultResponseJSON(w, r, http.StatusOK, newUser)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // DeleteUsers is only available in debug mode for cypress tests
 | |
| // Route: DELETE /users
 | |
| func DeleteUsers() func(http.ResponseWriter, *http.Request) {
 | |
| 	return func(w http.ResponseWriter, r *http.Request) {
 | |
| 		err := user.DeleteAll()
 | |
| 		if err != nil {
 | |
| 			h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
 | |
| 		} else {
 | |
| 			// also change setup to true
 | |
| 			config.IsSetup = false
 | |
| 			logger.Info("Users have been wiped, entering Setup Mode")
 | |
| 			h.ResultResponseJSON(w, r, http.StatusOK, true)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func getUserIDFromRequest(r *http.Request) (int, bool, error) {
 | |
| 	userIDstr := chi.URLParam(r, "userID")
 | |
| 	selfUserID, _ := r.Context().Value(c.UserIDCtxKey).(int)
 | |
| 
 | |
| 	var userID int
 | |
| 	self := false
 | |
| 	if userIDstr == "me" {
 | |
| 		// Get user id from Token
 | |
| 		userID = selfUserID
 | |
| 		self = true
 | |
| 	} else {
 | |
| 		var userIDerr error
 | |
| 		if userID, userIDerr = getURLParamInt(r, "userID"); userIDerr != nil {
 | |
| 			return 0, false, userIDerr
 | |
| 		}
 | |
| 		self = selfUserID == userID
 | |
| 	}
 | |
| 	return userID, self, nil
 | |
| }
 |