Skip to content
This repository has been archived by the owner on Jul 18, 2024. It is now read-only.

Missing features from m1k1o/neko #63

Draft
wants to merge 18 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{
"go.formatTool": "goformat",
"go.inferGopath": false,
"go.autocompleteUnimportedPackages": true,
"go.delveConfig": {
Expand Down
4 changes: 2 additions & 2 deletions dev/fmt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
cd "$(dirname "$0")"

if [ "$(docker images -q neko_server_build 2> /dev/null)" == "" ]; then
echo "Image 'neko_server_build' not found. Run ./build first."
exit 1
echo "Image 'neko_server_build' not found. Run ./build first."
exit 1
fi

docker run -it --rm \
Expand Down
4 changes: 2 additions & 2 deletions dev/go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
cd "$(dirname "$0")"

if [ "$(docker images -q neko_server_build 2> /dev/null)" == "" ]; then
echo "Image 'neko_server_build' not found. Run ./build first."
exit 1
echo "Image 'neko_server_build' not found. Run ./build first."
exit 1
fi

docker run -it \
Expand Down
4 changes: 2 additions & 2 deletions dev/lint
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
cd "$(dirname "$0")"

if [ "$(docker images -q neko_server_build 2> /dev/null)" == "" ]; then
echo "Image 'neko_server_build' not found. Run ./build first."
exit 1
echo "Image 'neko_server_build' not found. Run ./build first."
exit 1
fi

#
Expand Down
8 changes: 6 additions & 2 deletions dev/start
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
cd "$(dirname "$0")"

if [ -z "$(docker images -q neko_server_app 2> /dev/null)" ]; then
echo "Image 'neko_server_app' not found. Running ./build first."
./build
echo "Image 'neko_server_app' not found. Running ./build first."
./build
fi

if [ -z $NEKO_PORT ]; then
Expand All @@ -22,6 +22,10 @@ if [ -z $NEKO_NAT1TO1 ]; then
fi
done

if [ -z $NEKO_NAT1TO1 ]; then
NEKO_NAT1TO1=$(hostname -I 2>/dev/null | awk '{print $1}')
fi

if [ -z $NEKO_NAT1TO1 ]; then
NEKO_NAT1TO1=$(hostname -i 2>/dev/null)
fi
Expand Down
29 changes: 21 additions & 8 deletions internal/api/room/control.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"github.com/go-chi/chi"

"github.com/demodesk/neko/pkg/auth"
"github.com/demodesk/neko/pkg/types/event"
"github.com/demodesk/neko/pkg/types/message"
"github.com/demodesk/neko/pkg/utils"
)

Expand Down Expand Up @@ -33,17 +35,26 @@ func (h *RoomHandler) controlStatus(w http.ResponseWriter, r *http.Request) erro
}

func (h *RoomHandler) controlRequest(w http.ResponseWriter, r *http.Request) error {
_, hasHost := h.sessions.GetHost()
session, _ := auth.GetSession(r)
host, hasHost := h.sessions.GetHost()
if hasHost {
return utils.HttpUnprocessableEntity("there is already a host")
// TODO: Some throttling mechanism to prevent spamming.

// let host know that someone wants to take control
host.Send(
event.CONTROL_REQUEST,
message.SessionID{
ID: session.ID(),
})

return utils.HttpError(http.StatusAccepted, "control request sent")
}

session, _ := auth.GetSession(r)
if h.sessions.Settings().LockedControls && !session.Profile().IsAdmin {
return utils.HttpForbidden("controls are locked")
}

h.sessions.SetHost(session)
session.SetAsHost()

return utils.HttpSuccess(w)
}
Expand All @@ -55,19 +66,20 @@ func (h *RoomHandler) controlRelease(w http.ResponseWriter, r *http.Request) err
}

h.desktop.ResetKeys()
h.sessions.ClearHost()
session.ClearHost()

return utils.HttpSuccess(w)
}

func (h *RoomHandler) controlTake(w http.ResponseWriter, r *http.Request) error {
session, _ := auth.GetSession(r)
h.sessions.SetHost(session)
session.SetAsHost()

return utils.HttpSuccess(w)
}

func (h *RoomHandler) controlGive(w http.ResponseWriter, r *http.Request) error {
session, _ := auth.GetSession(r)
sessionId := chi.URLParam(r, "sessionId")

target, ok := h.sessions.Get(sessionId)
Expand All @@ -79,17 +91,18 @@ func (h *RoomHandler) controlGive(w http.ResponseWriter, r *http.Request) error
return utils.HttpBadRequest("target session is not allowed to host")
}

