From 0dab2a99d373df8ca2afa8bc977ab788fb5d64e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ediv=C3=BD?= Date: Mon, 16 Nov 2020 19:37:52 +0100 Subject: [PATCH] introduce REST API authorization. --- internal/api/room/handler.go | 8 ++--- internal/api/router.go | 17 ++--------- internal/http/auth/auth.go | 57 ++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 18 deletions(-) create mode 100644 internal/http/auth/auth.go diff --git a/internal/api/room/handler.go b/internal/api/room/handler.go index af9d327d..f996ee93 100644 --- a/internal/api/room/handler.go +++ b/internal/api/room/handler.go @@ -4,6 +4,7 @@ import ( "github.com/go-chi/chi" "demodesk/neko/internal/types" + "demodesk/neko/internal/http/auth" ) type RoomHandler struct { @@ -27,15 +28,14 @@ func New( } func (h *RoomHandler) Route(r chi.Router) { - // TODO: Authorizaton. r.Route("/screen", func(r chi.Router) { r.Get("/", h.ScreenConfiguration) - r.Post("/", h.ScreenConfigurationChange) - r.Get("/configurations", h.ScreenConfigurationsList) + r.With(auth.AdminsOnly).Post("/", h.ScreenConfigurationChange) + r.With(auth.AdminsOnly).Get("/configurations", h.ScreenConfigurationsList) }) - r.Route("/clipboard", func(r chi.Router) { + r.With(auth.HostsOnly).Route("/clipboard", func(r chi.Router) { r.Get("/", h.ClipboardRead) r.Post("/", h.ClipboardWrite) }) diff --git a/internal/api/router.go b/internal/api/router.go index 0a205ff2..f1cdf64a 100644 --- a/internal/api/router.go +++ b/internal/api/router.go @@ -1,13 +1,13 @@ package api import ( - "context" "net/http" "github.com/go-chi/chi" "demodesk/neko/internal/api/member" "demodesk/neko/internal/api/room" + "demodesk/neko/internal/http/auth" "demodesk/neko/internal/types" "demodesk/neko/internal/utils" "demodesk/neko/internal/config" @@ -19,12 +19,6 @@ type ApiManagerCtx struct { capture types.CaptureManager } -type key int - -const ( - keySessionCtx key = iota -) - func New( sessions types.SessionManager, desktop types.DesktopManager, @@ -49,7 +43,7 @@ func (api *ApiManagerCtx) Route(r chi.Router) { r.Route("/room", roomHandler.Route) r.Get("/test", func(w http.ResponseWriter, r *http.Request) { - session := GetSession(r) + session := auth.GetSession(r) utils.HttpBadRequest(w, "Hi `" + session.ID() + "`, you are authenticated.") }) } @@ -60,12 +54,7 @@ func (api *ApiManagerCtx) Authenticate(next http.Handler) http.Handler { if err != nil { utils.HttpNotAuthenticated(w, err) } else { - ctx := context.WithValue(r.Context(), keySessionCtx, session) - next.ServeHTTP(w, r.WithContext(ctx)) + next.ServeHTTP(w, auth.SetSession(r, session)) } }) } - -func GetSession(r *http.Request) types.Session { - return r.Context().Value(keySessionCtx).(types.Session) -} diff --git a/internal/http/auth/auth.go b/internal/http/auth/auth.go new file mode 100644 index 00000000..d0a9c3a6 --- /dev/null +++ b/internal/http/auth/auth.go @@ -0,0 +1,57 @@ +package auth + +import ( + "context" + "net/http" + + "demodesk/neko/internal/types" + "demodesk/neko/internal/utils" +) + +type key int + +const ( + keySessionCtx key = iota +) + +func SetSession(r *http.Request, session types.Session) *http.Request { + ctx := context.WithValue(r.Context(), keySessionCtx, session) + return r.WithContext(ctx) +} + +func GetSession(r *http.Request) types.Session { + return r.Context().Value(keySessionCtx).(types.Session) +} + +func AdminsOnly(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + session := GetSession(r) + if !session.Admin() { + utils.HttpNotAuthorized(w) + } else { + next.ServeHTTP(w, r) + } + }) +} + +func HostsOnly(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + session := GetSession(r) + if !session.IsHost() { + utils.HttpNotAuthorized(w, "Only host can do this.") + } else { + next.ServeHTTP(w, r) + } + }) +} + +func HostsOrAdminsOnly(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + session := GetSession(r) + if !session.IsHost() && !session.Admin() { + utils.HttpNotAuthorized(w, "Only host can do this.") + } else { + next.ServeHTTP(w, r) + } + }) +}