mirror of
https://github.com/m1k1o/neko.git
synced 2024-07-24 14:40:50 +12:00
refactor HTTP error.
This commit is contained in:
parent
d46c5d9d30
commit
4fa11e6a2a
@ -2,7 +2,6 @@ package members
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
@ -18,13 +17,13 @@ type MemberBulkUpdatePayload struct {
|
|||||||
func (h *MembersHandler) membersBulkUpdate(w http.ResponseWriter, r *http.Request) {
|
func (h *MembersHandler) membersBulkUpdate(w http.ResponseWriter, r *http.Request) {
|
||||||
bytes, err := io.ReadAll(r.Body)
|
bytes, err := io.ReadAll(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpBadRequest(w).WithInternalErr(err).Msg("unable to read post body")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
header := &MemberBulkUpdatePayload{}
|
header := &MemberBulkUpdatePayload{}
|
||||||
if err := json.Unmarshal(bytes, &header); err != nil {
|
if err := json.Unmarshal(bytes, &header); err != nil {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpBadRequest(w).WithInternalErr(err).Msg("unable to unmarshal payload")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +31,7 @@ func (h *MembersHandler) membersBulkUpdate(w http.ResponseWriter, r *http.Reques
|
|||||||
// TODO: Bulk select?
|
// TODO: Bulk select?
|
||||||
profile, err := h.members.Select(memberId)
|
profile, err := h.members.Select(memberId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpInternalServerError(w, fmt.Sprintf("member %s: %v", memberId, err))
|
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to select member profile").Msgf("failed to update member %s", memberId)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,12 +40,12 @@ func (h *MembersHandler) membersBulkUpdate(w http.ResponseWriter, r *http.Reques
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := json.Unmarshal(bytes, &body); err != nil {
|
if err := json.Unmarshal(bytes, &body); err != nil {
|
||||||
utils.HttpInternalServerError(w, fmt.Sprintf("member %s: %v", memberId, err))
|
utils.HttpBadRequest(w).WithInternalErr(err).Msgf("unable to unmarshal payload for member %s", memberId)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := h.members.UpdateProfile(memberId, body.Profile); err != nil {
|
if err := h.members.UpdateProfile(memberId, body.Profile); err != nil {
|
||||||
utils.HttpInternalServerError(w, fmt.Sprintf("member %s: %v", memberId, err))
|
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to update member profile").Msgf("failed to update member %s", memberId)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ func (h *MembersHandler) membersList(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
entries, err := h.members.SelectAll(limit, offset)
|
entries, err := h.members.SelectAll(limit, offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpInternalServerError(w, err).Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,21 +72,21 @@ func (h *MembersHandler) membersCreate(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if data.Username == "" {
|
if data.Username == "" {
|
||||||
utils.HttpBadRequest(w, "username cannot be empty")
|
utils.HttpBadRequest(w).Msg("username cannot be empty")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if data.Password == "" {
|
if data.Password == "" {
|
||||||
utils.HttpBadRequest(w, "password cannot be empty")
|
utils.HttpBadRequest(w).Msg("password cannot be empty")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := h.members.Insert(data.Username, data.Password, data.Profile)
|
id, err := h.members.Insert(data.Username, data.Password, data.Profile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, types.ErrMemberAlreadyExists) {
|
if errors.Is(err, types.ErrMemberAlreadyExists) {
|
||||||
utils.HttpUnprocessableEntity(w, err)
|
utils.HttpUnprocessableEntity(w).Msg("member already exists")
|
||||||
} else {
|
} else {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpInternalServerError(w, err).Send()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -113,7 +113,7 @@ func (h *MembersHandler) membersUpdateProfile(w http.ResponseWriter, r *http.Req
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := h.members.UpdateProfile(member.ID, profile); err != nil {
|
if err := h.members.UpdateProfile(member.ID, profile); err != nil {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpInternalServerError(w, err).Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,7 +129,7 @@ func (h *MembersHandler) membersUpdatePassword(w http.ResponseWriter, r *http.Re
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := h.members.UpdatePassword(member.ID, data.Password); err != nil {
|
if err := h.members.UpdatePassword(member.ID, data.Password); err != nil {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpInternalServerError(w, err).Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +140,7 @@ func (h *MembersHandler) membersDelete(w http.ResponseWriter, r *http.Request) {
|
|||||||
member := GetMember(r)
|
member := GetMember(r)
|
||||||
|
|
||||||
if err := h.members.Delete(member.ID); err != nil {
|
if err := h.members.Delete(member.ID); err != nil {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpInternalServerError(w, err).Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,9 +71,9 @@ func (h *MembersHandler) ExtractMember(next http.Handler) http.Handler {
|
|||||||
profile, err := h.members.Select(memberId)
|
profile, err := h.members.Select(memberId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, types.ErrMemberDoesNotExist) {
|
if errors.Is(err, types.ErrMemberDoesNotExist) {
|
||||||
utils.HttpNotFound(w, err)
|
utils.HttpNotFound(w).Msg("member not found")
|
||||||
} else {
|
} else {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpInternalServerError(w, err).Send()
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -28,18 +28,18 @@ func (h *RoomHandler) boradcastStart(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if data.URL == "" {
|
if data.URL == "" {
|
||||||
utils.HttpBadRequest(w, "missing broadcast URL")
|
utils.HttpBadRequest(w).Msg("missing broadcast URL")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
broadcast := h.capture.Broadcast()
|
broadcast := h.capture.Broadcast()
|
||||||
if broadcast.Started() {
|
if broadcast.Started() {
|
||||||
utils.HttpUnprocessableEntity(w, "server is already broadcasting")
|
utils.HttpUnprocessableEntity(w).Msg("server is already broadcasting")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := broadcast.Start(data.URL); err != nil {
|
if err := broadcast.Start(data.URL); err != nil {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpInternalServerError(w, err).Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ func (h *RoomHandler) boradcastStart(w http.ResponseWriter, r *http.Request) {
|
|||||||
func (h *RoomHandler) boradcastStop(w http.ResponseWriter, r *http.Request) {
|
func (h *RoomHandler) boradcastStop(w http.ResponseWriter, r *http.Request) {
|
||||||
broadcast := h.capture.Broadcast()
|
broadcast := h.capture.Broadcast()
|
||||||
if !broadcast.Started() {
|
if !broadcast.Started() {
|
||||||
utils.HttpUnprocessableEntity(w, "server is not broadcasting")
|
utils.HttpUnprocessableEntity(w).Msg("server is not broadcasting")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ type ClipboardPayload struct {
|
|||||||
func (h *RoomHandler) clipboardGetText(w http.ResponseWriter, r *http.Request) {
|
func (h *RoomHandler) clipboardGetText(w http.ResponseWriter, r *http.Request) {
|
||||||
data, err := h.desktop.ClipboardGetText()
|
data, err := h.desktop.ClipboardGetText()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpInternalServerError(w, err).Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ func (h *RoomHandler) clipboardSetText(w http.ResponseWriter, r *http.Request) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpInternalServerError(w, err).Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ func (h *RoomHandler) clipboardSetText(w http.ResponseWriter, r *http.Request) {
|
|||||||
func (h *RoomHandler) clipboardGetImage(w http.ResponseWriter, r *http.Request) {
|
func (h *RoomHandler) clipboardGetImage(w http.ResponseWriter, r *http.Request) {
|
||||||
bytes, err := h.desktop.ClipboardGetBinary("image/png")
|
bytes, err := h.desktop.ClipboardGetBinary("image/png")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpInternalServerError(w, err).Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +64,7 @@ func (h *RoomHandler) clipboardGetImage(w http.ResponseWriter, r *http.Request)
|
|||||||
func (h *RoomHandler) clipboardSetImage(w http.ResponseWriter, r *http.Request) {
|
func (h *RoomHandler) clipboardSetImage(w http.ResponseWriter, r *http.Request) {
|
||||||
err := r.ParseMultipartForm(MAX_UPLOAD_SIZE)
|
err := r.ParseMultipartForm(MAX_UPLOAD_SIZE)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpBadRequest(w, "failed to parse multipart form")
|
utils.HttpBadRequest(w).WithInternalErr(err).Msg("failed to parse multipart form")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ func (h *RoomHandler) clipboardSetImage(w http.ResponseWriter, r *http.Request)
|
|||||||
|
|
||||||
file, header, err := r.FormFile("file")
|
file, header, err := r.FormFile("file")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpBadRequest(w, "no file received")
|
utils.HttpBadRequest(w).WithInternalErr(err).Msg("no file received")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,20 +81,20 @@ func (h *RoomHandler) clipboardSetImage(w http.ResponseWriter, r *http.Request)
|
|||||||
|
|
||||||
mime := header.Header.Get("Content-Type")
|
mime := header.Header.Get("Content-Type")
|
||||||
if !strings.HasPrefix(mime, "image/") {
|
if !strings.HasPrefix(mime, "image/") {
|
||||||
utils.HttpBadRequest(w, "file must be image")
|
utils.HttpBadRequest(w).Msg("file must be image")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer := new(bytes.Buffer)
|
buffer := new(bytes.Buffer)
|
||||||
_, err = buffer.ReadFrom(file)
|
_, err = buffer.ReadFrom(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to read from uploaded file").Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = h.desktop.ClipboardSetBinary("image/png", buffer.Bytes())
|
err = h.desktop.ClipboardSetBinary("image/png", buffer.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpInternalServerError(w, err).WithInternalMsg("unable set image to clipboard").Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ func (h *RoomHandler) clipboardSetImage(w http.ResponseWriter, r *http.Request)
|
|||||||
func (h *RoomHandler) clipboardGetTargets(w http.ResponseWriter, r *http.Request) {
|
func (h *RoomHandler) clipboardGetTargets(w http.ResponseWriter, r *http.Request) {
|
||||||
targets, err := h.desktop.ClipboardGetTargets()
|
targets, err := h.desktop.ClipboardGetTargets()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpInternalServerError(w, err).Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ func (h *RoomHandler) controlStatus(w http.ResponseWriter, r *http.Request) {
|
|||||||
func (h *RoomHandler) controlRequest(w http.ResponseWriter, r *http.Request) {
|
func (h *RoomHandler) controlRequest(w http.ResponseWriter, r *http.Request) {
|
||||||
host := h.sessions.GetHost()
|
host := h.sessions.GetHost()
|
||||||
if host != nil {
|
if host != nil {
|
||||||
utils.HttpUnprocessableEntity(w, "there is already a host")
|
utils.HttpUnprocessableEntity(w).Msg("there is already a host")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ func (h *RoomHandler) controlRequest(w http.ResponseWriter, r *http.Request) {
|
|||||||
func (h *RoomHandler) controlRelease(w http.ResponseWriter, r *http.Request) {
|
func (h *RoomHandler) controlRelease(w http.ResponseWriter, r *http.Request) {
|
||||||
session := auth.GetSession(r)
|
session := auth.GetSession(r)
|
||||||
if !session.IsHost() {
|
if !session.IsHost() {
|
||||||
utils.HttpUnprocessableEntity(w, "session is not the host")
|
utils.HttpUnprocessableEntity(w).Msg("session is not the host")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,12 +71,12 @@ func (h *RoomHandler) controlGive(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
target, ok := h.sessions.Get(sessionId)
|
target, ok := h.sessions.Get(sessionId)
|
||||||
if !ok {
|
if !ok {
|
||||||
utils.HttpNotFound(w, "target session was not found")
|
utils.HttpNotFound(w).Msg("target session was not found")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !target.Profile().CanHost {
|
if !target.Profile().CanHost {
|
||||||
utils.HttpBadRequest(w, "target session is not allowed to host")
|
utils.HttpBadRequest(w).Msg("target session is not allowed to host")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ func (h *RoomHandler) uploadMiddleware(next http.Handler) http.Handler {
|
|||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
session := auth.GetSession(r)
|
session := auth.GetSession(r)
|
||||||
if !session.IsHost() && (!session.Profile().CanHost || !h.sessions.ImplicitHosting()) {
|
if !session.IsHost() && (!session.Profile().CanHost || !h.sessions.ImplicitHosting()) {
|
||||||
utils.HttpForbidden(w, "without implicit hosting, only host can upload files")
|
utils.HttpForbidden(w).Msg("without implicit hosting, only host can upload files")
|
||||||
} else {
|
} else {
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ func (h *RoomHandler) keyboardMapSet(w http.ResponseWriter, r *http.Request) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpInternalServerError(w, "unable to change keyboard map")
|
utils.HttpInternalServerError(w, err).Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ func (h *RoomHandler) keyboardMapGet(w http.ResponseWriter, r *http.Request) {
|
|||||||
data, err := h.desktop.GetKeyboardMap()
|
data, err := h.desktop.GetKeyboardMap()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpInternalServerError(w, "unable to get keyboard map")
|
utils.HttpInternalServerError(w, err).Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ func (h *RoomHandler) screenConfiguration(w http.ResponseWriter, r *http.Request
|
|||||||
size := h.desktop.GetScreenSize()
|
size := h.desktop.GetScreenSize()
|
||||||
|
|
||||||
if size == nil {
|
if size == nil {
|
||||||
utils.HttpInternalServerError(w, "unable to get screen configuration")
|
utils.HttpInternalServerError(w, nil).WithInternalMsg("unable to get screen configuration").Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ func (h *RoomHandler) screenConfigurationChange(w http.ResponseWriter, r *http.R
|
|||||||
Height: data.Height,
|
Height: data.Height,
|
||||||
Rate: data.Rate,
|
Rate: data.Rate,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
utils.HttpUnprocessableEntity(w, err)
|
utils.HttpUnprocessableEntity(w).WithInternalErr(err).Msg("cannot set screen size")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ func (h *RoomHandler) screenShotGet(w http.ResponseWriter, r *http.Request) {
|
|||||||
img := h.desktop.GetScreenshotImage()
|
img := h.desktop.GetScreenshotImage()
|
||||||
bytes, err := utils.CreateJPGImage(img, quality)
|
bytes, err := utils.CreateJPGImage(img, quality)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpInternalServerError(w, err).Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,13 +96,13 @@ func (h *RoomHandler) screenShotGet(w http.ResponseWriter, r *http.Request) {
|
|||||||
func (h *RoomHandler) screenCastGet(w http.ResponseWriter, r *http.Request) {
|
func (h *RoomHandler) screenCastGet(w http.ResponseWriter, r *http.Request) {
|
||||||
screencast := h.capture.Screencast()
|
screencast := h.capture.Screencast()
|
||||||
if !screencast.Enabled() {
|
if !screencast.Enabled() {
|
||||||
utils.HttpBadRequest(w, "screencast pipeline is not enabled")
|
utils.HttpBadRequest(w).Msg("screencast pipeline is not enabled")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes, err := screencast.Image()
|
bytes, err := screencast.Image()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpInternalServerError(w, err).Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,13 +10,15 @@ import (
|
|||||||
"demodesk/neko/internal/utils"
|
"demodesk/neko/internal/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO: Extract file uploading to custom utility.
|
||||||
|
|
||||||
// maximum upload size of 32 MB
|
// maximum upload size of 32 MB
|
||||||
const maxUploadSize = 32 << 20
|
const maxUploadSize = 32 << 20
|
||||||
|
|
||||||
func (h *RoomHandler) uploadDrop(w http.ResponseWriter, r *http.Request) {
|
func (h *RoomHandler) uploadDrop(w http.ResponseWriter, r *http.Request) {
|
||||||
err := r.ParseMultipartForm(maxUploadSize)
|
err := r.ParseMultipartForm(maxUploadSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpBadRequest(w, "failed to parse multipart form")
|
utils.HttpBadRequest(w).WithInternalErr(err).Msg("failed to parse multipart form")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,25 +27,25 @@ func (h *RoomHandler) uploadDrop(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
X, err := strconv.Atoi(r.FormValue("x"))
|
X, err := strconv.Atoi(r.FormValue("x"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpBadRequest(w, "no X coordinate received")
|
utils.HttpBadRequest(w).WithInternalErr(err).Msg("no X coordinate received")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Y, err := strconv.Atoi(r.FormValue("y"))
|
Y, err := strconv.Atoi(r.FormValue("y"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpBadRequest(w, "no Y coordinate received")
|
utils.HttpBadRequest(w).WithInternalErr(err).Msg("no Y coordinate received")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
req_files := r.MultipartForm.File["files"]
|
req_files := r.MultipartForm.File["files"]
|
||||||
if len(req_files) == 0 {
|
if len(req_files) == 0 {
|
||||||
utils.HttpBadRequest(w, "no files received")
|
utils.HttpBadRequest(w).Msg("no files received")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dir, err := os.MkdirTemp("", "neko-drop-*")
|
dir, err := os.MkdirTemp("", "neko-drop-*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to create temporary directory").Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +55,7 @@ func (h *RoomHandler) uploadDrop(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
srcFile, err := req_file.Open()
|
srcFile, err := req_file.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to open uploaded file").Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +63,7 @@ func (h *RoomHandler) uploadDrop(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
dstFile, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
dstFile, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to open destination file").Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +71,7 @@ func (h *RoomHandler) uploadDrop(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
_, err = io.Copy(dstFile, srcFile)
|
_, err = io.Copy(dstFile, srcFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to copy uploaded file to destination file").Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +79,7 @@ func (h *RoomHandler) uploadDrop(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !h.desktop.DropFiles(X, Y, files) {
|
if !h.desktop.DropFiles(X, Y, files) {
|
||||||
utils.HttpInternalServerError(w, "unable to drop files")
|
utils.HttpInternalServerError(w, nil).WithInternalMsg("unable to drop files").Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +89,7 @@ func (h *RoomHandler) uploadDrop(w http.ResponseWriter, r *http.Request) {
|
|||||||
func (h *RoomHandler) uploadDialogPost(w http.ResponseWriter, r *http.Request) {
|
func (h *RoomHandler) uploadDialogPost(w http.ResponseWriter, r *http.Request) {
|
||||||
err := r.ParseMultipartForm(maxUploadSize)
|
err := r.ParseMultipartForm(maxUploadSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpBadRequest(w, "failed to parse multipart form")
|
utils.HttpBadRequest(w).WithInternalErr(err).Msg("failed to parse multipart form")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,19 +97,19 @@ func (h *RoomHandler) uploadDialogPost(w http.ResponseWriter, r *http.Request) {
|
|||||||
defer r.MultipartForm.RemoveAll()
|
defer r.MultipartForm.RemoveAll()
|
||||||
|
|
||||||
if !h.desktop.IsFileChooserDialogOpened() {
|
if !h.desktop.IsFileChooserDialogOpened() {
|
||||||
utils.HttpBadRequest(w, "open file chooser dialog first")
|
utils.HttpUnprocessableEntity(w).Msg("file chooser dialog is not open")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
req_files := r.MultipartForm.File["files"]
|
req_files := r.MultipartForm.File["files"]
|
||||||
if len(req_files) == 0 {
|
if len(req_files) == 0 {
|
||||||
utils.HttpBadRequest(w, "no files received")
|
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to copy uploaded file to destination file").Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dir, err := os.MkdirTemp("", "neko-dialog-*")
|
dir, err := os.MkdirTemp("", "neko-dialog-*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to create temporary directory").Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +118,7 @@ func (h *RoomHandler) uploadDialogPost(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
srcFile, err := req_file.Open()
|
srcFile, err := req_file.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to open uploaded file").Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +126,7 @@ func (h *RoomHandler) uploadDialogPost(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
dstFile, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
dstFile, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to open destination file").Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,13 +134,13 @@ func (h *RoomHandler) uploadDialogPost(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
_, err = io.Copy(dstFile, srcFile)
|
_, err = io.Copy(dstFile, srcFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpInternalServerError(w, err)
|
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to copy uploaded file to destination file").Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := h.desktop.HandleFileChooserDialog(dir); err != nil {
|
if err := h.desktop.HandleFileChooserDialog(dir); err != nil {
|
||||||
utils.HttpInternalServerError(w, "unable to handle file chooser dialog")
|
utils.HttpInternalServerError(w, err).WithInternalMsg("unable to handle file chooser dialog").Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +149,7 @@ func (h *RoomHandler) uploadDialogPost(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
func (h *RoomHandler) uploadDialogClose(w http.ResponseWriter, r *http.Request) {
|
func (h *RoomHandler) uploadDialogClose(w http.ResponseWriter, r *http.Request) {
|
||||||
if !h.desktop.IsFileChooserDialogOpened() {
|
if !h.desktop.IsFileChooserDialogOpened() {
|
||||||
utils.HttpBadRequest(w, "file chooser dialog is not open")
|
utils.HttpUnprocessableEntity(w).Msg("file chooser dialog is not open")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,9 +76,9 @@ func (api *ApiManagerCtx) Authenticate(next http.Handler) http.Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if errors.Is(err, types.ErrSessionLoginDisabled) {
|
if errors.Is(err, types.ErrSessionLoginDisabled) {
|
||||||
utils.HttpForbidden(w, err)
|
utils.HttpForbidden(w).Msg("login is disabled for this session")
|
||||||
} else {
|
} else {
|
||||||
utils.HttpUnauthorized(w, err)
|
utils.HttpUnauthorized(w).WithInternalErr(err).Send()
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -28,7 +28,7 @@ func (api *ApiManagerCtx) Login(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
session, token, err := api.members.Login(data.Username, data.Password)
|
session, token, err := api.members.Login(data.Username, data.Password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpUnauthorized(w, err)
|
utils.HttpUnauthorized(w).WithInternalErr(err).Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ func (api *ApiManagerCtx) Logout(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
err := api.members.Logout(session.ID())
|
err := api.members.Logout(session.ID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.HttpUnauthorized(w, err)
|
utils.HttpUnauthorized(w).WithInternalErr(err).Send()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ func AdminsOnly(next http.Handler) http.Handler {
|
|||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
session := GetSession(r)
|
session := GetSession(r)
|
||||||
if !session.Profile().IsAdmin {
|
if !session.Profile().IsAdmin {
|
||||||
utils.HttpForbidden(w)
|
utils.HttpForbidden(w).Msg("session is not admin")
|
||||||
} else {
|
} else {
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
@ -36,7 +36,7 @@ func HostsOnly(next http.Handler) http.Handler {
|
|||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
session := GetSession(r)
|
session := GetSession(r)
|
||||||
if !session.IsHost() {
|
if !session.IsHost() {
|
||||||
utils.HttpForbidden(w, "only host can do this")
|
utils.HttpForbidden(w).Msg("session is not host")
|
||||||
} else {
|
} else {
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
@ -47,7 +47,7 @@ func CanWatchOnly(next http.Handler) http.Handler {
|
|||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
session := GetSession(r)
|
session := GetSession(r)
|
||||||
if !session.Profile().CanWatch {
|
if !session.Profile().CanWatch {
|
||||||
utils.HttpForbidden(w)
|
utils.HttpForbidden(w).Msg("session cannot watch")
|
||||||
} else {
|
} else {
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
@ -58,7 +58,7 @@ func CanHostOnly(next http.Handler) http.Handler {
|
|||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
session := GetSession(r)
|
session := GetSession(r)
|
||||||
if !session.Profile().CanHost {
|
if !session.Profile().CanHost {
|
||||||
utils.HttpForbidden(w)
|
utils.HttpForbidden(w).Msg("session cannot host")
|
||||||
} else {
|
} else {
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ func CanAccessClipboardOnly(next http.Handler) http.Handler {
|
|||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
session := GetSession(r)
|
session := GetSession(r)
|
||||||
if !session.Profile().CanAccessClipboard {
|
if !session.Profile().CanAccessClipboard {
|
||||||
utils.HttpForbidden(w)
|
utils.HttpForbidden(w).Msg("session cannot access clipboard")
|
||||||
} else {
|
} else {
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ import (
|
|||||||
|
|
||||||
"demodesk/neko/internal/config"
|
"demodesk/neko/internal/config"
|
||||||
"demodesk/neko/internal/types"
|
"demodesk/neko/internal/types"
|
||||||
"demodesk/neko/internal/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type HttpManagerCtx struct {
|
type HttpManagerCtx struct {
|
||||||
@ -55,13 +54,13 @@ func New(WebSocketManager types.WebSocketManager, ApiManager types.ApiManager, c
|
|||||||
if _, err := os.Stat(config.Static + r.URL.Path); !os.IsNotExist(err) {
|
if _, err := os.Stat(config.Static + r.URL.Path); !os.IsNotExist(err) {
|
||||||
fs.ServeHTTP(w, r)
|
fs.ServeHTTP(w, r)
|
||||||
} else {
|
} else {
|
||||||
utils.HttpNotFound(w)
|
http.NotFound(w, r)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
router.NotFound(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
router.NotFound(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
utils.HttpNotFound(w)
|
http.NotFound(w, r)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
return &HttpManagerCtx{
|
return &HttpManagerCtx{
|
||||||
|
@ -9,16 +9,12 @@ import (
|
|||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ErrResponse struct {
|
|
||||||
Message string `json:"message"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func HttpJsonRequest(w http.ResponseWriter, r *http.Request, res interface{}) bool {
|
func HttpJsonRequest(w http.ResponseWriter, r *http.Request, res interface{}) bool {
|
||||||
if err := json.NewDecoder(r.Body).Decode(res); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(res); err != nil {
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
HttpBadRequest(w, "no data provided")
|
HttpBadRequest(w).WithInternalErr(err).Msg("no data provided")
|
||||||
} else {
|
} else {
|
||||||
HttpBadRequest(w, err)
|
HttpBadRequest(w).WithInternalErr(err).Msg("unable to parse provided data")
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
@ -27,21 +23,15 @@ func HttpJsonRequest(w http.ResponseWriter, r *http.Request, res interface{}) bo
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func HttpJsonResponse(w http.ResponseWriter, status int, res interface{}) {
|
func HttpJsonResponse(w http.ResponseWriter, code int, res interface{}) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
w.WriteHeader(status)
|
w.WriteHeader(code)
|
||||||
|
|
||||||
if err := json.NewEncoder(w).Encode(res); err != nil {
|
if err := json.NewEncoder(w).Encode(res); err != nil {
|
||||||
log.Err(err).Str("module", "http").Msg("sending http json response failed")
|
log.Err(err).Str("module", "http").Msg("sending http json response failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func HttpError(w http.ResponseWriter, status int, res interface{}) {
|
|
||||||
HttpJsonResponse(w, status, &ErrResponse{
|
|
||||||
Message: fmt.Sprint(res),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func HttpSuccess(w http.ResponseWriter, res ...interface{}) {
|
func HttpSuccess(w http.ResponseWriter, res ...interface{}) {
|
||||||
if len(res) == 0 {
|
if len(res) == 0 {
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
@ -50,34 +40,108 @@ func HttpSuccess(w http.ResponseWriter, res ...interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func HttpBadRequest(w http.ResponseWriter, res ...interface{}) {
|
// HTTPError is an error with a message and an HTTP status code.
|
||||||
defHttpError(w, http.StatusBadRequest, "bad request", res...)
|
type HTTPError struct {
|
||||||
|
Code int `json:"code"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
|
||||||
|
InternalErr error `json:"-"`
|
||||||
|
InternalMsg string `json:"-"`
|
||||||
|
|
||||||
|
w http.ResponseWriter `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func HttpUnauthorized(w http.ResponseWriter, res ...interface{}) {
|
func (e *HTTPError) Error() string {
|
||||||
defHttpError(w, http.StatusUnauthorized, "invalid or missing access token", res...)
|
if e.InternalMsg != "" {
|
||||||
|
return e.InternalMsg
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%d: %s", e.Code, e.Message)
|
||||||
}
|
}
|
||||||
|
|
||||||
func HttpForbidden(w http.ResponseWriter, res ...interface{}) {
|
func (e *HTTPError) Cause() error {
|
||||||
defHttpError(w, http.StatusForbidden, "access token does not have the required scope", res...)
|
if e.InternalErr != nil {
|
||||||
|
return e.InternalErr
|
||||||
|
}
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
func HttpNotFound(w http.ResponseWriter, res ...interface{}) {
|
// WithInternalErr adds internal error information to the error
|
||||||
defHttpError(w, http.StatusNotFound, "resource not found", res...)
|
func (e *HTTPError) WithInternalErr(err error) *HTTPError {
|
||||||
|
e.InternalErr = err
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
func HttpUnprocessableEntity(w http.ResponseWriter, res ...interface{}) {
|
// WithInternalMsg adds internal message information to the error
|
||||||
defHttpError(w, http.StatusUnprocessableEntity, "unprocessable entity", res...)
|
func (e *HTTPError) WithInternalMsg(msg string) *HTTPError {
|
||||||
|
e.InternalMsg = msg
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
func HttpInternalServerError(w http.ResponseWriter, res ...interface{}) {
|
// WithInternalMsg adds internal formated message information to the error
|
||||||
defHttpError(w, http.StatusInternalServerError, "internal server error", res...)
|
func (e *HTTPError) WithInternalMsgf(fmtStr string, args ...interface{}) *HTTPError {
|
||||||
|
e.InternalMsg = fmt.Sprintf(fmtStr, args...)
|
||||||
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
func defHttpError(w http.ResponseWriter, status int, text string, res ...interface{}) {
|
// Sends error with custom formated message
|
||||||
if len(res) == 0 {
|
func (e *HTTPError) Msgf(fmtSt string, args ...interface{}) {
|
||||||
HttpError(w, status, text)
|
e.Message = fmt.Sprintf(fmtSt, args...)
|
||||||
} else {
|
e.Send()
|
||||||
HttpError(w, status, res[0])
|
}
|
||||||
|
|
||||||
|
// Sends error with custom message
|
||||||
|
func (e *HTTPError) Msg(str string) {
|
||||||
|
e.Message = str
|
||||||
|
e.Send()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sends error with default status text
|
||||||
|
func (e *HTTPError) Send() {
|
||||||
|
if e.Message == "" {
|
||||||
|
e.Message = http.StatusText(e.Code)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger := log.Error().
|
||||||
|
Err(e.InternalErr).
|
||||||
|
Str("module", "http").
|
||||||
|
Int("code", e.Code)
|
||||||
|
|
||||||
|
message := e.Message
|
||||||
|
if e.InternalMsg != "" {
|
||||||
|
message = e.InternalMsg
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Msg(message)
|
||||||
|
HttpJsonResponse(e.w, e.Code, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
func HttpError(w http.ResponseWriter, code int) *HTTPError {
|
||||||
|
return &HTTPError{
|
||||||
|
Code: code,
|
||||||
|
w: w,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func HttpBadRequest(w http.ResponseWriter) *HTTPError {
|
||||||
|
return HttpError(w, http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
func HttpUnauthorized(w http.ResponseWriter) *HTTPError {
|
||||||
|
return HttpError(w, http.StatusUnauthorized)
|
||||||
|
}
|
||||||
|
|
||||||
|
func HttpForbidden(w http.ResponseWriter) *HTTPError {
|
||||||
|
return HttpError(w, http.StatusForbidden)
|
||||||
|
}
|
||||||
|
|
||||||
|
func HttpNotFound(w http.ResponseWriter) *HTTPError {
|
||||||
|
return HttpError(w, http.StatusNotFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
func HttpUnprocessableEntity(w http.ResponseWriter) *HTTPError {
|
||||||
|
return HttpError(w, http.StatusUnprocessableEntity)
|
||||||
|
}
|
||||||
|
|
||||||
|
func HttpInternalServerError(w http.ResponseWriter, err error) *HTTPError {
|
||||||
|
return HttpError(w, http.StatusInternalServerError).WithInternalErr(err)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user