h.sessions.SetHost(target)
target.SetAsHostBy(session)

return utils.HttpSuccess(w)
}

func (h *RoomHandler) controlReset(w http.ResponseWriter, r *http.Request) error {
session, _ := auth.GetSession(r)
_, hasHost := h.sessions.GetHost()

if hasHost {
h.desktop.ResetKeys()
h.sessions.ClearHost()
session.ClearHost()
}

return utils.HttpSuccess(w)
Expand Down
2 changes: 1 addition & 1 deletion internal/api/room/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func New(
}

// generate fallback image for private mode when needed
sessions.OnSettingsChanged(func(new types.Settings, old types.Settings) {
sessions.OnSettingsChanged(func(session types.Session, new, old types.Settings) {
if old.PrivateMode && !new.PrivateMode {
log.Debug().Msg("clearing private mode fallback image")
h.privateModeImage = nil
Expand Down
32 changes: 11 additions & 21 deletions internal/api/room/keyboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,13 @@ import (
"github.com/demodesk/neko/pkg/utils"
)

type KeyboardMapData struct {
types.KeyboardMap
}

type KeyboardModifiersData struct {
types.KeyboardModifiers
}

func (h *RoomHandler) keyboardMapSet(w http.ResponseWriter, r *http.Request) error {
data := &KeyboardMapData{}
if err := utils.HttpJsonRequest(w, r, data); err != nil {
keyboardMap := types.KeyboardMap{}
if err := utils.HttpJsonRequest(w, r, &keyboardMap); err != nil {
return err
}

err := h.desktop.SetKeyboardMap(data.KeyboardMap)
err := h.desktop.SetKeyboardMap(keyboardMap)
if err != nil {
return utils.HttpInternalServerError().WithInternalErr(err)
}
Expand All @@ -30,28 +22,26 @@ func (h *RoomHandler) keyboardMapSet(w http.ResponseWriter, r *http.Request) err
}

func (h *RoomHandler) keyboardMapGet(w http.ResponseWriter, r *http.Request) error {
data, err := h.desktop.GetKeyboardMap()
keyboardMap, err := h.desktop.GetKeyboardMap()
if err != nil {
return utils.HttpInternalServerError().WithInternalErr(err)
}

return utils.HttpSuccess(w, KeyboardMapData{
KeyboardMap: *data,
})
return utils.HttpSuccess(w, keyboardMap)
}

func (h *RoomHandler) keyboardModifiersSet(w http.ResponseWriter, r *http.Request) error {
data := &KeyboardModifiersData{}
if err := utils.HttpJsonRequest(w, r, data); err != nil {
keyboardModifiers := types.KeyboardModifiers{}
if err := utils.HttpJsonRequest(w, r, &keyboardModifiers); err != nil {
return err
}

h.desktop.SetKeyboardModifiers(data.KeyboardModifiers)
h.desktop.SetKeyboardModifiers(keyboardModifiers)
return utils.HttpSuccess(w)
}

func (h *RoomHandler) keyboardModifiersGet(w http.ResponseWriter, r *http.Request) error {
return utils.HttpSuccess(w, KeyboardModifiersData{
KeyboardModifiers: h.desktop.GetKeyboardModifiers(),
})
keyboardModifiers := h.desktop.GetKeyboardModifiers()

return utils.HttpSuccess(w, keyboardModifiers)
}
36 changes: 9 additions & 27 deletions internal/api/room/screen.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,16 @@ import (
"github.com/demodesk/neko/pkg/utils"
)

type ScreenConfigurationPayload struct {
Width int `json:"width"`
Height int `json:"height"`
Rate int16 `json:"rate"`
}

func (h *RoomHandler) screenConfiguration(w http.ResponseWriter, r *http.Request) error {
size := h.desktop.GetScreenSize()
screenSize := h.desktop.GetScreenSize()

return utils.HttpSuccess(w, ScreenConfigurationPayload{
Width: size.Width,
Height: size.Height,
Rate: size.Rate,
})
return utils.HttpSuccess(w, screenSize)
}

func (h *RoomHandler) screenConfigurationChange(w http.ResponseWriter, r *http.Request) error {
data := &ScreenConfigurationPayload{}
auth, _ := auth.GetSession(r)

data := &types.ScreenSize{}
if err := utils.HttpJsonRequest(w, r, data); err != nil {
return err
}
Expand All @@ -43,10 +35,9 @@ func (h *RoomHandler) screenConfigurationChange(w http.ResponseWriter, r *http.R
return utils.HttpUnprocessableEntity("cannot set screen size").WithInternalErr(err)
}

h.sessions.Broadcast(event.SCREEN_UPDATED, message.ScreenSize{
Width: size.Width,
Height: size.Height,
Rate: size.Rate,
h.sessions.Broadcast(event.SCREEN_UPDATED, message.ScreenSizeUpdate{
ID: auth.ID(),
ScreenSize: size,
})

return utils.HttpSuccess(w, data)
Expand All @@ -56,16 +47,7 @@ func (h *RoomHandler) screenConfigurationChange(w http.ResponseWriter, r *http.R
func (h *RoomHandler) screenConfigurationsList(w http.ResponseWriter, r *http.Request) error {
configurations := h.desktop.ScreenConfigurations()

list := make([]ScreenConfigurationPayload, 0, len(configurations))
for _, conf := range configurations {
list = append(list, ScreenConfigurationPayload{
Width: conf.Width,
Height: conf.Height,
Rate: conf.Rate,
})
}

return utils.HttpSuccess(w, list)
return utils.HttpSuccess(w, configurations)
}

func (h *RoomHandler) screenShotGet(w http.ResponseWriter, r *http.Request) error {
Expand Down
22 changes: 18 additions & 4 deletions internal/api/room/settings.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package room

import (
"encoding/json"
"io"
"net/http"

"github.com/demodesk/neko/pkg/auth"
"github.com/demodesk/neko/pkg/types"
"github.com/demodesk/neko/pkg/utils"
)

Expand All @@ -12,13 +16,23 @@ func (h *RoomHandler) settingsGet(w http.ResponseWriter, r *http.Request) error
}

func (h *RoomHandler) settingsSet(w http.ResponseWriter, r *http.Request) error {
settings := h.sessions.Settings()
session, _ := auth.GetSession(r)

if err := utils.HttpJsonRequest(w, r, &settings); err != nil {
return err
// We read the request body first and unmashal it inside the UpdateSettingsFunc
// to ensure atomicity of the operation.
body, err := io.ReadAll(r.Body)
if err != nil {
return utils.HttpBadRequest("unable to read request body").WithInternalErr(err)
}

h.sessions.UpdateSettings(settings)
h.sessions.UpdateSettingsFunc(session, func(settings *types.Settings) bool {
err = json.Unmarshal(body, settings)
return err == nil
})

if err != nil {
return utils.HttpBadRequest("unable to parse provided data").WithInternalErr(err)
}

return utils.HttpSuccess(w)
}
5 changes: 4 additions & 1 deletion internal/api/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/demodesk/neko/internal/api/members"
"github.com/demodesk/neko/internal/api/room"
"github.com/demodesk/neko/internal/api/sessions"
"github.com/demodesk/neko/pkg/auth"
"github.com/demodesk/neko/pkg/types"
"github.com/demodesk/neko/pkg/utils"
Expand Down Expand Up @@ -45,7 +46,9 @@ func (api *ApiManagerCtx) Route(r types.Router) {

r.Post("/logout", api.Logout)
r.Get("/whoami", api.Whoami)
r.Get("/sessions", api.Sessions)

sessionsHandler := sessions.New(api.sessions)
r.Route("/sessions", sessionsHandler.Route)

membersHandler := members.New(api.members)
r.Route("/members", membersHandler.Route)
Expand Down
15 changes: 2 additions & 13 deletions internal/api/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ func (api *ApiManagerCtx) Login(w http.ResponseWriter, r *http.Request) error {
return utils.HttpUnprocessableEntity("session already connected")
} else if errors.Is(err, types.ErrMemberDoesNotExist) || errors.Is(err, types.ErrMemberInvalidPassword) {
return utils.HttpUnauthorized().WithInternalErr(err)
} else if errors.Is(err, types.ErrSessionLoginsLocked) {
return utils.HttpForbidden("logins are locked").WithInternalErr(err)
} else {
return utils.HttpInternalServerError().WithInternalErr(err)
}
Expand Down Expand Up @@ -81,16 +83,3 @@ func (api *ApiManagerCtx) Whoami(w http.ResponseWriter, r *http.Request) error {
State: session.State(),
})
}

func (api *ApiManagerCtx) Sessions(w http.ResponseWriter, r *http.Request) error {
sessions := []SessionDataPayload{}
for _, session := range api.sessions.List() {
sessions = append(sessions, SessionDataPayload{
ID: session.ID(),
Profile: session.Profile(),
State: session.State(),
})
}

return utils.HttpSuccess(w, sessions)
}
Loading
Loading