Files
netmaker/logic/errors.go
T
Abhishek Kondur c3c3ed1fb8 NM-254: add bulk delete apis, rm old acl code (#3937)
* NM-254: add bulk delete apis for users, hosts, nodes and optimise postgres connection settings

* NM-254: rm debug logs

* NM-254: add bulk delete apis, remove old acl code

* NM-254: rm unused flag

* NM-254: fix bulk delete bugs, add security and performance improvements

- Fix host delete notifying peers before confirming deletion from DB
- Fix self-delete vulnerability in bulk user delete
- Fix DissasociateNodeFromHost failing when host.Nodes is empty
- Fix AssociateNodeToHost/DissasociateNodeFromHost stale read race
- Hoist GetAllExtClients outside loop in bulk user delete/status
- Move initializeUUID outside master-pod guard for HA correctness

* NM-254: return 202 Accepted for async bulk APIs, fix relay allowedIPs and host association error handling

- Change all bulk endpoints (hosts, nodes, users, ext clients) from
  200 OK to 202 Accepted to correctly signal async processing
- Add ReturnAcceptedResponse helper in logic/errors.go
- Fix GetAllowedIpsForRelayed returning empty allowedIPs slice,
  restoring relay connectivity
- Make AssociateNodeToHost and DissasociateNodeFromHost return an
  error when the host DB re-fetch fails instead of silently using
  stale data
- Add bulk-apis.md documenting all five bulk endpoints

* NM-254: rm coredns container

* NM-254: add bulk apis for node,extclient status, add activity logs to bulk apis

* NM-254: add bulk api for connection toggle

* NM-254: add network check

* Update controllers/hosts.go

Co-authored-by: tenki-reviewer[bot] <262613592+tenki-reviewer[bot]@users.noreply.github.com>

* NM-254: optimise bulk extclient deletion

---------

Co-authored-by: tenki-reviewer[bot] <262613592+tenki-reviewer[bot]@users.noreply.github.com>
2026-03-26 10:15:07 +05:30

103 lines
3.4 KiB
Go

package logic
import (
"encoding/json"
"net/http"
"github.com/gravitl/netmaker/models"
"golang.org/x/exp/slog"
)
type ApiErrorType string
const (
Internal ApiErrorType = "internal"
BadReq ApiErrorType = "badrequest"
NotFound ApiErrorType = "notfound"
UnAuthorized ApiErrorType = "unauthorized"
Forbidden ApiErrorType = "forbidden"
)
// FormatError - takes ErrorResponse and uses correct code
func FormatError(err error, errType ApiErrorType) models.ErrorResponse {
var status = http.StatusInternalServerError
switch errType {
case Internal:
status = http.StatusInternalServerError
case BadReq:
status = http.StatusBadRequest
case NotFound:
status = http.StatusNotFound
case UnAuthorized:
status = http.StatusUnauthorized
case Forbidden:
status = http.StatusForbidden
default:
status = http.StatusInternalServerError
}
var response = models.ErrorResponse{
Message: err.Error(),
Code: status,
}
return response
}
// ReturnSuccessResponse - processes message and adds header
func ReturnSuccessResponse(response http.ResponseWriter, request *http.Request, message string) {
var httpResponse models.SuccessResponse
httpResponse.Code = http.StatusOK
httpResponse.Message = message
response.Header().Set("Content-Type", "application/json")
response.WriteHeader(http.StatusOK)
json.NewEncoder(response).Encode(httpResponse)
}
// ReturnAcceptedResponse - returns 202 Accepted for async operations
func ReturnAcceptedResponse(response http.ResponseWriter, request *http.Request, message string) {
var httpResponse models.SuccessResponse
httpResponse.Code = http.StatusAccepted
httpResponse.Message = message
response.Header().Set("Content-Type", "application/json")
response.WriteHeader(http.StatusAccepted)
json.NewEncoder(response).Encode(httpResponse)
}
// ReturnSuccessResponseWithJson - processes message and adds header
func ReturnSuccessResponseWithJson(response http.ResponseWriter, request *http.Request, res interface{}, message string) {
var httpResponse models.SuccessResponse
httpResponse.Code = http.StatusOK
httpResponse.Response = res
httpResponse.Message = message
response.Header().Set("Content-Type", "application/json")
response.WriteHeader(http.StatusOK)
json.NewEncoder(response).Encode(httpResponse)
}
// ReturnErrorResponse - processes error and adds header
func ReturnErrorResponse(response http.ResponseWriter, request *http.Request, errorMessage models.ErrorResponse) {
httpResponse := &models.ErrorResponse{Code: errorMessage.Code, Message: errorMessage.Message}
jsonResponse, err := json.Marshal(httpResponse)
if err != nil {
panic(err)
}
slog.Debug("processed request error", "err", errorMessage.Message)
response.Header().Set("Content-Type", "application/json")
response.WriteHeader(errorMessage.Code)
response.Write(jsonResponse)
}
// ReturnErrorResponseWithJson - processes error with body and adds header
func ReturnErrorResponseWithJson(response http.ResponseWriter, request *http.Request, msg interface{}, errorMessage models.ErrorResponse) {
httpResponse := &models.ErrorResponse{Code: errorMessage.Code, Message: errorMessage.Message, Response: msg}
jsonResponse, err := json.Marshal(httpResponse)
if err != nil {
panic(err)
}
slog.Debug("processed request error", "err", errorMessage.Message)
response.Header().Set("Content-Type", "application/json")
response.WriteHeader(errorMessage.Code)
response.Write(jsonResponse)
}