mirror of
https://github.com/portainer/portainer.git
synced 2025-08-01 20:05:23 +02:00
feat(api): introduces swagger.yml (#1112)
This commit is contained in:
parent
d3e87b2435
commit
92391254bc
19 changed files with 2691 additions and 286 deletions
|
@ -4,7 +4,6 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// errorResponse is a generic response for sending a error.
|
// errorResponse is a generic response for sending a error.
|
||||||
|
@ -21,10 +20,3 @@ func WriteErrorResponse(w http.ResponseWriter, err error, code int, logger *log.
|
||||||
w.WriteHeader(code)
|
w.WriteHeader(code)
|
||||||
json.NewEncoder(w).Encode(&errorResponse{Err: err.Error()})
|
json.NewEncoder(w).Encode(&errorResponse{Err: err.Error()})
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteMethodNotAllowedResponse writes an error message to the response and sets the Allow header.
|
|
||||||
func WriteMethodNotAllowedResponse(w http.ResponseWriter, allowedMethods []string) {
|
|
||||||
w.Header().Set("Allow", strings.Join(allowedMethods, ", "))
|
|
||||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
|
||||||
json.NewEncoder(w).Encode(&errorResponse{Err: http.StatusText(http.StatusMethodNotAllowed)})
|
|
||||||
}
|
|
||||||
|
|
|
@ -44,17 +44,23 @@ func NewAuthHandler(bouncer *security.RequestBouncer, authDisabled bool) *AuthHa
|
||||||
authDisabled: authDisabled,
|
authDisabled: authDisabled,
|
||||||
}
|
}
|
||||||
h.Handle("/auth",
|
h.Handle("/auth",
|
||||||
bouncer.PublicAccess(http.HandlerFunc(h.handlePostAuth)))
|
bouncer.PublicAccess(http.HandlerFunc(h.handlePostAuth))).Methods(http.MethodPost)
|
||||||
|
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler *AuthHandler) handlePostAuth(w http.ResponseWriter, r *http.Request) {
|
type (
|
||||||
if r.Method != http.MethodPost {
|
postAuthRequest struct {
|
||||||
httperror.WriteMethodNotAllowedResponse(w, []string{http.MethodPost})
|
Username string `valid:"required"`
|
||||||
return
|
Password string `valid:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
postAuthResponse struct {
|
||||||
|
JWT string `json:"jwt"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (handler *AuthHandler) handlePostAuth(w http.ResponseWriter, r *http.Request) {
|
||||||
if handler.authDisabled {
|
if handler.authDisabled {
|
||||||
httperror.WriteErrorResponse(w, ErrAuthDisabled, http.StatusServiceUnavailable, handler.Logger)
|
httperror.WriteErrorResponse(w, ErrAuthDisabled, http.StatusServiceUnavailable, handler.Logger)
|
||||||
return
|
return
|
||||||
|
@ -118,12 +124,3 @@ func (handler *AuthHandler) handlePostAuth(w http.ResponseWriter, r *http.Reques
|
||||||
|
|
||||||
encodeJSON(w, &postAuthResponse{JWT: token}, handler.Logger)
|
encodeJSON(w, &postAuthResponse{JWT: token}, handler.Logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
type postAuthRequest struct {
|
|
||||||
Username string `valid:"required"`
|
|
||||||
Password string `valid:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type postAuthResponse struct {
|
|
||||||
JWT string `json:"jwt"`
|
|
||||||
}
|
|
||||||
|
|
|
@ -22,20 +22,28 @@ type DockerHubHandler struct {
|
||||||
DockerHubService portainer.DockerHubService
|
DockerHubService portainer.DockerHubService
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDockerHubHandler returns a new instance of OldDockerHubHandler.
|
// NewDockerHubHandler returns a new instance of NewDockerHubHandler.
|
||||||
func NewDockerHubHandler(bouncer *security.RequestBouncer) *DockerHubHandler {
|
func NewDockerHubHandler(bouncer *security.RequestBouncer) *DockerHubHandler {
|
||||||
h := &DockerHubHandler{
|
h := &DockerHubHandler{
|
||||||
Router: mux.NewRouter(),
|
Router: mux.NewRouter(),
|
||||||
Logger: log.New(os.Stderr, "", log.LstdFlags),
|
Logger: log.New(os.Stderr, "", log.LstdFlags),
|
||||||
}
|
}
|
||||||
h.Handle("/dockerhub",
|
h.Handle("/dockerhub",
|
||||||
bouncer.PublicAccess(http.HandlerFunc(h.handleGetDockerHub))).Methods(http.MethodGet)
|
bouncer.AuthenticatedAccess(http.HandlerFunc(h.handleGetDockerHub))).Methods(http.MethodGet)
|
||||||
h.Handle("/dockerhub",
|
h.Handle("/dockerhub",
|
||||||
bouncer.AdministratorAccess(http.HandlerFunc(h.handlePutDockerHub))).Methods(http.MethodPut)
|
bouncer.AdministratorAccess(http.HandlerFunc(h.handlePutDockerHub))).Methods(http.MethodPut)
|
||||||
|
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
putDockerHubRequest struct {
|
||||||
|
Authentication bool `valid:""`
|
||||||
|
Username string `valid:""`
|
||||||
|
Password string `valid:""`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// handleGetDockerHub handles GET requests on /dockerhub
|
// handleGetDockerHub handles GET requests on /dockerhub
|
||||||
func (handler *DockerHubHandler) handleGetDockerHub(w http.ResponseWriter, r *http.Request) {
|
func (handler *DockerHubHandler) handleGetDockerHub(w http.ResponseWriter, r *http.Request) {
|
||||||
dockerhub, err := handler.DockerHubService.DockerHub()
|
dockerhub, err := handler.DockerHubService.DockerHub()
|
||||||
|
@ -79,9 +87,3 @@ func (handler *DockerHubHandler) handlePutDockerHub(w http.ResponseWriter, r *ht
|
||||||
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger)
|
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type putDockerHubRequest struct {
|
|
||||||
Authentication bool `valid:""`
|
|
||||||
Username string `valid:""`
|
|
||||||
Password string `valid:""`
|
|
||||||
}
|
|
||||||
|
|
|
@ -55,6 +55,31 @@ func NewEndpointHandler(bouncer *security.RequestBouncer, authorizeEndpointManag
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
postEndpointsRequest struct {
|
||||||
|
Name string `valid:"required"`
|
||||||
|
URL string `valid:"required"`
|
||||||
|
PublicURL string `valid:"-"`
|
||||||
|
TLS bool
|
||||||
|
}
|
||||||
|
|
||||||
|
postEndpointsResponse struct {
|
||||||
|
ID int `json:"Id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
putEndpointAccessRequest struct {
|
||||||
|
AuthorizedUsers []int `valid:"-"`
|
||||||
|
AuthorizedTeams []int `valid:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
putEndpointsRequest struct {
|
||||||
|
Name string `valid:"-"`
|
||||||
|
URL string `valid:"-"`
|
||||||
|
PublicURL string `valid:"-"`
|
||||||
|
TLS bool `valid:"-"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// handleGetEndpoints handles GET requests on /endpoints
|
// handleGetEndpoints handles GET requests on /endpoints
|
||||||
func (handler *EndpointHandler) handleGetEndpoints(w http.ResponseWriter, r *http.Request) {
|
func (handler *EndpointHandler) handleGetEndpoints(w http.ResponseWriter, r *http.Request) {
|
||||||
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
||||||
|
@ -130,17 +155,6 @@ func (handler *EndpointHandler) handlePostEndpoints(w http.ResponseWriter, r *ht
|
||||||
encodeJSON(w, &postEndpointsResponse{ID: int(endpoint.ID)}, handler.Logger)
|
encodeJSON(w, &postEndpointsResponse{ID: int(endpoint.ID)}, handler.Logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
type postEndpointsRequest struct {
|
|
||||||
Name string `valid:"required"`
|
|
||||||
URL string `valid:"required"`
|
|
||||||
PublicURL string `valid:"-"`
|
|
||||||
TLS bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type postEndpointsResponse struct {
|
|
||||||
ID int `json:"Id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// handleGetEndpoint handles GET requests on /endpoints/:id
|
// handleGetEndpoint handles GET requests on /endpoints/:id
|
||||||
func (handler *EndpointHandler) handleGetEndpoint(w http.ResponseWriter, r *http.Request) {
|
func (handler *EndpointHandler) handleGetEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
|
@ -219,11 +233,6 @@ func (handler *EndpointHandler) handlePutEndpointAccess(w http.ResponseWriter, r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type putEndpointAccessRequest struct {
|
|
||||||
AuthorizedUsers []int `valid:"-"`
|
|
||||||
AuthorizedTeams []int `valid:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// handlePutEndpoint handles PUT requests on /endpoints/:id
|
// handlePutEndpoint handles PUT requests on /endpoints/:id
|
||||||
func (handler *EndpointHandler) handlePutEndpoint(w http.ResponseWriter, r *http.Request) {
|
func (handler *EndpointHandler) handlePutEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
if !handler.authorizeEndpointManagement {
|
if !handler.authorizeEndpointManagement {
|
||||||
|
@ -307,13 +316,6 @@ func (handler *EndpointHandler) handlePutEndpoint(w http.ResponseWriter, r *http
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type putEndpointsRequest struct {
|
|
||||||
Name string `valid:"-"`
|
|
||||||
URL string `valid:"-"`
|
|
||||||
PublicURL string `valid:"-"`
|
|
||||||
TLS bool `valid:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// handleDeleteEndpoint handles DELETE requests on /endpoints/:id
|
// handleDeleteEndpoint handles DELETE requests on /endpoints/:id
|
||||||
func (handler *EndpointHandler) handleDeleteEndpoint(w http.ResponseWriter, r *http.Request) {
|
func (handler *EndpointHandler) handleDeleteEndpoint(w http.ResponseWriter, r *http.Request) {
|
||||||
if !handler.authorizeEndpointManagement {
|
if !handler.authorizeEndpointManagement {
|
||||||
|
|
|
@ -36,48 +36,48 @@ const (
|
||||||
ErrInvalidRequestFormat = portainer.Error("Invalid request data format")
|
ErrInvalidRequestFormat = portainer.Error("Invalid request data format")
|
||||||
// ErrInvalidQueryFormat defines an error raised when the data sent in the query or the URL is invalid
|
// ErrInvalidQueryFormat defines an error raised when the data sent in the query or the URL is invalid
|
||||||
ErrInvalidQueryFormat = portainer.Error("Invalid query format")
|
ErrInvalidQueryFormat = portainer.Error("Invalid query format")
|
||||||
// ErrEmptyResponseBody defines an error raised when portainer excepts to parse the body of a HTTP response and there is nothing to parse
|
|
||||||
// ErrEmptyResponseBody = portainer.Error("Empty response body")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ServeHTTP delegates a request to the appropriate subhandler.
|
// ServeHTTP delegates a request to the appropriate subhandler.
|
||||||
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
if strings.HasPrefix(r.URL.Path, "/api/auth") {
|
|
||||||
|
switch {
|
||||||
|
case strings.HasPrefix(r.URL.Path, "/api/auth"):
|
||||||
http.StripPrefix("/api", h.AuthHandler).ServeHTTP(w, r)
|
http.StripPrefix("/api", h.AuthHandler).ServeHTTP(w, r)
|
||||||
} else if strings.HasPrefix(r.URL.Path, "/api/users") {
|
case strings.HasPrefix(r.URL.Path, "/api/dockerhub"):
|
||||||
http.StripPrefix("/api", h.UserHandler).ServeHTTP(w, r)
|
http.StripPrefix("/api", h.DockerHubHandler).ServeHTTP(w, r)
|
||||||
} else if strings.HasPrefix(r.URL.Path, "/api/teams") {
|
case strings.HasPrefix(r.URL.Path, "/api/endpoints"):
|
||||||
http.StripPrefix("/api", h.TeamHandler).ServeHTTP(w, r)
|
|
||||||
} else if strings.HasPrefix(r.URL.Path, "/api/team_memberships") {
|
|
||||||
http.StripPrefix("/api", h.TeamMembershipHandler).ServeHTTP(w, r)
|
|
||||||
} else if strings.HasPrefix(r.URL.Path, "/api/endpoints") {
|
|
||||||
if strings.Contains(r.URL.Path, "/docker") {
|
if strings.Contains(r.URL.Path, "/docker") {
|
||||||
http.StripPrefix("/api/endpoints", h.DockerHandler).ServeHTTP(w, r)
|
http.StripPrefix("/api/endpoints", h.DockerHandler).ServeHTTP(w, r)
|
||||||
} else {
|
} else {
|
||||||
http.StripPrefix("/api", h.EndpointHandler).ServeHTTP(w, r)
|
http.StripPrefix("/api", h.EndpointHandler).ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
} else if strings.HasPrefix(r.URL.Path, "/api/registries") {
|
case strings.HasPrefix(r.URL.Path, "/api/registries"):
|
||||||
http.StripPrefix("/api", h.RegistryHandler).ServeHTTP(w, r)
|
http.StripPrefix("/api", h.RegistryHandler).ServeHTTP(w, r)
|
||||||
} else if strings.HasPrefix(r.URL.Path, "/api/dockerhub") {
|
case strings.HasPrefix(r.URL.Path, "/api/resource_controls"):
|
||||||
http.StripPrefix("/api", h.DockerHubHandler).ServeHTTP(w, r)
|
|
||||||
} else if strings.HasPrefix(r.URL.Path, "/api/resource_controls") {
|
|
||||||
http.StripPrefix("/api", h.ResourceHandler).ServeHTTP(w, r)
|
http.StripPrefix("/api", h.ResourceHandler).ServeHTTP(w, r)
|
||||||
} else if strings.HasPrefix(r.URL.Path, "/api/settings") {
|
case strings.HasPrefix(r.URL.Path, "/api/settings"):
|
||||||
http.StripPrefix("/api", h.SettingsHandler).ServeHTTP(w, r)
|
http.StripPrefix("/api", h.SettingsHandler).ServeHTTP(w, r)
|
||||||
} else if strings.HasPrefix(r.URL.Path, "/api/status") {
|
case strings.HasPrefix(r.URL.Path, "/api/status"):
|
||||||
http.StripPrefix("/api", h.StatusHandler).ServeHTTP(w, r)
|
http.StripPrefix("/api", h.StatusHandler).ServeHTTP(w, r)
|
||||||
} else if strings.HasPrefix(r.URL.Path, "/api/templates") {
|
case strings.HasPrefix(r.URL.Path, "/api/templates"):
|
||||||
http.StripPrefix("/api", h.TemplatesHandler).ServeHTTP(w, r)
|
http.StripPrefix("/api", h.TemplatesHandler).ServeHTTP(w, r)
|
||||||
} else if strings.HasPrefix(r.URL.Path, "/api/upload") {
|
case strings.HasPrefix(r.URL.Path, "/api/upload"):
|
||||||
http.StripPrefix("/api", h.UploadHandler).ServeHTTP(w, r)
|
http.StripPrefix("/api", h.UploadHandler).ServeHTTP(w, r)
|
||||||
} else if strings.HasPrefix(r.URL.Path, "/api/websocket") {
|
case strings.HasPrefix(r.URL.Path, "/api/users"):
|
||||||
|
http.StripPrefix("/api", h.UserHandler).ServeHTTP(w, r)
|
||||||
|
case strings.HasPrefix(r.URL.Path, "/api/teams"):
|
||||||
|
http.StripPrefix("/api", h.TeamHandler).ServeHTTP(w, r)
|
||||||
|
case strings.HasPrefix(r.URL.Path, "/api/team_memberships"):
|
||||||
|
http.StripPrefix("/api", h.TeamMembershipHandler).ServeHTTP(w, r)
|
||||||
|
case strings.HasPrefix(r.URL.Path, "/api/websocket"):
|
||||||
http.StripPrefix("/api", h.WebSocketHandler).ServeHTTP(w, r)
|
http.StripPrefix("/api", h.WebSocketHandler).ServeHTTP(w, r)
|
||||||
} else if strings.HasPrefix(r.URL.Path, "/") {
|
case strings.HasPrefix(r.URL.Path, "/"):
|
||||||
h.FileHandler.ServeHTTP(w, r)
|
h.FileHandler.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// encodeJSON encodes v to w in JSON format. Error() is called if encoding fails.
|
// encodeJSON encodes v to w in JSON format. WriteErrorResponse() is called if encoding fails.
|
||||||
func encodeJSON(w http.ResponseWriter, v interface{}, logger *log.Logger) {
|
func encodeJSON(w http.ResponseWriter, v interface{}, logger *log.Logger) {
|
||||||
if err := json.NewEncoder(w).Encode(v); err != nil {
|
if err := json.NewEncoder(w).Encode(v); err != nil {
|
||||||
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, logger)
|
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, logger)
|
||||||
|
|
|
@ -44,6 +44,33 @@ func NewRegistryHandler(bouncer *security.RequestBouncer) *RegistryHandler {
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
postRegistriesRequest struct {
|
||||||
|
Name string `valid:"required"`
|
||||||
|
URL string `valid:"required"`
|
||||||
|
Authentication bool `valid:""`
|
||||||
|
Username string `valid:""`
|
||||||
|
Password string `valid:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
postRegistriesResponse struct {
|
||||||
|
ID int `json:"Id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
putRegistryAccessRequest struct {
|
||||||
|
AuthorizedUsers []int `valid:"-"`
|
||||||
|
AuthorizedTeams []int `valid:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
putRegistriesRequest struct {
|
||||||
|
Name string `valid:"required"`
|
||||||
|
URL string `valid:"required"`
|
||||||
|
Authentication bool `valid:""`
|
||||||
|
Username string `valid:""`
|
||||||
|
Password string `valid:""`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// handleGetRegistries handles GET requests on /registries
|
// handleGetRegistries handles GET requests on /registries
|
||||||
func (handler *RegistryHandler) handleGetRegistries(w http.ResponseWriter, r *http.Request) {
|
func (handler *RegistryHandler) handleGetRegistries(w http.ResponseWriter, r *http.Request) {
|
||||||
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
||||||
|
@ -112,18 +139,6 @@ func (handler *RegistryHandler) handlePostRegistries(w http.ResponseWriter, r *h
|
||||||
encodeJSON(w, &postRegistriesResponse{ID: int(registry.ID)}, handler.Logger)
|
encodeJSON(w, &postRegistriesResponse{ID: int(registry.ID)}, handler.Logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
type postRegistriesRequest struct {
|
|
||||||
Name string `valid:"required"`
|
|
||||||
URL string `valid:"required"`
|
|
||||||
Authentication bool `valid:""`
|
|
||||||
Username string `valid:""`
|
|
||||||
Password string `valid:""`
|
|
||||||
}
|
|
||||||
|
|
||||||
type postRegistriesResponse struct {
|
|
||||||
ID int `json:"Id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// handleGetRegistry handles GET requests on /registries/:id
|
// handleGetRegistry handles GET requests on /registries/:id
|
||||||
func (handler *RegistryHandler) handleGetRegistry(w http.ResponseWriter, r *http.Request) {
|
func (handler *RegistryHandler) handleGetRegistry(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
|
@ -202,11 +217,6 @@ func (handler *RegistryHandler) handlePutRegistryAccess(w http.ResponseWriter, r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type putRegistryAccessRequest struct {
|
|
||||||
AuthorizedUsers []int `valid:"-"`
|
|
||||||
AuthorizedTeams []int `valid:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// handlePutRegistry handles PUT requests on /registries/:id
|
// handlePutRegistry handles PUT requests on /registries/:id
|
||||||
func (handler *RegistryHandler) handlePutRegistry(w http.ResponseWriter, r *http.Request) {
|
func (handler *RegistryHandler) handlePutRegistry(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
|
@ -276,14 +286,6 @@ func (handler *RegistryHandler) handlePutRegistry(w http.ResponseWriter, r *http
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type putRegistriesRequest struct {
|
|
||||||
Name string `valid:"required"`
|
|
||||||
URL string `valid:"required"`
|
|
||||||
Authentication bool `valid:""`
|
|
||||||
Username string `valid:""`
|
|
||||||
Password string `valid:""`
|
|
||||||
}
|
|
||||||
|
|
||||||
// handleDeleteRegistry handles DELETE requests on /registries/:id
|
// handleDeleteRegistry handles DELETE requests on /registries/:id
|
||||||
func (handler *RegistryHandler) handleDeleteRegistry(w http.ResponseWriter, r *http.Request) {
|
func (handler *RegistryHandler) handleDeleteRegistry(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
|
|
|
@ -39,6 +39,23 @@ func NewResourceHandler(bouncer *security.RequestBouncer) *ResourceHandler {
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
postResourcesRequest struct {
|
||||||
|
ResourceID string `valid:"required"`
|
||||||
|
Type string `valid:"required"`
|
||||||
|
AdministratorsOnly bool `valid:"-"`
|
||||||
|
Users []int `valid:"-"`
|
||||||
|
Teams []int `valid:"-"`
|
||||||
|
SubResourceIDs []string `valid:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
putResourcesRequest struct {
|
||||||
|
AdministratorsOnly bool `valid:"-"`
|
||||||
|
Users []int `valid:"-"`
|
||||||
|
Teams []int `valid:"-"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// handlePostResources handles POST requests on /resources
|
// handlePostResources handles POST requests on /resources
|
||||||
func (handler *ResourceHandler) handlePostResources(w http.ResponseWriter, r *http.Request) {
|
func (handler *ResourceHandler) handlePostResources(w http.ResponseWriter, r *http.Request) {
|
||||||
var req postResourcesRequest
|
var req postResourcesRequest
|
||||||
|
@ -121,22 +138,13 @@ func (handler *ResourceHandler) handlePostResources(w http.ResponseWriter, r *ht
|
||||||
|
|
||||||
err = handler.ResourceControlService.CreateResourceControl(&resourceControl)
|
err = handler.ResourceControlService.CreateResourceControl(&resourceControl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httperror.WriteErrorResponse(w, ErrInvalidRequestFormat, http.StatusBadRequest, handler.Logger)
|
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type postResourcesRequest struct {
|
|
||||||
ResourceID string `valid:"required"`
|
|
||||||
Type string `valid:"required"`
|
|
||||||
AdministratorsOnly bool `valid:"-"`
|
|
||||||
Users []int `valid:"-"`
|
|
||||||
Teams []int `valid:"-"`
|
|
||||||
SubResourceIDs []string `valid:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// handlePutResources handles PUT requests on /resources/:id
|
// handlePutResources handles PUT requests on /resources/:id
|
||||||
func (handler *ResourceHandler) handlePutResources(w http.ResponseWriter, r *http.Request) {
|
func (handler *ResourceHandler) handlePutResources(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
|
@ -210,12 +218,6 @@ func (handler *ResourceHandler) handlePutResources(w http.ResponseWriter, r *htt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type putResourcesRequest struct {
|
|
||||||
AdministratorsOnly bool `valid:"-"`
|
|
||||||
Users []int `valid:"-"`
|
|
||||||
Teams []int `valid:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// handleDeleteResources handles DELETE requests on /resources/:id
|
// handleDeleteResources handles DELETE requests on /resources/:id
|
||||||
func (handler *ResourceHandler) handleDeleteResources(w http.ResponseWriter, r *http.Request) {
|
func (handler *ResourceHandler) handleDeleteResources(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
|
|
|
@ -43,6 +43,27 @@ func NewSettingsHandler(bouncer *security.RequestBouncer) *SettingsHandler {
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
publicSettingsResponse struct {
|
||||||
|
LogoURL string `json:"LogoURL"`
|
||||||
|
DisplayExternalContributors bool `json:"DisplayExternalContributors"`
|
||||||
|
AuthenticationMethod portainer.AuthenticationMethod `json:"AuthenticationMethod"`
|
||||||
|
}
|
||||||
|
|
||||||
|
putSettingsRequest struct {
|
||||||
|
TemplatesURL string `valid:"required"`
|
||||||
|
LogoURL string `valid:""`
|
||||||
|
BlackListedLabels []portainer.Pair `valid:""`
|
||||||
|
DisplayExternalContributors bool `valid:""`
|
||||||
|
AuthenticationMethod int `valid:"required"`
|
||||||
|
LDAPSettings portainer.LDAPSettings `valid:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
putSettingsLDAPCheckRequest struct {
|
||||||
|
LDAPSettings portainer.LDAPSettings `valid:""`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// handleGetSettings handles GET requests on /settings
|
// handleGetSettings handles GET requests on /settings
|
||||||
func (handler *SettingsHandler) handleGetSettings(w http.ResponseWriter, r *http.Request) {
|
func (handler *SettingsHandler) handleGetSettings(w http.ResponseWriter, r *http.Request) {
|
||||||
settings, err := handler.SettingsService.Settings()
|
settings, err := handler.SettingsService.Settings()
|
||||||
|
@ -73,12 +94,6 @@ func (handler *SettingsHandler) handleGetPublicSettings(w http.ResponseWriter, r
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type publicSettingsResponse struct {
|
|
||||||
LogoURL string `json:"LogoURL"`
|
|
||||||
DisplayExternalContributors bool `json:"DisplayExternalContributors"`
|
|
||||||
AuthenticationMethod portainer.AuthenticationMethod `json:"AuthenticationMethod"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// handlePutSettings handles PUT requests on /settings
|
// handlePutSettings handles PUT requests on /settings
|
||||||
func (handler *SettingsHandler) handlePutSettings(w http.ResponseWriter, r *http.Request) {
|
func (handler *SettingsHandler) handlePutSettings(w http.ResponseWriter, r *http.Request) {
|
||||||
var req putSettingsRequest
|
var req putSettingsRequest
|
||||||
|
@ -127,15 +142,6 @@ func (handler *SettingsHandler) handlePutSettings(w http.ResponseWriter, r *http
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type putSettingsRequest struct {
|
|
||||||
TemplatesURL string `valid:"required"`
|
|
||||||
LogoURL string `valid:""`
|
|
||||||
BlackListedLabels []portainer.Pair `valid:""`
|
|
||||||
DisplayExternalContributors bool `valid:""`
|
|
||||||
AuthenticationMethod int `valid:"required"`
|
|
||||||
LDAPSettings portainer.LDAPSettings `valid:""`
|
|
||||||
}
|
|
||||||
|
|
||||||
// handlePutSettingsLDAPCheck handles PUT requests on /settings/ldap/check
|
// handlePutSettingsLDAPCheck handles PUT requests on /settings/ldap/check
|
||||||
func (handler *SettingsHandler) handlePutSettingsLDAPCheck(w http.ResponseWriter, r *http.Request) {
|
func (handler *SettingsHandler) handlePutSettingsLDAPCheck(w http.ResponseWriter, r *http.Request) {
|
||||||
var req putSettingsLDAPCheckRequest
|
var req putSettingsLDAPCheckRequest
|
||||||
|
@ -161,7 +167,3 @@ func (handler *SettingsHandler) handlePutSettingsLDAPCheck(w http.ResponseWriter
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type putSettingsLDAPCheckRequest struct {
|
|
||||||
LDAPSettings portainer.LDAPSettings `valid:""`
|
|
||||||
}
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ func NewTeamHandler(bouncer *security.RequestBouncer) *TeamHandler {
|
||||||
h.Handle("/teams",
|
h.Handle("/teams",
|
||||||
bouncer.AdministratorAccess(http.HandlerFunc(h.handlePostTeams))).Methods(http.MethodPost)
|
bouncer.AdministratorAccess(http.HandlerFunc(h.handlePostTeams))).Methods(http.MethodPost)
|
||||||
h.Handle("/teams",
|
h.Handle("/teams",
|
||||||
bouncer.AuthenticatedAccess(http.HandlerFunc(h.handleGetTeams))).Methods(http.MethodGet)
|
bouncer.RestrictedAccess(http.HandlerFunc(h.handleGetTeams))).Methods(http.MethodGet)
|
||||||
h.Handle("/teams/{id}",
|
h.Handle("/teams/{id}",
|
||||||
bouncer.RestrictedAccess(http.HandlerFunc(h.handleGetTeam))).Methods(http.MethodGet)
|
bouncer.RestrictedAccess(http.HandlerFunc(h.handleGetTeam))).Methods(http.MethodGet)
|
||||||
h.Handle("/teams/{id}",
|
h.Handle("/teams/{id}",
|
||||||
|
@ -47,6 +47,20 @@ func NewTeamHandler(bouncer *security.RequestBouncer) *TeamHandler {
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
postTeamsRequest struct {
|
||||||
|
Name string `valid:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
postTeamsResponse struct {
|
||||||
|
ID int `json:"Id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
putTeamRequest struct {
|
||||||
|
Name string `valid:"-"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// handlePostTeams handles POST requests on /teams
|
// handlePostTeams handles POST requests on /teams
|
||||||
func (handler *TeamHandler) handlePostTeams(w http.ResponseWriter, r *http.Request) {
|
func (handler *TeamHandler) handlePostTeams(w http.ResponseWriter, r *http.Request) {
|
||||||
var req postTeamsRequest
|
var req postTeamsRequest
|
||||||
|
@ -84,23 +98,23 @@ func (handler *TeamHandler) handlePostTeams(w http.ResponseWriter, r *http.Reque
|
||||||
encodeJSON(w, &postTeamsResponse{ID: int(team.ID)}, handler.Logger)
|
encodeJSON(w, &postTeamsResponse{ID: int(team.ID)}, handler.Logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
type postTeamsResponse struct {
|
|
||||||
ID int `json:"Id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type postTeamsRequest struct {
|
|
||||||
Name string `valid:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// handleGetTeams handles GET requests on /teams
|
// handleGetTeams handles GET requests on /teams
|
||||||
func (handler *TeamHandler) handleGetTeams(w http.ResponseWriter, r *http.Request) {
|
func (handler *TeamHandler) handleGetTeams(w http.ResponseWriter, r *http.Request) {
|
||||||
|
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
||||||
|
if err != nil {
|
||||||
|
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
teams, err := handler.TeamService.Teams()
|
teams, err := handler.TeamService.Teams()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger)
|
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
encodeJSON(w, teams, handler.Logger)
|
filteredTeams := security.FilterUserTeams(teams, securityContext)
|
||||||
|
|
||||||
|
encodeJSON(w, filteredTeams, handler.Logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleGetTeam handles GET requests on /teams/:id
|
// handleGetTeam handles GET requests on /teams/:id
|
||||||
|
@ -181,10 +195,6 @@ func (handler *TeamHandler) handlePutTeam(w http.ResponseWriter, r *http.Request
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type putTeamRequest struct {
|
|
||||||
Name string `valid:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// handleDeleteTeam handles DELETE requests on /teams/:id
|
// handleDeleteTeam handles DELETE requests on /teams/:id
|
||||||
func (handler *TeamHandler) handleDeleteTeam(w http.ResponseWriter, r *http.Request) {
|
func (handler *TeamHandler) handleDeleteTeam(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
|
|
|
@ -42,6 +42,24 @@ func NewTeamMembershipHandler(bouncer *security.RequestBouncer) *TeamMembershipH
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
postTeamMembershipsRequest struct {
|
||||||
|
UserID int `valid:"required"`
|
||||||
|
TeamID int `valid:"required"`
|
||||||
|
Role int `valid:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
postTeamMembershipsResponse struct {
|
||||||
|
ID int `json:"Id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
putTeamMembershipRequest struct {
|
||||||
|
UserID int `valid:"required"`
|
||||||
|
TeamID int `valid:"required"`
|
||||||
|
Role int `valid:"required"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// handlePostTeamMemberships handles POST requests on /team_memberships
|
// handlePostTeamMemberships handles POST requests on /team_memberships
|
||||||
func (handler *TeamMembershipHandler) handlePostTeamMemberships(w http.ResponseWriter, r *http.Request) {
|
func (handler *TeamMembershipHandler) handlePostTeamMemberships(w http.ResponseWriter, r *http.Request) {
|
||||||
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
||||||
|
@ -100,16 +118,6 @@ func (handler *TeamMembershipHandler) handlePostTeamMemberships(w http.ResponseW
|
||||||
encodeJSON(w, &postTeamMembershipsResponse{ID: int(membership.ID)}, handler.Logger)
|
encodeJSON(w, &postTeamMembershipsResponse{ID: int(membership.ID)}, handler.Logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
type postTeamMembershipsResponse struct {
|
|
||||||
ID int `json:"Id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type postTeamMembershipsRequest struct {
|
|
||||||
UserID int `valid:"required"`
|
|
||||||
TeamID int `valid:"required"`
|
|
||||||
Role int `valid:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// handleGetTeamsMemberships handles GET requests on /team_memberships
|
// handleGetTeamsMemberships handles GET requests on /team_memberships
|
||||||
func (handler *TeamMembershipHandler) handleGetTeamsMemberships(w http.ResponseWriter, r *http.Request) {
|
func (handler *TeamMembershipHandler) handleGetTeamsMemberships(w http.ResponseWriter, r *http.Request) {
|
||||||
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
||||||
|
@ -195,12 +203,6 @@ func (handler *TeamMembershipHandler) handlePutTeamMembership(w http.ResponseWri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type putTeamMembershipRequest struct {
|
|
||||||
UserID int `valid:"required"`
|
|
||||||
TeamID int `valid:"required"`
|
|
||||||
Role int `valid:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// handleDeleteTeamMembership handles DELETE requests on /team_memberships/:id
|
// handleDeleteTeamMembership handles DELETE requests on /team_memberships/:id
|
||||||
func (handler *TeamMembershipHandler) handleDeleteTeamMembership(w http.ResponseWriter, r *http.Request) {
|
func (handler *TeamMembershipHandler) handleDeleteTeamMembership(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
|
|
|
@ -30,17 +30,12 @@ func NewTemplatesHandler(bouncer *security.RequestBouncer) *TemplatesHandler {
|
||||||
Logger: log.New(os.Stderr, "", log.LstdFlags),
|
Logger: log.New(os.Stderr, "", log.LstdFlags),
|
||||||
}
|
}
|
||||||
h.Handle("/templates",
|
h.Handle("/templates",
|
||||||
bouncer.AuthenticatedAccess(http.HandlerFunc(h.handleGetTemplates)))
|
bouncer.AuthenticatedAccess(http.HandlerFunc(h.handleGetTemplates))).Methods(http.MethodGet)
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleGetTemplates handles GET requests on /templates?key=<key>
|
// handleGetTemplates handles GET requests on /templates?key=<key>
|
||||||
func (handler *TemplatesHandler) handleGetTemplates(w http.ResponseWriter, r *http.Request) {
|
func (handler *TemplatesHandler) handleGetTemplates(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method != http.MethodGet {
|
|
||||||
httperror.WriteMethodNotAllowedResponse(w, []string{http.MethodGet})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
key := r.FormValue("key")
|
key := r.FormValue("key")
|
||||||
if key == "" {
|
if key == "" {
|
||||||
httperror.WriteErrorResponse(w, ErrInvalidQueryFormat, http.StatusBadRequest, handler.Logger)
|
httperror.WriteErrorResponse(w, ErrInvalidQueryFormat, http.StatusBadRequest, handler.Logger)
|
||||||
|
|
|
@ -26,17 +26,12 @@ func NewUploadHandler(bouncer *security.RequestBouncer) *UploadHandler {
|
||||||
Logger: log.New(os.Stderr, "", log.LstdFlags),
|
Logger: log.New(os.Stderr, "", log.LstdFlags),
|
||||||
}
|
}
|
||||||
h.Handle("/upload/tls/{certificate:(?:ca|cert|key)}",
|
h.Handle("/upload/tls/{certificate:(?:ca|cert|key)}",
|
||||||
bouncer.AuthenticatedAccess(http.HandlerFunc(h.handlePostUploadTLS)))
|
bouncer.AdministratorAccess(http.HandlerFunc(h.handlePostUploadTLS))).Methods(http.MethodPost)
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
// handlePostUploadTLS handles POST requests on /upload/tls/{certificate:(?:ca|cert|key)}?folder=folder
|
// handlePostUploadTLS handles POST requests on /upload/tls/{certificate:(?:ca|cert|key)}?folder=folder
|
||||||
func (handler *UploadHandler) handlePostUploadTLS(w http.ResponseWriter, r *http.Request) {
|
func (handler *UploadHandler) handlePostUploadTLS(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method != http.MethodPost {
|
|
||||||
httperror.WriteMethodNotAllowedResponse(w, []string{http.MethodPost})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
certificate := vars["certificate"]
|
certificate := vars["certificate"]
|
||||||
|
|
||||||
|
|
|
@ -47,18 +47,45 @@ func NewUserHandler(bouncer *security.RequestBouncer) *UserHandler {
|
||||||
bouncer.AdministratorAccess(http.HandlerFunc(h.handleDeleteUser))).Methods(http.MethodDelete)
|
bouncer.AdministratorAccess(http.HandlerFunc(h.handleDeleteUser))).Methods(http.MethodDelete)
|
||||||
h.Handle("/users/{id}/memberships",
|
h.Handle("/users/{id}/memberships",
|
||||||
bouncer.AuthenticatedAccess(http.HandlerFunc(h.handleGetMemberships))).Methods(http.MethodGet)
|
bouncer.AuthenticatedAccess(http.HandlerFunc(h.handleGetMemberships))).Methods(http.MethodGet)
|
||||||
h.Handle("/users/{id}/teams",
|
|
||||||
bouncer.RestrictedAccess(http.HandlerFunc(h.handleGetTeams))).Methods(http.MethodGet)
|
|
||||||
h.Handle("/users/{id}/passwd",
|
h.Handle("/users/{id}/passwd",
|
||||||
bouncer.AuthenticatedAccess(http.HandlerFunc(h.handlePostUserPasswd)))
|
bouncer.AuthenticatedAccess(http.HandlerFunc(h.handlePostUserPasswd))).Methods(http.MethodPost)
|
||||||
h.Handle("/users/admin/check",
|
h.Handle("/users/admin/check",
|
||||||
bouncer.PublicAccess(http.HandlerFunc(h.handleGetAdminCheck)))
|
bouncer.PublicAccess(http.HandlerFunc(h.handleGetAdminCheck))).Methods(http.MethodGet)
|
||||||
h.Handle("/users/admin/init",
|
h.Handle("/users/admin/init",
|
||||||
bouncer.PublicAccess(http.HandlerFunc(h.handlePostAdminInit)))
|
bouncer.PublicAccess(http.HandlerFunc(h.handlePostAdminInit))).Methods(http.MethodPost)
|
||||||
|
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
postUsersRequest struct {
|
||||||
|
Username string `valid:"required"`
|
||||||
|
Password string `valid:""`
|
||||||
|
Role int `valid:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
postUsersResponse struct {
|
||||||
|
ID int `json:"Id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
postUserPasswdRequest struct {
|
||||||
|
Password string `valid:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
postUserPasswdResponse struct {
|
||||||
|
Valid bool `json:"valid"`
|
||||||
|
}
|
||||||
|
|
||||||
|
putUserRequest struct {
|
||||||
|
Password string `valid:"-"`
|
||||||
|
Role int `valid:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
postAdminInitRequest struct {
|
||||||
|
Password string `valid:"required"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// handlePostUsers handles POST requests on /users
|
// handlePostUsers handles POST requests on /users
|
||||||
func (handler *UserHandler) handlePostUsers(w http.ResponseWriter, r *http.Request) {
|
func (handler *UserHandler) handlePostUsers(w http.ResponseWriter, r *http.Request) {
|
||||||
var req postUsersRequest
|
var req postUsersRequest
|
||||||
|
@ -139,16 +166,6 @@ func (handler *UserHandler) handlePostUsers(w http.ResponseWriter, r *http.Reque
|
||||||
encodeJSON(w, &postUsersResponse{ID: int(user.ID)}, handler.Logger)
|
encodeJSON(w, &postUsersResponse{ID: int(user.ID)}, handler.Logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
type postUsersResponse struct {
|
|
||||||
ID int `json:"Id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type postUsersRequest struct {
|
|
||||||
Username string `valid:"required"`
|
|
||||||
Password string `valid:""`
|
|
||||||
Role int `valid:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// handleGetUsers handles GET requests on /users
|
// handleGetUsers handles GET requests on /users
|
||||||
func (handler *UserHandler) handleGetUsers(w http.ResponseWriter, r *http.Request) {
|
func (handler *UserHandler) handleGetUsers(w http.ResponseWriter, r *http.Request) {
|
||||||
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
||||||
|
@ -174,11 +191,6 @@ func (handler *UserHandler) handleGetUsers(w http.ResponseWriter, r *http.Reques
|
||||||
|
|
||||||
// handlePostUserPasswd handles POST requests on /users/:id/passwd
|
// handlePostUserPasswd handles POST requests on /users/:id/passwd
|
||||||
func (handler *UserHandler) handlePostUserPasswd(w http.ResponseWriter, r *http.Request) {
|
func (handler *UserHandler) handlePostUserPasswd(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method != http.MethodPost {
|
|
||||||
httperror.WriteMethodNotAllowedResponse(w, []string{http.MethodPost})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
id := vars["id"]
|
id := vars["id"]
|
||||||
|
|
||||||
|
@ -220,14 +232,6 @@ func (handler *UserHandler) handlePostUserPasswd(w http.ResponseWriter, r *http.
|
||||||
encodeJSON(w, &postUserPasswdResponse{Valid: valid}, handler.Logger)
|
encodeJSON(w, &postUserPasswdResponse{Valid: valid}, handler.Logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
type postUserPasswdRequest struct {
|
|
||||||
Password string `valid:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type postUserPasswdResponse struct {
|
|
||||||
Valid bool `json:"valid"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// handleGetUser handles GET requests on /users/:id
|
// handleGetUser handles GET requests on /users/:id
|
||||||
func (handler *UserHandler) handleGetUser(w http.ResponseWriter, r *http.Request) {
|
func (handler *UserHandler) handleGetUser(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
|
@ -327,18 +331,8 @@ func (handler *UserHandler) handlePutUser(w http.ResponseWriter, r *http.Request
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type putUserRequest struct {
|
// handleGetAdminCheck handles GET requests on /users/admin/check
|
||||||
Password string `valid:"-"`
|
|
||||||
Role int `valid:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// handlePostAdminInit handles GET requests on /users/admin/check
|
|
||||||
func (handler *UserHandler) handleGetAdminCheck(w http.ResponseWriter, r *http.Request) {
|
func (handler *UserHandler) handleGetAdminCheck(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method != http.MethodGet {
|
|
||||||
httperror.WriteMethodNotAllowedResponse(w, []string{http.MethodGet})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
users, err := handler.UserService.UsersByRole(portainer.AdministratorRole)
|
users, err := handler.UserService.UsersByRole(portainer.AdministratorRole)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger)
|
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger)
|
||||||
|
@ -352,11 +346,6 @@ func (handler *UserHandler) handleGetAdminCheck(w http.ResponseWriter, r *http.R
|
||||||
|
|
||||||
// handlePostAdminInit handles POST requests on /users/admin/init
|
// handlePostAdminInit handles POST requests on /users/admin/init
|
||||||
func (handler *UserHandler) handlePostAdminInit(w http.ResponseWriter, r *http.Request) {
|
func (handler *UserHandler) handlePostAdminInit(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method != http.MethodPost {
|
|
||||||
httperror.WriteMethodNotAllowedResponse(w, []string{http.MethodPost})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var req postAdminInitRequest
|
var req postAdminInitRequest
|
||||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||||
httperror.WriteErrorResponse(w, ErrInvalidJSON, http.StatusBadRequest, handler.Logger)
|
httperror.WriteErrorResponse(w, ErrInvalidJSON, http.StatusBadRequest, handler.Logger)
|
||||||
|
@ -391,15 +380,11 @@ func (handler *UserHandler) handlePostAdminInit(w http.ResponseWriter, r *http.R
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if user != nil {
|
if user != nil {
|
||||||
httperror.WriteErrorResponse(w, portainer.ErrAdminAlreadyInitialized, http.StatusForbidden, handler.Logger)
|
httperror.WriteErrorResponse(w, portainer.ErrAdminAlreadyInitialized, http.StatusConflict, handler.Logger)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type postAdminInitRequest struct {
|
|
||||||
Password string `valid:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// handleDeleteUser handles DELETE requests on /users/:id
|
// handleDeleteUser handles DELETE requests on /users/:id
|
||||||
func (handler *UserHandler) handleDeleteUser(w http.ResponseWriter, r *http.Request) {
|
func (handler *UserHandler) handleDeleteUser(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
|
@ -464,37 +449,3 @@ func (handler *UserHandler) handleGetMemberships(w http.ResponseWriter, r *http.
|
||||||
|
|
||||||
encodeJSON(w, memberships, handler.Logger)
|
encodeJSON(w, memberships, handler.Logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleGetTeams handles GET requests on /users/:id/teams
|
|
||||||
func (handler *UserHandler) handleGetTeams(w http.ResponseWriter, r *http.Request) {
|
|
||||||
vars := mux.Vars(r)
|
|
||||||
id := vars["id"]
|
|
||||||
|
|
||||||
uid, err := strconv.Atoi(id)
|
|
||||||
if err != nil {
|
|
||||||
httperror.WriteErrorResponse(w, err, http.StatusBadRequest, handler.Logger)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
userID := portainer.UserID(uid)
|
|
||||||
|
|
||||||
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
|
||||||
if err != nil {
|
|
||||||
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !security.AuthorizedUserManagement(userID, securityContext) {
|
|
||||||
httperror.WriteErrorResponse(w, portainer.ErrResourceAccessDenied, http.StatusForbidden, handler.Logger)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
teams, err := handler.TeamService.Teams()
|
|
||||||
if err != nil {
|
|
||||||
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
filteredTeams := security.FilterUserTeams(teams, securityContext)
|
|
||||||
|
|
||||||
encodeJSON(w, filteredTeams, handler.Logger)
|
|
||||||
}
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ func (bouncer *RequestBouncer) AuthenticatedAccess(h http.Handler) http.Handler
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
// RestrictedAccess defines defines a security check for restricted endpoints.
|
// RestrictedAccess defines a security check for restricted endpoints.
|
||||||
// Authentication is required to access these endpoints.
|
// Authentication is required to access these endpoints.
|
||||||
// The request context will be enhanced with a RestrictedRequestContext object
|
// The request context will be enhanced with a RestrictedRequestContext object
|
||||||
// that might be used later to authorize/filter access to resources.
|
// that might be used later to authorize/filter access to resources.
|
||||||
|
|
2471
api/swagger.yaml
Normal file
2471
api/swagger.yaml
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
||||||
angular.module('portainer')
|
angular.module('portainer')
|
||||||
.controller('porAccessControlFormController', ['$q', 'UserService', 'Notifications', 'Authentication', 'ResourceControlService',
|
.controller('porAccessControlFormController', ['$q', 'UserService', 'TeamService', 'Notifications', 'Authentication', 'ResourceControlService',
|
||||||
function ($q, UserService, Notifications, Authentication, ResourceControlService) {
|
function ($q, UserService, TeamService, Notifications, Authentication, ResourceControlService) {
|
||||||
var ctrl = this;
|
var ctrl = this;
|
||||||
|
|
||||||
ctrl.availableTeams = [];
|
ctrl.availableTeams = [];
|
||||||
|
@ -42,7 +42,7 @@ function ($q, UserService, Notifications, Authentication, ResourceControlService
|
||||||
}
|
}
|
||||||
|
|
||||||
$q.all({
|
$q.all({
|
||||||
availableTeams: UserService.userTeams(userDetails.ID),
|
availableTeams: TeamService.teams(),
|
||||||
availableUsers: isAdmin ? UserService.users(false) : []
|
availableUsers: isAdmin ? UserService.users(false) : []
|
||||||
})
|
})
|
||||||
.then(function success(data) {
|
.then(function success(data) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
angular.module('portainer')
|
angular.module('portainer')
|
||||||
.controller('porAccessControlPanelController', ['$q', '$state', 'UserService', 'ResourceControlService', 'Notifications', 'Authentication', 'ModalService', 'FormValidator',
|
.controller('porAccessControlPanelController', ['$q', '$state', 'UserService', 'TeamService', 'ResourceControlService', 'Notifications', 'Authentication', 'ModalService', 'FormValidator',
|
||||||
function ($q, $state, UserService, ResourceControlService, Notifications, Authentication, ModalService, FormValidator) {
|
function ($q, $state, UserService, TeamService, ResourceControlService, Notifications, Authentication, ModalService, FormValidator) {
|
||||||
|
|
||||||
var ctrl = this;
|
var ctrl = this;
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ function ($q, $state, UserService, ResourceControlService, Notifications, Authen
|
||||||
|
|
||||||
return $q.all({
|
return $q.all({
|
||||||
availableUsers: isAdmin ? UserService.users(false) : [],
|
availableUsers: isAdmin ? UserService.users(false) : [],
|
||||||
availableTeams: isAdmin || data.isPartOfRestrictedUsers ? UserService.userTeams(userId) : []
|
availableTeams: isAdmin || data.isPartOfRestrictedUsers ? TeamService.teams() : []
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(function success(data) {
|
.then(function success(data) {
|
||||||
|
|
|
@ -8,7 +8,6 @@ angular.module('portainer.rest')
|
||||||
update: { method: 'PUT', params: { id: '@id' } },
|
update: { method: 'PUT', params: { id: '@id' } },
|
||||||
remove: { method: 'DELETE', params: { id: '@id'} },
|
remove: { method: 'DELETE', params: { id: '@id'} },
|
||||||
queryMemberships: { method: 'GET', isArray: true, params: { id: '@id', entity: 'memberships' } },
|
queryMemberships: { method: 'GET', isArray: true, params: { id: '@id', entity: 'memberships' } },
|
||||||
queryTeams: { method: 'GET', isArray: true, params: { id: '@id', entity: 'teams' } },
|
|
||||||
// RPCs should be moved to a specific endpoint
|
// RPCs should be moved to a specific endpoint
|
||||||
checkPassword: { method: 'POST', params: { id: '@id', entity: 'passwd' } },
|
checkPassword: { method: 'POST', params: { id: '@id', entity: 'passwd' } },
|
||||||
checkAdminUser: { method: 'GET', params: { id: 'admin', entity: 'check' }, isArray: true },
|
checkAdminUser: { method: 'GET', params: { id: 'admin', entity: 'check' }, isArray: true },
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
angular.module('portainer.services')
|
angular.module('portainer.services')
|
||||||
.factory('UserService', ['$q', 'Users', 'UserHelper', 'TeamMembershipService', function UserServiceFactory($q, Users, UserHelper, TeamMembershipService) {
|
.factory('UserService', ['$q', 'Users', 'UserHelper', 'TeamService', 'TeamMembershipService', function UserServiceFactory($q, Users, UserHelper, TeamService, TeamMembershipService) {
|
||||||
'use strict';
|
'use strict';
|
||||||
var service = {};
|
var service = {};
|
||||||
|
|
||||||
|
@ -110,28 +110,11 @@ angular.module('portainer.services')
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
};
|
};
|
||||||
|
|
||||||
service.userTeams = function(id) {
|
|
||||||
var deferred = $q.defer();
|
|
||||||
|
|
||||||
Users.queryTeams({id: id}).$promise
|
|
||||||
.then(function success(data) {
|
|
||||||
var teams = data.map(function (item) {
|
|
||||||
return new TeamViewModel(item);
|
|
||||||
});
|
|
||||||
deferred.resolve(teams);
|
|
||||||
})
|
|
||||||
.catch(function error(err) {
|
|
||||||
deferred.reject({ msg: 'Unable to retrieve user teams', err: err });
|
|
||||||
});
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
};
|
|
||||||
|
|
||||||
service.userLeadingTeams = function(id) {
|
service.userLeadingTeams = function(id) {
|
||||||
var deferred = $q.defer();
|
var deferred = $q.defer();
|
||||||
|
|
||||||
$q.all({
|
$q.all({
|
||||||
teams: service.userTeams(id),
|
teams: TeamService.teams(),
|
||||||
memberships: service.userMemberships(id)
|
memberships: service.userMemberships(id)
|
||||||
})
|
})
|
||||||
.then(function success(data) {
|
.then(function success(data) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue